fix: ccda zip import and php warnings and deprecations (#7416)
[openemr.git] / library / htmlspecialchars.inc.php
blob8c38680562a9035e4145641a1adb024e4e57f26c
1 <?php
3 /**
4 * Escaping Functions
6 * @package OpenEMR
7 * @link https://www.open-emr.org
8 * @author Boyd Stephen Smith Jr.
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2011 Boyd Stephen Smith Jr.
11 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
12 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 /**
16 * Escape a javascript literal.
18 function js_escape($text)
20 return json_encode($text);
23 /**
24 * Escape a javascript literal within html onclick attribute.
26 function attr_js($text)
28 return attr(json_encode($text));
31 /**
32 * Escape html and url encode a url item.
34 function attr_url($text)
36 return attr(urlencode($text ?? ''));
39 /**
40 * Escape js and url encode a url item.
42 function js_url($text)
44 return js_escape(urlencode($text ?? ''));
47 /**
48 * Escape variables that are outputted into the php error log.
50 function errorLogEscape($text)
52 return attr($text);
55 /**
56 * Escape variables that are outputted into csv and spreadsheet files.
57 * See here: https://www.owasp.org/index.php/CSV_Injection
58 * Based mitigation strategy on this report: https://asecurityz.blogspot.com/2017/12/csv-injection-mitigations.html
59 * 1. Remove all the following characters: = + " |
60 * 2. Only remove leading - characters (since need in dates)
61 * 3. Only remove leading @ characters (since need in email addresses)
62 * 4. Surround with double quotes (no reference link, but seems very reasonable, which will prevent commas from breaking things).
63 * If needed in future, will add a second parameter called 'options' which will be an array of option tokens that will allow
64 * less stringent (or more stringent) mechanisms to escape for csv.
66 function csvEscape($text)
68 // 1. Remove all the following characters: = + " |
69 $text = preg_replace('/[=+"|]/', '', $text ?? '');
71 // 2. Only remove leading - characters (since need in dates)
72 // 3. Only remove leading @ characters (since need in email addresses)
73 $text = preg_replace('/^[\-@]+/', '', $text);
75 // 4. Surround with double quotes (no reference link, but seems very reasonable, which will prevent commas from breaking things).
76 return '"' . $text . '"';
79 /**
81 * references: https://stackoverflow.com/questions/3426090/how-do-you-make-strings-xml-safe
82 * https://www.php.net/htmlspecialchars
83 * https://www.php.net/XMLWriter
86 * Escapes & < > ' "
87 * TODO: not sure if need to escape ' and ", which are escaping for now (via the ENT_QUOTES flag)
89 function xmlEscape($text)
91 return htmlspecialchars(($text ?? ''), ENT_XML1 | ENT_QUOTES);
94 /**
95 * Special function to remove the 'javascript' strings (case insensitive) for when including a variable within a html link
97 function javascriptStringRemove(?string $text): string
99 $returnText = str_ireplace('javascript', '', $text ?? '');
101 if (javascriptStringCheck($returnText)) {
102 $returnText = javascriptStringRemove($returnText);
105 return $returnText;
109 * Special function to check if 'javascript' string (case insensitive) is in a variable within a html link
111 function javascriptStringCheck(?string $text): bool
113 if (stripos($text ?? '', 'javascript') === false) {
114 return false;
115 } else {
116 return true;
121 * Escape a PHP string for use as (part of) an HTML / XML text node.
123 * It only escapes a few special chars: the ampersand (&) and both the left-
124 * pointing angle bracket (<) and the right-pointing angle bracket (>), since
125 * these are the only characters that are special in a text node. Minimal
126 * quoting is preferred because it produces smaller and more easily human-
127 * readable output.
129 * Some characters simply cannot appear in valid XML documents, even
130 * as entities but, this function does not attempt to handle them.
132 * NOTE: Attribute values are NOT text nodes, and require additional escaping.
134 * @param string $text The string to escape, possibly including "&", "<",
135 * or ">".
136 * @return string The string, with "&", "<", and ">" escaped.
138 function text($text)
140 return htmlspecialchars(($text ?? ''), ENT_NOQUOTES);
144 * Given an array of properties run through both the keys and values of the array and
145 * escape each PHP string for use as (part of) an HTML / XML text node.
147 * It only escapes a few special chars: the ampersand (&) and both the left-
148 * pointing angle bracket (<) and the right-pointing angle bracket (>), since
149 * these are the only characters that are special in a text node. Minimal
150 * quoting is preferred because it produces smaller and more easily human-
151 * readable output.
153 * Some characters simply cannot appear in valid XML documents, even
154 * as entities but, this function does not attempt to handle them.
156 * NOTE: Attribute values are NOT text nodes, and require additional escaping.
158 * @param string $arr The array of strings to escape, possibly including "&", "<",
159 * or ">".
160 * @param int $depth The current recursive depth of the escaping function. Defaults to 0 for initial call
161 * @return array The array that has each key and property escaped.
163 function textArray(array $arr, $depth = 0)
165 if ($depth > 50) {
166 throw new \InvalidArgumentException("array was nested too deep for escaping. Max limit reached");
169 $newArray = [];
170 foreach ($arr as $key => $value) {
171 if (is_array($value)) {
172 $newArray[text($key)] = textArray($value, $depth + 1);
173 } else {
174 $newArray[text($key)] = text($value);
177 return $newArray;
181 * Escape a PHP string for use as (part of) an HTML / XML attribute value.
183 * It escapes several special chars: the ampersand (&), the double quote
184 * ("), the singlequote ('), and both the left-pointing angle bracket (<)
185 * and the right-pointing angle bracket (>), since these are the characters
186 * that are special in an attribute value.
188 * Some characters simply cannot appear in valid XML documents, even
189 * as entities but, this function does not attempt to handle them.
191 * NOTE: This can be used as a "generic" HTML escape since it does maximal
192 * quoting. However, some HTML and XML contexts (CDATA) don't provide
193 * escape mechanisms. Also, further pre- or post-escaping might need to
194 * be done when embdedded other languages (like JavaScript) inside HTML /
195 * XML documents.
197 * @param string $text The string to escape, possibly including (&), (<),
198 * (>), ('), and (").
199 * @return string The string, with (&), (<), (>), ("), and (') escaped.
201 function attr($text)
203 return htmlspecialchars(($text ?? ''), ENT_QUOTES);
207 * Don't call this function. You don't see this function. This function
208 * doesn't exist.
210 * TODO: Hide this function so it can be called from this file but not from
211 * PHP that includes / requires this file. Either that, or write reasonable
212 * documentation and clean up the name.
214 function hsc_private_xl_or_warn($key)
216 if (function_exists('xl')) {
217 return xl($key);
218 } else {
219 trigger_error(
220 'Translation via xl() was requested, but the xl()'
221 . ' function is not defined, yet.',
222 E_USER_WARNING
224 return $key;
229 * Translate via xl() and then escape via text().
231 * @param string $key The string to escape, possibly including "&", "<",
232 * or ">".
233 * @return string The string, with "&", "<", and ">" escaped.
235 function xlt($key)
237 return text(hsc_private_xl_or_warn($key));
241 * Translate via xl() and then escape via attr().
243 * @param string $key The string to escape, possibly including (&), (<),
244 * (>), ('), and (").
245 * @return string The string, with (&), (<), (>), ("), and (') escaped.
247 function xla($key)
249 return attr(hsc_private_xl_or_warn($key));
253 * Translate via xl() and then escape via js_escape for use with javascript literals
255 function xlj($key)
257 return js_escape(hsc_private_xl_or_warn($key));
261 * Deprecated
262 *Translate via xl() and then escape via addslashes for use with javascript literals
264 function xls($key)
266 return addslashes(hsc_private_xl_or_warn($key));