Passed
Pull Request — develop (#92)
by Felipe
04:47
created

src/controllers/DataexportController.php (2 issues)

1
<?php
2
0 ignored issues
show
You must use "/**" style comments for a file comment
Loading history...
3
/*
4
 * PHPPgAdmin v6.0.0-beta.30
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
/**
10
 * Base controller class.
11
 */
12
class DataexportController extends BaseController
13
{
14
    public $controller_name = 'DataexportController';
15
    public $extensions      = [
16
        'sql'  => 'sql',
17
        'copy' => 'sql',
18
        'csv'  => 'csv',
19
        'tab'  => 'txt',
20
        'html' => 'html',
21
        'xml'  => 'xml',
22
    ];
23
24
    /**
25
     * Default method to render the controller according to the action parameter.
26
     */
27
    public function render()
28
    {
29
        $conf = $this->conf;
30
31
        $lang   = $this->lang;
1 ignored issue
show
The assignment to $lang is dead and can be removed.
Loading history...
32
        $data   = $this->misc->getDatabaseAccessor();
33
        $action = $this->action;
34
35
        set_time_limit(0);
36
37
        // if (!isset($_REQUEST['table']) && !isset($_REQUEST['query']))
38
        // What must we do in this case? Maybe redirect to the homepage?
39
40
        // If format is set, then perform the export
41
        if (isset($_REQUEST['what'])) {
42
            $this->prtrace("REQUEST['what']", $_REQUEST['what']);
43
44
            // Include application functions
45
            $this->setNoOutput(true);
46
47
            switch ($_REQUEST['what']) {
48
                case 'dataonly':
49
                    // Check to see if they have pg_dump set up and if they do, use that
50
                    // instead of custom dump code
51
                    if ($this->misc->isDumpEnabled() && ('copy' == $_REQUEST['d_format'] || 'sql' == $_REQUEST['d_format'])) {
52
                        $this->prtrace('DUMP ENABLED, d_format is', $_REQUEST['d_format']);
53
                        $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
54
55
                        return $dbexport_controller->render();
56
                    }
57
                    $this->prtrace('d_format is', $_REQUEST['d_format'], 'd_oids is', isset($_REQUEST['d_oids']));
58
                    $format = $_REQUEST['d_format'];
59
                    $oids   = isset($_REQUEST['d_oids']);
60
61
                    break;
62
                case 'structureonly':
63
                    // Check to see if they have pg_dump set up and if they do, use that
64
                    // instead of custom dump code
65
                    if ($this->misc->isDumpEnabled()) {
66
                        $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
67
68
                        return $dbexport_controller->render();
69
                    }
70
                    $clean = isset($_REQUEST['s_clean']);
71
72
                    break;
73
                case 'structureanddata':
74
                    // Check to see if they have pg_dump set up and if they do, use that
75
                    // instead of custom dump code
76
                    if ($this->misc->isDumpEnabled()) {
77
                        $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
78
79
                        return $dbexport_controller->render();
80
                    }
81
                    $format = $_REQUEST['sd_format'];
82
                    $clean  = isset($_REQUEST['sd_clean']);
83
                    $oids   = isset($_REQUEST['sd_oids']);
84
85
                    break;
86
            }
87
88
            // Make it do a download, if necessary
89
            if ('download' == $_REQUEST['output']) {
90
                // Set headers.  MSIE is totally broken for SSL downloading, so
91
                // we need to have it download in-place as plain text
92
                if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS'])) {
93
                    header('Content-Type: text/plain');
94
                } else {
95
                    header('Content-Type: application/download');
96
97
                    if (isset($extensions[$format])) {
98
                        $ext = $extensions[$format];
99
                    } else {
100
                        $ext = 'txt';
101
                    }
102
103
                    header('Content-Disposition: attachment; filename=dump.'.$ext);
104
                }
105
            } else {
106
                header('Content-Type: text/plain');
107
            }
108
109
            if (isset($_REQUEST['query'])) {
110
                $_REQUEST['query'] = trim(urldecode($_REQUEST['query']));
111
            }
112
113
            // Set the schema search path
114
            if (isset($_REQUEST['search_path'])) {
115
                $data->setSearchPath(array_map('trim', explode(',', $_REQUEST['search_path'])));
116
            }
117
118
            // Set up the dump transaction
119
            $status = $data->beginDump();
120
121
            // If the dump is not dataonly then dump the structure prefix
122
            if ('dataonly' != $_REQUEST['what']) {
123
                echo $data->getTableDefPrefix($_REQUEST['table'], $clean);
124
            }
125
126
            // If the dump is not structureonly then dump the actual data
127
            if ('structureonly' != $_REQUEST['what']) {
128
                // Get database encoding
129
                $dbEncoding = $data->getDatabaseEncoding();
130
131
                // Set fetch mode to NUM so that duplicate field names are properly returned
132
                $data->conn->setFetchMode(ADODB_FETCH_NUM);
133
134
                // Execute the query, if set, otherwise grab all rows from the table
135
                if (isset($_REQUEST['table'])) {
136
                    $rs = $data->dumpRelation($_REQUEST['table'], $oids);
137
                } else {
138
                    $rs = $data->conn->Execute($_REQUEST['query']);
139
                }
140
141
                if ('copy' == $format) {
142
                    $data->fieldClean($_REQUEST['table']);
143
                    echo "COPY \"{$_REQUEST['table']}\"";
144
                    if ($oids) {
145
                        echo ' WITH OIDS';
146
                    }
147
148
                    echo " FROM stdin;\n";
149
                    while (!$rs->EOF) {
150
                        $first = true;
151
                        while (list($k, $v) = each($rs->fields)) {
152
                            // Escape value
153
                            $v = $data->escapeBytea($v);
154
155
                            // We add an extra escaping slash onto octal encoded characters
156
                            $v = preg_replace('/\\\\([0-7]{3})/', '\\\\\1', $v);
157
                            if ($first) {
158
                                echo (is_null($v)) ? '\\N' : $v;
159
                                $first = false;
160
                            } else {
161
                                echo "\t", (is_null($v)) ? '\\N' : $v;
162
                            }
163
                        }
164
                        echo "\n";
165
                        $rs->moveNext();
166
                    }
167
                    echo "\\.\n";
168
                } elseif ('html' == $format) {
169
                    echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n";
170
                    echo "<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n";
171
                    echo "<head>\r\n";
172
                    echo "\t<title></title>\r\n";
173
                    echo "\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\r\n";
174
                    echo "</head>\r\n";
175
                    echo "<body>\r\n";
176
                    echo "<table class=\"phppgadmin\">\r\n";
177
                    echo "\t<tr>\r\n";
178
                    if (!$rs->EOF) {
179
                        // Output header row
180
                        $j = 0;
181
                        foreach ($rs->fields as $k => $v) {
182
                            $finfo = $rs->fetchField($j++);
183
                            if ($finfo->name == $data->id && !$oids) {
184
                                continue;
185
                            }
186
187
                            echo "\t\t<th>", $this->misc->printVal($finfo->name, true), "</th>\r\n";
188
                        }
189
                    }
190
                    echo "\t</tr>\r\n";
191
                    while (!$rs->EOF) {
192
                        echo "\t<tr>\r\n";
193
                        $j = 0;
194
                        foreach ($rs->fields as $k => $v) {
195
                            $finfo = $rs->fetchField($j++);
196
                            if ($finfo->name == $data->id && !$oids) {
197
                                continue;
198
                            }
199
200
                            echo "\t\t<td>", $this->misc->printVal($v, true, $finfo->type), "</td>\r\n";
201
                        }
202
                        echo "\t</tr>\r\n";
203
                        $rs->moveNext();
204
                    }
205
                    echo "</table>\r\n";
206
                    echo "</body>\r\n";
207
                    echo "</html>\r\n";
208
                } elseif ('xml' == $format) {
209
                    echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
210
                    echo "<data>\n";
211
                    if (!$rs->EOF) {
212
                        // Output header row
213
                        $j = 0;
214
                        echo "\t<header>\n";
215
                        foreach ($rs->fields as $k => $v) {
216
                            $finfo = $rs->fetchField($j++);
217
                            $name  = htmlspecialchars($finfo->name);
218
                            $type  = htmlspecialchars($finfo->type);
219
                            echo "\t\t<column name=\"{$name}\" type=\"{$type}\" />\n";
220
                        }
221
                        echo "\t</header>\n";
222
                    }
223
                    echo "\t<records>\n";
224
                    while (!$rs->EOF) {
225
                        $j = 0;
226
                        echo "\t\t<row>\n";
227
                        foreach ($rs->fields as $k => $v) {
228
                            $finfo = $rs->fetchField($j++);
229
                            $name  = htmlspecialchars($finfo->name);
230
                            if (!is_null($v)) {
231
                                $v = htmlspecialchars($v);
232
                            }
233
234
                            echo "\t\t\t<column name=\"{$name}\"", (is_null($v) ? ' null="null"' : ''), ">{$v}</column>\n";
235
                        }
236
                        echo "\t\t</row>\n";
237
                        $rs->moveNext();
238
                    }
239
                    echo "\t</records>\n";
240
                    echo "</data>\n";
241
                } elseif ('sql' == $format) {
242
                    $data->fieldClean($_REQUEST['table']);
243
                    while (!$rs->EOF) {
244
                        echo "INSERT INTO \"{$_REQUEST['table']}\" (";
245
                        $first = true;
246
                        $j     = 0;
247
                        foreach ($rs->fields as $k => $v) {
248
                            $finfo = $rs->fetchField($j++);
249
                            $k     = $finfo->name;
250
                            // SQL (INSERT) format cannot handle oids
251
                            //                        if ($k == $data->id) continue;
252
                            // Output field
253
                            $data->fieldClean($k);
254
                            if ($first) {
255
                                echo "\"{$k}\"";
256
                            } else {
257
                                echo ", \"{$k}\"";
258
                            }
259
260
                            if (!is_null($v)) {
261
                                // Output value
262
                                // addCSlashes converts all weird ASCII characters to octal representation,
263
                                // EXCEPT the 'special' ones like \r \n \t, etc.
264
                                $v = addcslashes($v, "\0..\37\177..\377");
265
                                // We add an extra escaping slash onto octal encoded characters
266
                                $v = preg_replace('/\\\\([0-7]{3})/', '\\\1', $v);
267
                                // Finally, escape all apostrophes
268
                                $v = str_replace("'", "''", $v);
269
                            }
270
                            if ($first) {
271
                                $values = (is_null($v) ? 'NULL' : "'{$v}'");
272
                                $first  = false;
273
                            } else {
274
                                $values .= ', '.((is_null($v) ? 'NULL' : "'{$v}'"));
275
                            }
276
                        }
277
                        echo ") VALUES ({$values});\n";
278
                        $rs->moveNext();
279
                    }
280
                } else {
281
                    switch ($format) {
282
                        case 'tab':
283
                            $sep = "\t";
284
285
                            break;
286
                        case 'csv':
287
                        default:
288
                            $sep = ',';
289
290
                            break;
291
                    }
292
                    if (!$rs->EOF) {
293
                        // Output header row
294
                        $first = true;
295
                        foreach ($rs->fields as $k => $v) {
296
                            $finfo = $rs->fetchField($k);
297
                            $v     = $finfo->name;
298
                            if (!is_null($v)) {
299
                                $v = str_replace('"', '""', $v);
300
                            }
301
302
                            if ($first) {
303
                                echo "\"{$v}\"";
304
                                $first = false;
305
                            } else {
306
                                echo "{$sep}\"{$v}\"";
307
                            }
308
                        }
309
                        echo "\r\n";
310
                    }
311
                    while (!$rs->EOF) {
312
                        $first = true;
313
                        foreach ($rs->fields as $k => $v) {
314
                            if (!is_null($v)) {
315
                                $v = str_replace('"', '""', $v);
316
                            }
317
318
                            if ($first) {
319
                                echo (is_null($v)) ? '"\\N"' : "\"{$v}\"";
320
                                $first = false;
321
                            } else {
322
                                echo is_null($v) ? "{$sep}\"\\N\"" : "{$sep}\"{$v}\"";
323
                            }
324
                        }
325
                        echo "\r\n";
326
                        $rs->moveNext();
327
                    }
328
                }
329
            }
330
331
            // If the dump is not dataonly then dump the structure suffix
332
            if ('dataonly' != $_REQUEST['what']) {
333
                // Set fetch mode back to ASSOC for the table suffix to work
334
                $data->conn->setFetchMode(ADODB_FETCH_ASSOC);
335
                echo $data->getTableDefSuffix($_REQUEST['table']);
336
            }
337
338
            // Finish the dump transaction
339
            $status = $data->endDump();
340
        } else {
341
            return $this->doDefault();
342
        }
343
    }
344
345
    public function doDefault($msg = '')
346
    {
347
        $conf = $this->conf;
348
349
        $lang   = $this->lang;
350
        $data   = $this->misc->getDatabaseAccessor();
351
        $action = $this->action;
352
353
        if (!isset($_REQUEST['query']) or empty($_REQUEST['query'])) {
354
            $_REQUEST['query'] = $_SESSION['sqlquery'];
355
        }
356
357
        $this->printHeader($lang['strexport']);
358
        $this->printBody();
359
        $this->printTrail(isset($_REQUEST['subject']) ? $_REQUEST['subject'] : 'database');
360
        $this->printTitle($lang['strexport']);
361
        if (isset($msg)) {
362
            $this->printMsg($msg);
363
        }
364
365
        echo '<form action="'.\SUBFOLDER."/src/views/dataexport.php\" method=\"post\">\n";
366
        echo "<table>\n";
367
        echo "<tr><th class=\"data\">{$lang['strformat']}:</th><td><select name=\"d_format\">\n";
368
        // COPY and SQL require a table
369
        if (isset($_REQUEST['table'])) {
370
            echo "<option value=\"copy\">COPY</option>\n";
371
            echo "<option value=\"sql\">SQL</option>\n";
372
        }
373
        echo "<option value=\"csv\">CSV</option>\n";
374
        echo "<option value=\"tab\">{$lang['strtabbed']}</option>\n";
375
        echo "<option value=\"html\">XHTML</option>\n";
376
        echo "<option value=\"xml\">XML</option>\n";
377
        echo '</select></td></tr>';
378
        echo "</table>\n";
379
380
        echo "<h3>{$lang['stroptions']}</h3>\n";
381
        echo "<p><input type=\"radio\" id=\"output1\" name=\"output\" value=\"show\" checked=\"checked\" /><label for=\"output1\">{$lang['strshow']}</label>\n";
382
        echo "<br/><input type=\"radio\" id=\"output2\" name=\"output\" value=\"download\" /><label for=\"output2\">{$lang['strdownload']}</label></p>\n";
383
384
        echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
385
        echo "<input type=\"hidden\" name=\"what\" value=\"dataonly\" />\n";
386
        if (isset($_REQUEST['table'])) {
387
            echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), "\" />\n";
388
        }
389
        echo '<input type="hidden" name="query" value="', htmlspecialchars(urlencode($_REQUEST['query'])), "\" />\n";
390
        if (isset($_REQUEST['search_path'])) {
391
            echo '<input type="hidden" name="search_path" value="', htmlspecialchars($_REQUEST['search_path']), "\" />\n";
392
        }
393
        echo $this->misc->form;
394
        echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
395
        echo "</form>\n";
396
397
        $this->printFooter();
398
    }
399
}
400