3 * Functions to globally validate and prepare data for sql database insertion.
5 * Copyright (C) 2009 Rod Roark <rod@sunsetsystems.com>
7 * LICENSE: This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>;.
19 * @author Rod Roark <rod@sunsetsystems.com>
20 * @author Brady Miller <brady.g.miller@gmail.com>
21 * @link http://www.open-emr.org
25 * Escape a parameter to prepare for a sql query.
27 * @param string $s Parameter to be escaped.
28 * @return string Escaped parameter.
30 function add_escape_custom($s)
32 //prepare for safe mysql insertion
33 $s = mysqli_real_escape_string($GLOBALS['dbh'], $s);
38 * Escape a sql limit variable to prepare for a sql query.
40 * This will escape integers within the LIMIT ?, ? part of a sql query.
41 * Note that there is a maximum value to these numbers, which is why
42 * should only use for the LIMIT ? , ? part of the sql query and why
43 * this is centralized to a function (in case need to upgrade this
44 * function to support larger numbers in the future).
46 * @param string $s Limit variable to be escaped.
47 * @return string Escaped limit variable.
49 function escape_limit($s)
51 //prepare for safe mysql insertion
57 * Escape/sanitize a sql sort order keyword variable to prepare for a sql query.
59 * This will escape/sanitize the sort order keyword. It is done by whitelisting
60 * only certain keywords(asc,desc). If the keyword is illegal, then will default
63 * @param string $s Sort order keyword variable to be escaped/sanitized.
64 * @return string Escaped sort order keyword variable.
66 function escape_sort_order($s)
68 return escape_identifier(strtolower($s), array("asc","desc"));
72 * Escape/sanitize a table sql column name for a sql query..
74 * This will escape/sanitize the sql column name for a sql query. It is done by whitelisting
75 * all of the current sql column names in the openemr database from a table(s). Note that if
76 * there is no match, then it will die() and a error message will be sent to the screen and
77 * the error log. This function should not be used for escaping tables outside the openemr
78 * database (should use escape_identifier() function below for that scenario)
80 * @param string $s sql column name variable to be escaped/sanitized.
81 * @param array $tables The table(s) that the sql columns is from (in an array).
82 * @param boolean $long Use long form (ie. table.colname) vs short form (ie. colname).
83 * @return string Escaped table name variable.
85 function escape_sql_column_name($s, $tables, $long = false)
88 // If the $tables is empty, then process them all
90 $res = sqlStatementNoLog("SHOW TABLES");
92 while ($row=sqlFetchArray($res)) {
93 $keys_return = array_keys($row);
94 $tables[]=$row[$keys_return[0]];
98 // First need to escape the $tables
99 $tables_escaped = array();
100 foreach ($tables as $table) {
101 $tables_escaped[] = escape_table_name($table);
104 // Collect all the possible sql columns from the tables
105 $columns_options = array();
106 foreach ($tables_escaped as $table_escaped) {
107 $res = sqlStatementNoLog("SHOW COLUMNS FROM ".$table_escaped);
108 while ($row=sqlFetchArray($res)) {
110 $columns_options[]=$table_escaped.".".$row['Field'];
112 $columns_options[]=$row['Field'];
117 // Now can escape(via whitelisting) the sql column name
118 return escape_identifier($s, $columns_options, true);
122 * Escape/sanitize a table name for a sql query. This function can also can be used to
123 * process tables that contain any upper case letters.
125 * This will escape/sanitize the table name for a sql query. It is done by whitelisting
126 * all of the current tables in the openemr database. The matching is not case sensitive,
127 * although it will attempt a case sensitive match before proceeding to a case insensitive
128 * match (see below escape_identifier() function for more details on this). Note that if
129 * there is no match, then it will die() and a error message will be sent to the screen
130 * and the error log. This function should not be used for escaping tables outside the
131 * openemr database (should use escape_identifier() function below for that scenario).
132 * Another use of this function is to deal with casing issues that arise in tables that
133 * contain upper case letter(s) (these tables can be huge issues when transferring databases
134 * from Windows to Linux and vice versa); this function can avoid this issues if run the
135 * table name through this function (To avoid confusion, there is a wrapper function
136 * entitled mitigateSqlTableUpperCase() that is used when just need to mitigate casing
137 * for table names that contain any uppercase letters).
138 * @param string $s sql table name variable to be escaped/sanitized.
139 * @return string Escaped table name variable.
141 function escape_table_name($s)
143 $res = sqlStatementNoLog("SHOW TABLES");
144 $tables_array = array();
145 while ($row=sqlFetchArray($res)) {
146 $keys_return = array_keys($row);
147 $tables_array[]=$row[$keys_return[0]];
150 // Now can escape(via whitelisting) the sql table name
151 return escape_identifier($s, $tables_array, true, false);
155 * Process tables that contain any upper case letters; this is simple a wrapper function of
156 * escape_table_name() above when using it for the sole purpose of mitigating sql table names
157 * that contain upper case letters.
159 * @param string $s sql table name variable to be escaped/sanitized.
160 * @return string Escaped table name variable.
162 function mitigateSqlTableUpperCase($s)
164 return escape_table_name($s);
168 * Escape/sanitize a sql identifier variable to prepare for a sql query.
170 * This will escape/sanitize a sql identifier. There are two options provided by this
172 * The first option is done by whitelisting ($whitelist_items is used) and in this case
173 * only certain identifiers (listed in the $whitelist_items array) can be used; if
174 * there is no match, then it will either default to the first item in the $whitelist_items
175 * (if $die_if_no_match is FALSE) or it will die() and send an error message to the screen
176 * and log (if $die_if_no_match is TRUE). Note there is an option to allow case insensitive
177 * matching; if this option is chosen, it will first attempt a case sensitive match and if this
178 * fails, then attempt a case insensitive match.
179 * The second option is done by sanitizing ($whitelist_items is not used) and in this case
180 * only US alphanumeric,'_' and '.' items are kept in the returned string. Note
181 * the second option is still experimental as we figure out the ideal items to
182 * filter out of the identifier. The first option is ideal if all the possible identifiers
183 * are known, however we realize this may not always be the case.
185 * @param string $s Sql identifier variable to be escaped/sanitized.
186 * @param array $whitelist_items Items used in whitelisting method (See function description for details of whitelisting method).
187 * @param boolean $die_if_no_match If there is no match in the whitelist, then die and echo an error to screen and log.
188 * @param boolean $case_sens_match Use case sensitive match (this is default).
189 * @return string Escaped/sanitized sql identifier variable.
191 function escape_identifier($s, $whitelist_items, $die_if_no_match = false, $case_sens_match = true)
193 if (is_array($whitelist_items)) {
194 // Only return an item within the whitelist_items
195 $ok = $whitelist_items;
196 // First, search for case sensitive match
197 $key = array_search($s, $ok);
198 if ($key === false) {
200 if (!$case_sens_match) {
201 // Attempt a case insensitive match
202 $ok_UPPER = array_map("strtoupper", $ok);
203 $key = array_search(strtoupper($s), $ok_UPPER);
206 if ($key === false) {
208 if ($die_if_no_match) {
209 // No match and $die_if_no_match is set, so die() and send error messages to screen and log
210 error_Log("ERROR: OpenEMR SQL Escaping ERROR of the following string: ".$s, 0);
211 die("<br><span style='color:red;font-weight:bold;'>".xlt("There was an OpenEMR SQL Escaping ERROR of the following string")." ".text($s)."</span><br>");
213 // Return first token since no match
221 // Return an item that has been "cleaned" up
222 // (this is currently experimental and goal is to avoid using this)
223 return preg_replace('/[^a-zA-Z0-9_.]/', '', $s);
228 * (Note this function is deprecated for new scripts and is only utilized to support legacy scripts)
229 * Function to manage POST, GET, and REQUEST variables.
231 * @param string $name name of the variable requested.
232 * @param string $type 'P', 'G' for post or get data, otherwise uses request.
233 * @param bool $istrim whether to use trim() on the data.
234 * @return string variable requested, or empty string
236 function formData($name, $type = 'P', $isTrim = false)
239 $s = isset($_POST[$name]) ?
$_POST[$name] : '';
240 } else if ($type == 'G') {
241 $s = isset($_GET[$name]) ?
$_GET[$name] : '';
243 $s = isset($_REQUEST[$name]) ?
$_REQUEST[$name] : '';
246 return formDataCore($s, $isTrim);
250 * (Note this function is deprecated for new scripts and is only utilized to support legacy scripts)
251 * Core function that will be called by formData.
252 * Note it can also be called directly if preparing
253 * normal variables (not GET,POST, or REQUEST)
256 * @param bool $istrim whether to use trim() on the data.
259 function formDataCore($s, $isTrim = false)
267 $s = strip_escape_custom($s);
268 //add escapes for safe database insertion
269 $s = add_escape_custom($s);
274 * (Note this function is deprecated for new scripts and is only utilized to support legacy scripts)
275 * Will remove escapes if needed (ie magic quotes turned on) from string
276 * Called by above formDataCore() function to prepare for database insertion.
277 * Can also be called directly if simply need to remove escaped characters
278 * from a string before processing.
283 function strip_escape_custom($s)
285 //magic quotes is gone as of php 5.4, so just return the value
290 * (Note this function is deprecated for new scripts and is only utilized to support legacy scripts)
291 * This function is only being kept to support
292 * previous functionality. If you want to trim
293 * variables, this should be done using above
299 function formTrim($s)
301 return formDataCore($s, true);