BLOB streaming documentation
[phpmyadmin/crack.git] / libraries / import / sql.php
blob6a6e76e357d60d6877c45383e3b40537f97df703
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(
29 'type' => 'select',
30 'name' => 'compatibility',
31 'text' => 'strSQLCompatibility',
32 'values' => $values,
33 'doc' => array(
34 'manual_MySQL_Database_Administration',
35 'Server_SQL_mode',
41 /* We do not define function when plugin is just queried for information above */
42 return;
45 $buffer = '';
46 // Defaults for parser
47 $sql = '';
48 $start_pos = 0;
49 $i = 0;
50 $len= 0;
51 $big_value = 2147483647;
53 if (isset($_POST['sql_delimiter'])) {
54 $sql_delimiter = $_POST['sql_delimiter'];
55 } else {
56 $sql_delimiter = ';';
59 // Handle compatibility option
60 if (isset($_REQUEST['sql_compatibility'])) {
61 PMA_DBI_try_query('SET SQL_MODE="' . $_REQUEST['sql_compatibility'] . '"');
64 /**
65 * will be set in PMA_importGetNextChunk()
67 * @global boolean $GLOBALS['finished']
69 $GLOBALS['finished'] = false;
71 while (!($GLOBALS['finished'] && $i >= $len) && !$error && !$timeout_passed) {
72 $data = PMA_importGetNextChunk();
73 if ($data === FALSE) {
74 // subtract data we didn't handle yet and stop processing
75 $offset -= strlen($buffer);
76 break;
77 } elseif ($data === TRUE) {
78 // Handle rest of buffer
79 } else {
80 // Append new data to buffer
81 $buffer .= $data;
82 // free memory
83 unset($data);
84 // Do not parse string when we're not at the end and don't have ; inside
85 if ((strpos($buffer, $sql_delimiter, $i) === FALSE) && !$GLOBALS['finished']) {
86 continue;
89 // Current length of our buffer
90 $len = strlen($buffer);
92 // Grab some SQL queries out of it
93 while ($i < $len) {
94 $found_delimiter = false;
95 // Find first interesting character
96 $old_i = $i;
97 // this is about 7 times faster that looking for each sequence i
98 // one by one with strpos()
99 if (preg_match('/(\'|"|#|-- |\/\*|`|(?i)DELIMITER)/', $buffer, $matches, PREG_OFFSET_CAPTURE, $i)) {
100 // in $matches, index 0 contains the match for the complete
101 // expression but we don't use it
102 $first_position = $matches[1][1];
103 } else {
104 $first_position = $big_value;
107 * @todo we should not look for a delimiter that might be
108 * inside quotes (or even double-quotes)
110 // the cost of doing this one with preg_match() would be too high
111 $first_sql_delimiter = strpos($buffer, $sql_delimiter, $i);
112 if ($first_sql_delimiter === FALSE) {
113 $first_sql_delimiter = $big_value;
114 } else {
115 $found_delimiter = true;
118 // set $i to the position of the first quote, comment.start or delimiter found
119 $i = min($first_position, $first_sql_delimiter);
121 if ($i == $big_value) {
122 // none of the above was found in the string
124 $i = $old_i;
125 if (!$GLOBALS['finished']) {
126 break;
128 // at the end there might be some whitespace...
129 if (trim($buffer) == '') {
130 $buffer = '';
131 $len = 0;
132 break;
134 // We hit end of query, go there!
135 $i = strlen($buffer) - 1;
138 // Grab current character
139 $ch = $buffer[$i];
141 // Quotes
142 if (strpos('\'"`', $ch) !== FALSE) {
143 $quote = $ch;
144 $endq = FALSE;
145 while (!$endq) {
146 // Find next quote
147 $pos = strpos($buffer, $quote, $i + 1);
148 // No quote? Too short string
149 if ($pos === FALSE) {
150 // We hit end of string => unclosed quote, but we handle it as end of query
151 if ($GLOBALS['finished']) {
152 $endq = TRUE;
153 $i = $len - 1;
155 $found_delimiter = false;
156 break;
158 // Was not the quote escaped?
159 $j = $pos - 1;
160 while ($buffer[$j] == '\\') $j--;
161 // Even count means it was not escaped
162 $endq = (((($pos - 1) - $j) % 2) == 0);
163 // Skip the string
164 $i = $pos;
166 if ($first_sql_delimiter < $pos) {
167 $found_delimiter = false;
170 if (!$endq) {
171 break;
173 $i++;
174 // Aren't we at the end?
175 if ($GLOBALS['finished'] && $i == $len) {
176 $i--;
177 } else {
178 continue;
182 // Not enough data to decide
183 if ((($i == ($len - 1) && ($ch == '-' || $ch == '/'))
184 || ($i == ($len - 2) && (($ch == '-' && $buffer[$i + 1] == '-')
185 || ($ch == '/' && $buffer[$i + 1] == '*')))) && !$GLOBALS['finished']) {
186 break;
189 // Comments
190 if ($ch == '#'
191 || ($i < ($len - 1) && $ch == '-' && $buffer[$i + 1] == '-'
192 && (($i < ($len - 2) && $buffer[$i + 2] <= ' ')
193 || ($i == ($len - 1) && $GLOBALS['finished'])))
194 || ($i < ($len - 1) && $ch == '/' && $buffer[$i + 1] == '*')
196 // Copy current string to SQL
197 if ($start_pos != $i) {
198 $sql .= substr($buffer, $start_pos, $i - $start_pos);
200 // Skip the rest
201 $j = $i;
202 $i = strpos($buffer, $ch == '/' ? '*/' : "\n", $i);
203 // didn't we hit end of string?
204 if ($i === FALSE) {
205 if ($GLOBALS['finished']) {
206 $i = $len - 1;
207 } else {
208 break;
211 // Skip *
212 if ($ch == '/') {
213 // Check for MySQL conditional comments and include them as-is
214 if ($buffer[$j + 2] == '!') {
215 $comment = substr($buffer, $j + 3, $i - $j - 3);
216 if (preg_match('/^[0-9]{5}/', $comment, $version)) {
217 if ($version[0] <= PMA_MYSQL_INT_VERSION) {
218 $sql .= substr($comment, 5);
220 } else {
221 $sql .= $comment;
224 $i++;
226 // Skip last char
227 $i++;
228 // Next query part will start here
229 $start_pos = $i;
230 // Aren't we at the end?
231 if ($i == $len) {
232 $i--;
233 } else {
234 continue;
237 // Change delimiter, if redefined, and skip it (don't send to server!)
238 if (strtoupper(substr($buffer, $i, 9)) == "DELIMITER"
239 && ($buffer[$i + 9] <= ' ')
240 && ($i < $len - 11)
241 && strpos($buffer, "\n", $i + 11) !== FALSE) {
242 $new_line_pos = strpos($buffer, "\n", $i + 10);
243 $sql_delimiter = substr($buffer, $i + 10, $new_line_pos - $i - 10);
244 $i = $new_line_pos + 1;
245 // Next query part will start here
246 $start_pos = $i;
247 continue;
250 // End of SQL
251 if ($found_delimiter || ($GLOBALS['finished'] && ($i == $len - 1))) {
252 $tmp_sql = $sql;
253 if ($start_pos < $len) {
254 $length_to_grab = $i - $start_pos;
256 if (! $found_delimiter) {
257 $length_to_grab++;
259 $tmp_sql .= substr($buffer, $start_pos, $length_to_grab);
260 unset($length_to_grab);
262 // Do not try to execute empty SQL
263 if (! preg_match('/^([\s]*;)*$/', trim($tmp_sql))) {
264 $sql = $tmp_sql;
265 PMA_importRunQuery($sql, substr($buffer, 0, $i + strlen($sql_delimiter)));
266 $buffer = substr($buffer, $i + strlen($sql_delimiter));
267 // Reset parser:
268 $len = strlen($buffer);
269 $sql = '';
270 $i = 0;
271 $start_pos = 0;
272 // Any chance we will get a complete query?
273 //if ((strpos($buffer, ';') === FALSE) && !$GLOBALS['finished']) {
274 if ((strpos($buffer, $sql_delimiter) === FALSE) && !$GLOBALS['finished']) {
275 break;
277 } else {
278 $i++;
279 $start_pos = $i;
282 } // End of parser loop
283 } // End of import loop
284 // Commit any possible data in buffers
285 PMA_importRunQuery('', substr($buffer, 0, $len));
286 PMA_importRunQuery();