1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* Does an import to a particular table from a text file
|
5
|
*
|
6
|
* $Id: dataimport.php,v 1.10 2005/10/09 09:05:16 chriskl Exp $
|
7
|
*/
|
8
|
|
9
|
// Prevent timeouts on large exports (non-safe mode only)
|
10
|
if (!ini_get('safe_mode')) set_time_limit(0);
|
11
|
|
12
|
// Include application functions
|
13
|
include_once('./libraries/lib.inc.php');
|
14
|
|
15
|
// Default state for XML parser
|
16
|
$state = 'XML';
|
17
|
$curr_col_name = null;
|
18
|
$curr_col_val = null;
|
19
|
$curr_col_null = false;
|
20
|
$curr_row = array();
|
21
|
|
22
|
/**
|
23
|
* Open tag handler for XML import feature
|
24
|
*/
|
25
|
function _startElement($parser, $name, $attrs) {
|
26
|
global $data, $misc, $lang;
|
27
|
global $state, $curr_row, $curr_col_name, $curr_col_val, $curr_col_null;
|
28
|
|
29
|
switch ($name) {
|
30
|
case 'DATA':
|
31
|
if ($state != 'XML') {
|
32
|
$data->rollbackTransaction();
|
33
|
$misc->printMsg($lang['strimporterror']);
|
34
|
exit;
|
35
|
}
|
36
|
$state = 'DATA';
|
37
|
break;
|
38
|
case 'HEADER':
|
39
|
if ($state != 'DATA') {
|
40
|
$data->rollbackTransaction();
|
41
|
$misc->printMsg($lang['strimporterror']);
|
42
|
exit;
|
43
|
}
|
44
|
$state = 'HEADER';
|
45
|
break;
|
46
|
case 'RECORDS':
|
47
|
if ($state != 'READ_HEADER') {
|
48
|
$data->rollbackTransaction();
|
49
|
$misc->printMsg($lang['strimporterror']);
|
50
|
exit;
|
51
|
}
|
52
|
$state = 'RECORDS';
|
53
|
break;
|
54
|
case 'ROW':
|
55
|
if ($state != 'RECORDS') {
|
56
|
$data->rollbackTransaction();
|
57
|
$misc->printMsg($lang['strimporterror']);
|
58
|
exit;
|
59
|
}
|
60
|
$state = 'ROW';
|
61
|
$curr_row = array();
|
62
|
break;
|
63
|
case 'COLUMN':
|
64
|
// We handle columns in rows
|
65
|
if ($state == 'ROW') {
|
66
|
$state = 'COLUMN';
|
67
|
$curr_col_name = $attrs['NAME'];
|
68
|
$curr_col_null = isset($attrs['NULL']);
|
69
|
}
|
70
|
// And we ignore columns in headers and fail in any other context
|
71
|
elseif ($state != 'HEADER') {
|
72
|
$data->rollbackTransaction();
|
73
|
$misc->printMsg($lang['strimporterror']);
|
74
|
exit;
|
75
|
}
|
76
|
break;
|
77
|
default:
|
78
|
// An unrecognised tag means failure
|
79
|
$data->rollbackTransaction();
|
80
|
$misc->printMsg($lang['strimporterror']);
|
81
|
exit;
|
82
|
}
|
83
|
}
|
84
|
|
85
|
/**
|
86
|
* Close tag handler for XML import feature
|
87
|
*/
|
88
|
function _endElement($parser, $name) {
|
89
|
global $data, $misc, $lang;
|
90
|
global $state, $curr_row, $curr_col_name, $curr_col_val, $curr_col_null;
|
91
|
|
92
|
switch ($name) {
|
93
|
case 'DATA':
|
94
|
$state = 'READ_DATA';
|
95
|
break;
|
96
|
case 'HEADER':
|
97
|
$state = 'READ_HEADER';
|
98
|
break;
|
99
|
case 'RECORDS':
|
100
|
$state = 'READ_RECORDS';
|
101
|
break;
|
102
|
case 'ROW':
|
103
|
// Build value map in order to insert row into table
|
104
|
$vars = array();
|
105
|
$nulls = array();
|
106
|
$format = array();
|
107
|
$types = array();
|
108
|
foreach ($curr_row as $k => $v) {
|
109
|
// Check for nulls
|
110
|
if ($v === null) $nulls[$k] = 'on';
|
111
|
// Add to value array
|
112
|
$vars[$k] = $v;
|
113
|
// Format is always VALUE
|
114
|
$format[$k] = 'VALUE';
|
115
|
// Type is always text
|
116
|
$types[$k] = 'text';
|
117
|
}
|
118
|
$status = $data->insertRow($_REQUEST['table'], $vars, $nulls, $format, $types);
|
119
|
if ($status != 0) {
|
120
|
$data->rollbackTransaction();
|
121
|
$misc->printMsg($lang['strimporterror']);
|
122
|
exit;
|
123
|
}
|
124
|
$curr_row = array();
|
125
|
$state = 'RECORDS';
|
126
|
break;
|
127
|
case 'COLUMN':
|
128
|
$curr_row[$curr_col_name] = ($curr_col_null ? null : $curr_col_val);
|
129
|
$curr_col_name = null;
|
130
|
$curr_col_val = null;
|
131
|
$curr_col_null = false;
|
132
|
$state = 'ROW';
|
133
|
break;
|
134
|
default:
|
135
|
// An unrecognised tag means failure
|
136
|
$data->rollbackTransaction();
|
137
|
$misc->printMsg($lang['strimporterror']);
|
138
|
exit;
|
139
|
}
|
140
|
}
|
141
|
|
142
|
/**
|
143
|
* Character data handler for XML import feature
|
144
|
*/
|
145
|
function _charHandler($parser, $cdata) {
|
146
|
global $data, $misc, $lang;
|
147
|
global $state, $curr_col_val;
|
148
|
|
149
|
if ($state == 'COLUMN') {
|
150
|
$curr_col_val .= $cdata;
|
151
|
}
|
152
|
}
|
153
|
|
154
|
function loadNULLArray() {
|
155
|
$array = array();
|
156
|
if (isset($_POST['allowednulls'])) {
|
157
|
foreach($_POST['allowednulls'] as $null_char) {
|
158
|
switch ($null_char) {
|
159
|
case 'default':
|
160
|
$array[] = "\\N";
|
161
|
break;
|
162
|
case 'null':
|
163
|
$array[] = "NULL";
|
164
|
break;
|
165
|
case 'emptystring':
|
166
|
$array[] = null;
|
167
|
break;
|
168
|
}
|
169
|
}
|
170
|
}
|
171
|
return $array;
|
172
|
}
|
173
|
|
174
|
function determineNull($field, $null_array) {
|
175
|
return in_array($field, $null_array);
|
176
|
}
|
177
|
|
178
|
$misc->printHeader($lang['strimport']);
|
179
|
$misc->printTrail('table');
|
180
|
$misc->printTabs('table','import');
|
181
|
|
182
|
// Check that file is specified and is an uploaded file
|
183
|
if (isset($_FILES['source']) && is_uploaded_file($_FILES['source']['tmp_name']) && is_readable($_FILES['source']['tmp_name'])) {
|
184
|
|
185
|
$fd = fopen($_FILES['source']['tmp_name'], 'r');
|
186
|
// Check that file was opened successfully
|
187
|
if ($fd !== false) {
|
188
|
$null_array = loadNULLArray();
|
189
|
$status = $data->beginTransaction();
|
190
|
if ($status != 0) {
|
191
|
$misc->printMsg($lang['strimporterror']);
|
192
|
exit;
|
193
|
}
|
194
|
|
195
|
// If format is set to 'auto', then determine format automatically from file name
|
196
|
if ($_REQUEST['format'] == 'auto') {
|
197
|
$extension = substr(strrchr($_FILES['source']['name'], '.'), 1);
|
198
|
switch ($extension) {
|
199
|
case 'csv':
|
200
|
$_REQUEST['format'] = 'csv';
|
201
|
break;
|
202
|
case 'txt':
|
203
|
$_REQUEST['format'] = 'tab';
|
204
|
break;
|
205
|
case 'xml':
|
206
|
$_REQUEST['format'] = 'xml';
|
207
|
break;
|
208
|
default:
|
209
|
$data->rollbackTransaction();
|
210
|
$misc->printMsg($lang['strimporterror-fileformat']);
|
211
|
exit;
|
212
|
}
|
213
|
}
|
214
|
|
215
|
// Do different import technique depending on file format
|
216
|
switch ($_REQUEST['format']) {
|
217
|
case 'csv':
|
218
|
case 'tab':
|
219
|
// XXX: Length of CSV lines limited to 100k
|
220
|
$csv_max_line = 100000;
|
221
|
// Set delimiter to tabs or commas
|
222
|
if ($_REQUEST['format'] == 'csv') $csv_delimiter = ',';
|
223
|
else $csv_delimiter = "\t";
|
224
|
// Get first line of field names
|
225
|
$fields = fgetcsv($fd, $csv_max_line, $csv_delimiter);
|
226
|
$row = 2; //We start on the line AFTER the field names
|
227
|
while ($line = fgetcsv($fd, $csv_max_line, $csv_delimiter)) {
|
228
|
// Build value map
|
229
|
$vars = array();
|
230
|
$nulls = array();
|
231
|
$format = array();
|
232
|
$types = array();
|
233
|
$i = 0;
|
234
|
foreach ($fields as $f) {
|
235
|
// Check that there is a column
|
236
|
if (!isset($line[$i])) {
|
237
|
$misc->printMsg(sprintf($lang['strimporterrorline-badcolumnnum'], $row));
|
238
|
exit;
|
239
|
}
|
240
|
// Check for nulls
|
241
|
if (determineNull($line[$i], $null_array)) {
|
242
|
$nulls[$f] = 'on';
|
243
|
}
|
244
|
// Add to value array
|
245
|
$vars[$f] = $line[$i];
|
246
|
// Format is always VALUE
|
247
|
$format[$f] = 'VALUE';
|
248
|
// Type is always text
|
249
|
$types[$f] = 'text';
|
250
|
$i++;
|
251
|
}
|
252
|
|
253
|
$status = $data->insertRow($_REQUEST['table'], $vars, $nulls, $format, $types);
|
254
|
if ($status != 0) {
|
255
|
$data->rollbackTransaction();
|
256
|
$misc->printMsg(sprintf($lang['strimporterrorline'], $row));
|
257
|
exit;
|
258
|
}
|
259
|
$row++;
|
260
|
}
|
261
|
break;
|
262
|
case 'xml':
|
263
|
$parser = xml_parser_create();
|
264
|
xml_set_element_handler($parser, '_startElement', '_endElement');
|
265
|
xml_set_character_data_handler($parser, '_charHandler');
|
266
|
|
267
|
while (!feof($fd)) {
|
268
|
$line = fgets($fd, 4096);
|
269
|
xml_parse($parser, $line);
|
270
|
}
|
271
|
|
272
|
xml_parser_free($parser);
|
273
|
break;
|
274
|
default:
|
275
|
// Unknown type
|
276
|
$data->rollbackTransaction();
|
277
|
$misc->printMsg($lang['strinvalidparam']);
|
278
|
exit;
|
279
|
}
|
280
|
|
281
|
$status = $data->endTransaction();
|
282
|
if ($status != 0) {
|
283
|
$misc->printMsg($lang['strimporterror']);
|
284
|
exit;
|
285
|
}
|
286
|
fclose($fd);
|
287
|
|
288
|
$misc->printMsg($lang['strfileimported']);
|
289
|
}
|
290
|
else {
|
291
|
// File could not be opened
|
292
|
$misc->printMsg($lang['strimporterror']);
|
293
|
}
|
294
|
}
|
295
|
else {
|
296
|
// Upload went wrong
|
297
|
$misc->printMsg($lang['strimporterror-uploadedfile']);
|
298
|
}
|
299
|
|
300
|
$misc->printFooter();
|
301
|
|
302
|
?>
|