2
/* $Id: csv.php 9606 2006-10-26 07:37:48Z nijel $ */
3
// vim: expandtab sw=4 ts=4 sts=4:
5
/* CSV import plugin for phpMyAdmin */
7
if ($plugin_param == 'table') {
8
if (isset($plugin_list)) {
9
$plugin_list['csv'] = array(
13
array('type' => 'bool', 'name' => 'replace', 'text' => 'strReplaceTable'),
14
array('type' => 'bool', 'name' => 'ignore', 'text' => 'strIgnoreDuplicates'),
15
array('type' => 'text', 'name' => 'terminated', 'text' => 'strFieldsTerminatedBy', 'size' => 2, 'len' => 2),
16
array('type' => 'text', 'name' => 'enclosed', 'text' => 'strFieldsEnclosedBy', 'size' => 2, 'len' => 2),
17
array('type' => 'text', 'name' => 'escaped', 'text' => 'strFieldsEscapedBy', 'size' => 2, 'len' => 2),
18
array('type' => 'text', 'name' => 'new_line', 'text' => 'strLinesTerminatedBy', 'size' => 2),
19
array('type' => 'text', 'name' => 'columns', 'text' => 'strColumnNames'),
21
'options_text' => 'strCSVImportOptions',
24
/* We do not define function when plugin is just queried for information above */
25
$replacements = array(
30
$csv_terminated = strtr($csv_terminated, $replacements);
31
$csv_enclosed = strtr($csv_enclosed, $replacements);
32
$csv_escaped = strtr($csv_escaped, $replacements);
33
$csv_new_line = strtr($csv_new_line, $replacements);
35
if (strlen($csv_terminated) != 1) {
36
$message = sprintf($strInvalidCSVParameter, $strFieldsTerminatedBy);
37
$show_error_header = TRUE;
39
} elseif (strlen($csv_enclosed) != 1) {
40
$message = sprintf($strInvalidCSVParameter, $strFieldsEnclosedBy);
41
$show_error_header = TRUE;
43
} elseif (strlen($csv_escaped) != 1) {
44
$message = sprintf($strInvalidCSVParameter, $strFieldsEscapedBy);
45
$show_error_header = TRUE;
47
} elseif (strlen($csv_new_line) != 1 && $csv_new_line != 'auto') {
48
$message = sprintf($strInvalidCSVParameter, $strLinesTerminatedBy);
49
$show_error_header = TRUE;
54
if (isset($csv_replace)) {
55
$sql_template = 'REPLACE';
57
$sql_template = 'INSERT';
58
if (isset($csv_ignore)) {
59
$sql_template .= ' IGNORE';
62
$sql_template .= ' INTO ' . PMA_backquote($table);
64
$tmp_fields = PMA_DBI_get_fields($db, $table);
66
if (empty($csv_columns)) {
67
$fields = $tmp_fields;
69
$sql_template .= ' (';
71
$tmp = split(',( ?)', $csv_columns);
72
foreach ($tmp as $key => $val) {
73
if (count($fields) > 0) {
74
$sql_template .= ', ';
78
foreach ($tmp_fields as $id => $field) {
79
if ($field['Field'] == $val) {
85
$message = sprintf($strInvalidColumn, $val);
86
$show_error_header = TRUE;
91
$sql_template .= PMA_backquote($val);
93
$sql_template .= ') ';
96
$required_fields = count($fields);
98
$sql_template .= ' VALUES (';
100
// Defaults for parser
108
while (!($finished && $i >= $len) && !$error && !$timeout_passed) {
109
$data = PMA_importGetNextChunk();
110
if ($data === FALSE) {
111
// subtract data we didn't handle yet and stop processing
112
$offset -= strlen($buffer);
114
} elseif ($data === TRUE) {
115
// Handle rest of buffer
117
// Append new data to buffer
119
// Do not parse string when we're not at the end and don't have new line inside
120
if (($csv_new_line == 'auto' && strpos($buffer, "\r") === FALSE && strpos($buffer, "\n") === FALSE)
121
|| ($csv_new_line != 'auto' && strpos($buffer, $csv_new_line) === FALSE)) {
126
// Current length of our buffer
127
$len = strlen($buffer);
128
// Currently parsed char
131
// Deadlock protection
132
if ($lasti == $i && $lastlen == $len) {
133
$message = sprintf($strInvalidCSVFormat, $line);
134
$show_error_header = TRUE;
141
// This can happen with auto EOL and \r at the end of buffer
144
if ($ch == $csv_terminated) {
145
if ($i == $len - 1) {
156
if ($ch == $csv_enclosed) {
157
if ($i == $len - 1) {
168
while (($need_end && $ch != $csv_enclosed) || (!$need_end && !($ch == $csv_terminated || $ch == $csv_new_line || ($csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n"))))) {
169
if ($ch == $csv_escaped) {
170
if ($i == $len - 1) {
178
if ($i == $len - 1) {
192
// Need to strip trailing enclosing char?
193
if ($need_end && $ch == $csv_enclosed) {
194
if ($finished && $i == $len - 1) {
196
} elseif ($i == $len - 1) {
205
// Are we at the end?
206
if ($ch == $csv_new_line || ($csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n")) || ($finished && $i == $len - 1)) {
210
if ($ch == $csv_terminated) {
211
if ($i == $len - 1) {
219
// If everything went okay, store value
224
if ($csv_finish || $ch == $csv_new_line || ($csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n"))) {
225
if ($csv_new_line == 'auto' && $ch == "\r") { // Handle "\r\n"
226
if ($i >= ($len - 2) && !$finished) {
227
break; // We need more data to decide new line
229
if ($buffer[$i + 1] == "\n") {
233
// We didn't parse value till the end of line, so there was empty one
237
// Do we have correct count of values?
238
if (count($values) != $required_fields) {
240
if ($values[count($values) - 1] == ';') {
241
unset($values[count($values) - 1]);
243
$message = sprintf($strInvalidCSVFieldCount, $line);
244
$show_error_header = TRUE;
251
$sql = $sql_template;
252
foreach ($values as $key => $val) {
256
$sql .= '\'' . addslashes($val) . '\'';
262
* @todo maybe we could add original line to verbose SQL in comment
264
PMA_importRunQuery($sql, $sql);
268
$buffer = substr($buffer, $i + 1);
269
$len = strlen($buffer);
274
} // End of parser loop
275
} // End of import loop
277
// Commit any possible data in buffers
278
PMA_importRunQuery();
280
if (count($values) != 0 && !$error) {
281
$message = sprintf($strInvalidCSVFormat, $line);
282
$show_error_header = TRUE;