1: <?php
2: /**
3: * XOOPS MySQL utility
4: *
5: * You may not change or alter any portion of this comment or credits
6: * of supporting developers from this source code or any supporting source code
7: * which is considered copyrighted (c) material of the original comment or credit authors.
8: * This program is distributed in the hope that it will be useful,
9: * but WITHOUT ANY WARRANTY; without even the implied warranty of
10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11: *
12: * @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
13: * @license GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
14: * @package kernel
15: * @subpackage database
16: * @author Kazumi Ono <onokazu@xoops.org>
17: */
18:
19: defined('XOOPS_ROOT_PATH') || exit('Restricted access');
20:
21: /**
22: * provide some utility methods for databases
23: *
24: * @author Kazumi Ono <onokazu@xoops.org>
25: * @package kernel
26: * @subpackage database
27: */
28: class SqlUtility
29: {
30: /**
31: * Function from phpMyAdmin (http://phpwizard.net/projects/phpMyAdmin/)
32: *
33: * Removes comment and splits large sql files into individual queries
34: *
35: * Last revision: September 23, 2001 - gandon
36: *
37: * @param array $ret the splitted sql commands
38: * @param string $sql the sql commands
39: * @return boolean always true
40: * @access public
41: */
42: public static function splitMySqlFile(&$ret, $sql)
43: {
44: $sql = trim($sql);
45: $sql_len = strlen($sql);
46: $char = '';
47: $string_start = '';
48: $in_string = false;
49:
50: for ($i = 0; $i < $sql_len; ++$i) {
51: $char = $sql[$i];
52: // We are in a string, check for not escaped end of
53: // strings except for backquotes that can't be escaped
54: if ($in_string) {
55: for (; ;) {
56: $i = strpos($sql, $string_start, $i);
57: // No end of string found -> add the current
58: // substring to the returned array
59: if (!$i) {
60: $ret[] = $sql;
61:
62: return true;
63: }
64: // Backquotes or no backslashes before
65: // quotes: it's indeed the end of the
66: // string -> exit the loop
67: elseif ($string_start === '`' || $sql[$i - 1] !== '\\') {
68: $string_start = '';
69: $in_string = false;
70: break;
71: }
72: // one or more Backslashes before the presumed
73: // end of string...
74: else {
75: // first checks for escaped backslashes
76: $j = 2;
77: $escaped_backslash = false;
78: while ($i - $j > 0 && $sql[$i - $j] === '\\') {
79: $escaped_backslash = !$escaped_backslash;
80: ++$j;
81: }
82: // ... if escaped backslashes: it's really the
83: // end of the string -> exit the loop
84: if ($escaped_backslash) {
85: $string_start = '';
86: $in_string = false;
87: break;
88: } // ... else loop
89: else {
90: ++$i;
91: }
92: } // end if...elseif...else
93: } // end for
94: } // end if (in string)
95: // We are not in a string, first check for delimiter...
96: elseif ($char === ';') {
97: // if delimiter found, add the parsed part to the returned array
98: $ret[] = substr($sql, 0, $i);
99: $sql = ltrim(substr($sql, min($i + 1, $sql_len)));
100: $sql_len = strlen($sql);
101: if ($sql_len) {
102: $i = -1;
103: } else {
104: // The submited statement(s) end(s) here
105: return true;
106: }
107: } // end else if (is delimiter)
108: // ... then check for start of a string,...
109: elseif (($char === '"') || ($char === '\'') || ($char === '`')) {
110: $in_string = true;
111: $string_start = $char;
112: } // end else if (is start of string)
113: // for start of a comment (and remove this comment if found)...
114: elseif ($char === '#' || ($char === ' ' && $i > 1 && $sql[$i - 2] . $sql[$i - 1] === '--')) {
115: // starting position of the comment depends on the comment type
116: $start_of_comment = (($sql[$i] === '#') ? $i : $i - 2);
117: // if no "\n" exits in the remaining string, checks for "\r"
118: // (Mac eol style)
119: $end_of_comment = strpos(' ' . $sql, "\012", $i + 2) ?: strpos(' ' . $sql, "\015", $i + 2);
120: if (!$end_of_comment) {
121: // no eol found after '#', add the parsed part to the returned
122: // array and exit
123: // RMV fix for comments at end of file
124: //$last = trim(substr($sql, 0, $i-1));
125: //if (!empty($last)) {
126: // $ret[] = $last;
127: //}
128: return true;
129: } else {
130: $sql = substr($sql, 0, $start_of_comment) . ltrim(substr($sql, $end_of_comment));
131: $sql_len = strlen($sql);
132: $i--;
133: } // end if...else
134: } // end else if (is comment)
135: } // end for
136: // add any rest to the returned array
137: if (!empty($sql) && trim($sql) != '') {
138: $ret[] = $sql;
139: }
140:
141: return true; // end for
142: }
143:
144: /**
145: * add a prefix.'_' to all tablenames in a query
146: *
147: * @param string $query valid SQL query string
148: * @param string $prefix prefix to add to all table names
149: * @return mixed FALSE on failure
150: */
151: public static function prefixQuery($query, $prefix)
152: {
153: $pattern = "/^(INSERT[\s]+INTO|CREATE[\s]+TABLE|ALTER[\s]+TABLE|UPDATE)(\s)+([`]?)([^`\s]+)\\3(\s)+/siU";
154: $pattern2 = "/^(DROP TABLE)(\s)+([`]?)([^`\s]+)\\3(\s)?$/siU";
155: if (preg_match($pattern, $query, $matches) || preg_match($pattern2, $query, $matches)) {
156: $replace = "\\1 " . $prefix . "_\\4\\5";
157: $matches[0] = preg_replace($pattern, $replace, $query);
158:
159: return $matches;
160: }
161:
162: return false;
163: }
164: }
165: