Fix for the Open in New Window in Patient/Client->Patients search gui, take 2.
[openemr.git] / phpmyadmin / libraries / import / sql.php
blob28021066103c98d6e8dcbeda3d682e9fc1476791
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * SQL import plugin for phpMyAdmin
6 * @version $Id$
7 */
8 if (! defined('PHPMYADMIN')) {
9 exit;
12 /**
15 if (isset($plugin_list)) {
16 $plugin_list['sql'] = array(
17 'text' => 'strSQL',
18 'extension' => 'sql',
19 'options_text' => 'strOptions',
21 $compats = PMA_DBI_getCompatibilities();
22 if (count($compats) > 0) {
23 $values = array();
24 foreach($compats as $val) {
25 $values[$val] = $val;
27 $plugin_list['sql']['options'] = array(
28 array('type' => 'select', 'name' => 'compatibility', 'text' => 'strSQLCompatibility', 'values' => $values, 'doc' => array('manual_MySQL_Database_Administration', 'Server_SQL_mode'))
32 /* We do not define function when plugin is just queried for information above */
33 return;
36 $buffer = '';
37 // Defaults for parser
38 $sql = '';
39 $start_pos = 0;
40 $i = 0;
41 $len= 0;
42 if (isset($_POST['sql_delimiter'])) {
43 $sql_delimiter = $_POST['sql_delimiter'];
44 } else {
45 $sql_delimiter = ';';
48 // Handle compatibility option
49 if (isset($_REQUEST['sql_compatibility'])) {
50 PMA_DBI_try_query('SET SQL_MODE="' . $_REQUEST['sql_compatibility'] . '"');
52 while (!($finished && $i >= $len) && !$error && !$timeout_passed) {
53 $data = PMA_importGetNextChunk();
54 if ($data === FALSE) {
55 // subtract data we didn't handle yet and stop processing
56 $offset -= strlen($buffer);
57 break;
58 } elseif ($data === TRUE) {
59 // Handle rest of buffer
60 } else {
61 // Append new data to buffer
62 $buffer .= $data;
63 // free memory
64 unset($data);
65 // Do not parse string when we're not at the end and don't have ; inside
66 if ((strpos($buffer, $sql_delimiter, $i) === FALSE) && !$finished) {
67 continue;
70 // Current length of our buffer
71 $len = strlen($buffer);
72 // prepare an uppercase copy of buffer for PHP < 5
73 // outside of the loop
74 // (but on Windows and PHP 5.2.5, stripos() is very slow
75 // so prepare this buffer also in this case)
76 if (PMA_PHP_INT_VERSION < 50000 || PMA_IS_WINDOWS) {
77 $buffer_upper = strtoupper($buffer);
79 // Grab some SQL queries out of it
80 while ($i < $len) {
81 $found_delimiter = false;
82 // Find first interesting character, several strpos seem to be faster than simple loop in php:
83 //while (($i < $len) && (strpos('\'";#-/', $buffer[$i]) === FALSE)) $i++;
84 //if ($i == $len) break;
85 $oi = $i;
86 $big_value = 2147483647;
87 $first_quote = strpos($buffer, '\'', $i);
88 if ($first_quote === FALSE) {
89 $first_quote = $big_value;
91 $p2 = strpos($buffer, '"', $i);
92 if ($p2 === FALSE) {
93 $p2 = $big_value;
95 /**
96 * @todo it's a shortcoming to look for a delimiter that might be
97 * inside quotes (or even double-quotes)
99 $first_sql_delimiter = strpos($buffer, $sql_delimiter, $i);
100 if ($first_sql_delimiter === FALSE) {
101 $first_sql_delimiter = $big_value;
102 } else {
103 $found_delimiter = true;
105 $p4 = strpos($buffer, '#', $i);
106 if ($p4 === FALSE) {
107 $p4 = $big_value;
109 $p5 = strpos($buffer, '--', $i);
110 if ($p5 === FALSE || $p5 >= ($len - 2) || $buffer[$p5 + 2] > ' ') {
111 $p5 = $big_value;
113 $p6 = strpos($buffer, '/*', $i);
114 if ($p6 === FALSE) {
115 $p6 = $big_value;
117 $p7 = strpos($buffer, '`', $i);
118 if ($p7 === FALSE) {
119 $p7 = $big_value;
121 // catch also "delimiter"
122 // stripos() very slow on Windows (at least on PHP 5.2.5)
123 if (PMA_PHP_INT_VERSION >= 50000 && ! PMA_IS_WINDOWS) {
124 $p8 = stripos($buffer, 'DELIMITER', $i);
125 } else {
126 $p8 = strpos($buffer_upper, 'DELIMITER', $i);
128 if ($p8 === FALSE || $p8 >= ($len - 11) || $buffer[$p8 + 9] > ' ') {
129 $p8 = $big_value;
131 $i = min ($first_quote, $p2, $first_sql_delimiter, $p4, $p5, $p6, $p7, $p8);
132 unset($first_quote, $p2, $p4, $p5, $p6, $p7, $p8);
133 if ($i == $big_value) {
134 $i = $oi;
135 if (!$finished) {
136 break;
138 // at the end there might be some whitespace...
139 if (trim($buffer) == '') {
140 $buffer = '';
141 $len = 0;
142 break;
144 // We hit end of query, go there!
145 $i = strlen($buffer) - 1;
148 // Grab current character
149 $ch = $buffer[$i];
151 // Quotes
152 if (strpos('\'"`', $ch) !== FALSE) {
153 $quote = $ch;
154 $endq = FALSE;
155 while (!$endq) {
156 // Find next quote
157 $pos = strpos($buffer, $quote, $i + 1);
158 // No quote? Too short string
159 if ($pos === FALSE) {
160 // We hit end of string => unclosed quote, but we handle it as end of query
161 if ($finished) {
162 $endq = TRUE;
163 $i = $len - 1;
165 $found_delimiter = false;
166 break;
168 // Was not the quote escaped?
169 $j = $pos - 1;
170 while ($buffer[$j] == '\\') $j--;
171 // Even count means it was not escaped
172 $endq = (((($pos - 1) - $j) % 2) == 0);
173 // Skip the string
174 $i = $pos;
176 if ($first_sql_delimiter < $pos) {
177 $found_delimiter = false;
180 if (!$endq) {
181 break;
183 $i++;
184 // Aren't we at the end?
185 if ($finished && $i == $len) {
186 $i--;
187 } else {
188 continue;
192 // Not enough data to decide
193 if ((($i == ($len - 1) && ($ch == '-' || $ch == '/'))
194 || ($i == ($len - 2) && (($ch == '-' && $buffer[$i + 1] == '-')
195 || ($ch == '/' && $buffer[$i + 1] == '*')))) && !$finished) {
196 break;
199 // Comments
200 if ($ch == '#'
201 || ($i < ($len - 1) && $ch == '-' && $buffer[$i + 1] == '-' && (($i < ($len - 2) && $buffer[$i + 2] <= ' ') || ($i == ($len - 1) && $finished)))
202 || ($i < ($len - 1) && $ch == '/' && $buffer[$i + 1] == '*')
204 // Copy current string to SQL
205 if ($start_pos != $i) {
206 $sql .= substr($buffer, $start_pos, $i - $start_pos);
208 // Skip the rest
209 $j = $i;
210 $i = strpos($buffer, $ch == '/' ? '*/' : "\n", $i);
211 // didn't we hit end of string?
212 if ($i === FALSE) {
213 if ($finished) {
214 $i = $len - 1;
215 } else {
216 break;
219 // Skip *
220 if ($ch == '/') {
221 // Check for MySQL conditional comments and include them as-is
222 if ($buffer[$j + 2] == '!') {
223 $comment = substr($buffer, $j + 3, $i - $j - 3);
224 if (preg_match('/^[0-9]{5}/', $comment, $version)) {
225 if ($version[0] <= PMA_MYSQL_INT_VERSION) {
226 $sql .= substr($comment, 5);
228 } else {
229 $sql .= $comment;
232 $i++;
234 // Skip last char
235 $i++;
236 // Next query part will start here
237 $start_pos = $i;
238 // Aren't we at the end?
239 if ($i == $len) {
240 $i--;
241 } else {
242 continue;
245 // Change delimiter, if redefined, and skip it (don't send to server!)
246 if ((strtoupper(substr($buffer, $i, 9)) == "DELIMITER") && ($buffer[$i + 9] <= ' ') && ($i<$len-11) && (!(strpos($buffer,"\n",$i+11)===FALSE))) {
247 $new_line_pos = strpos($buffer, "\n", $i + 10);
248 $sql_delimiter = substr($buffer, $i+10, $new_line_pos - $i -10);
249 $i= $new_line_pos + 1;
250 // Next query part will start here
251 $start_pos = $i;
252 continue;
255 // End of SQL
256 if ($found_delimiter || ($finished && ($i == $len - 1))) {
257 $tmp_sql = $sql;
258 if ($start_pos < $len) {
259 $length_to_grab = $i - $start_pos;
260 if (!$found_delimiter) {
261 $length_to_grab++;
263 $tmp_sql .= substr($buffer, $start_pos, $length_to_grab);
264 unset($length_to_grab);
266 // Do not try to execute empty SQL
267 if (!preg_match('/^([\s]*;)*$/', trim($tmp_sql))) {
268 $sql = $tmp_sql;
269 PMA_importRunQuery($sql, substr($buffer, 0, $i + strlen($sql_delimiter)));
270 $buffer = substr($buffer, $i + strlen($sql_delimiter));
271 // Reset parser:
272 $len = strlen($buffer);
273 $sql = '';
274 $i = 0;
275 $start_pos = 0;
276 // Any chance we will get a complete query?
277 //if ((strpos($buffer, ';') === FALSE) && !$finished) {
278 if ((strpos($buffer, $sql_delimiter) === FALSE) && !$finished) {
279 break;
281 } else {
282 $i++;
283 $start_pos = $i;
287 } // End of parser loop
288 } // End of import loop
289 // Commit any possible data in buffers
290 PMA_importRunQuery('', substr($buffer, 0, $len));
291 PMA_importRunQuery();