If you are not redirected within ' . ( $timeout + 1 ) . ' seconds, please click here.
';
$template->footer(true);
-
+
$db->close();
exit(0);
-
+
}
// Removed wikiFormat() from here, replaced with RenderMan::render
@@ -305,21 +305,21 @@
function isPage($p) {
global $db, $session, $paths, $template, $plugins; // Common objects
-
+
// Try the easy way first ;-)
if ( isset( $paths->pages[ $p ] ) )
{
return true;
}
-
+
// Special case for Special, Template, and Admin pages that can't have slashes in their URIs
$ns_test = RenderMan::strToPageID( $p );
-
+
if($ns_test[1] != 'Special' && $ns_test[1] != 'Template' && $ns_test[1] != 'Admin')
{
return false;
}
-
+
$particles = explode('/', $p);
if ( isset ( $paths->pages[ $particles[ 0 ] ] ) )
{
@@ -331,6 +331,10 @@
}
}
+/**
+ * These are some old functions that were used with the Midget codebase. They are deprecated and should not be used any more.
+ */
+
function arrayItemUp($arr, $keyname) {
$keylist = array_keys($arr);
$keyflop = array_flip($keylist);
@@ -436,16 +440,24 @@
// Function strip_php moved to RenderMan class
+/**
+ * Immediately brings the site to a halt with an error message. Unlike grinding_halt() this can only be called after the config has been
+ * fetched (plugin developers don't even need to worry since plugins are always loaded after the config) and shows the site name and
+ * description.
+ * @param string The title of the error message
+ * @param string The body of the message, this can be HTML, and should be separated into paragraphs using the
tag
+ */
+
function die_semicritical($t, $p)
{
global $db, $session, $paths, $template, $plugins; // Common objects
$db->close();
-
+
if ( ob_get_status() )
ob_end_clean();
-
+
dc_here('functions: calling die_semicritical');
-
+
$tpl = new template_nodb();
$tpl->load_theme('oxygen', 'bleu');
$tpl->tpl_strings['SITE_NAME'] = getConfig('site_name');
@@ -455,17 +467,23 @@
$tpl->header();
echo $p;
$tpl->footer();
-
+
exit;
}
+/**
+ * Halts Enano execution with a message. This doesn't have to be an error message, it's sometimes used to indicate success at an operation.
+ * @param string The title of the message
+ * @param string The body of the message, this can be HTML, and should be separated into paragraphs using the
tag
+ */
+
function die_friendly($t, $p)
{
global $db, $session, $paths, $template, $plugins; // Common objects
-
+
if ( ob_get_status() )
ob_end_clean();
-
+
dc_here('functions: calling die_friendly');
$paths->cpage['name'] = $t;
$template->tpl_strings['PAGE_NAME'] = $t;
@@ -473,19 +491,25 @@
echo $p;
$template->footer();
$db->close();
-
+
exit;
}
+/**
+ * Immediately brings the site to a halt with an error message, and focuses on immediately closing the database connection and shutting down Enano in the event that an attack may happen. This should only be used very early on to indicate very severe errors, or if the site may be under attack (like if the DBAL detects a malicious query). In the vast majority of cases, die_semicritical() is more appropriate.
+ * @param string The title of the error message
+ * @param string The body of the message, this can be HTML, and should be separated into paragraphs using the
tag
+ */
+
function grinding_halt($t, $p)
{
global $db, $session, $paths, $template, $plugins; // Common objects
-
+
$db->close();
-
+
if ( ob_get_status() )
ob_end_clean();
-
+
dc_here('functions: calling grinding_halt');
$tpl = new template_nodb();
$tpl->load_theme('oxygen', 'bleu');
@@ -499,11 +523,17 @@
exit;
}
-function show_category_info() {
+/**
+ * Prints out the categorization box found on most regular pages. Doesn't take or return anything, but assumes that the page information is already set in $paths.
+ */
+
+ /*
+function show_category_info()
+{
global $db, $session, $paths, $template, $plugins; // Common objects
dc_here('functions: showing category info');
- if($template->no_headers && !strpos($_SERVER['REQUEST_URI'], 'ajax.php')) return '';
- if($paths->namespace=='Category')
+ // if($template->no_headers && !strpos($_SERVER['REQUEST_URI'], 'ajax.php')) return '';
+ if ( $paths->namespace == 'Category' )
{
$q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\'Category\' ORDER BY page_id;');
if(!$q) $db->_die('The category information could not be selected.');
@@ -513,27 +543,49 @@
echo '
';
-
+
$q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace!=\'Category\' ORDER BY page_id;');
- if(!$q) $db->_die('The category information could not be selected.');
+ if ( !$q )
+ {
+ $db->_die('The category information could not be selected.');
+ }
$ticker = -1;
echo '
';
+
+ }
+
+}
+
+/**
+ * Prints out the file information box seen on File: pages. Doesn't take or return anything, but assumes that the page information is already set in $paths, and expects $paths->namespace to be File.
+ */
function show_file_info()
{
@@ -630,6 +858,10 @@
echo ' ';
}
+/**
+ * Shows header information on the current page. Currently this is only the delete-vote feature. Doesn't take or return anything, but assumes that the page information is already set in $paths.
+ */
+
function display_page_headers()
{
global $db, $session, $paths, $template, $plugins; // Common objects
@@ -653,6 +885,10 @@
}
}
+/**
+ * Displays page footer information including file and category info. This also has the send_page_footers hook. Doesn't take or return anything, but assumes that the page information is already set in $paths.
+ */
+
function display_page_footers()
{
global $db, $session, $paths, $template, $plugins; // Common objects
@@ -666,6 +902,10 @@
show_category_info();
}
+/**
+ * Deprecated, do not use.
+ */
+
function password_prompt($id = false)
{
global $db, $session, $paths, $template, $plugins; // Common objects
@@ -679,6 +919,12 @@
}
}
+/**
+ * Some sort of primitive hex converter from back in the day. Deprecated, do not use.
+ * @param string Text to encode
+ * @return string
+ */
+
function str_hex($string){
$hex='';
for ($i=0; $i < strlen($string); $i++){
@@ -687,92 +933,111 @@
return substr($hex, 1, strlen($hex));
}
-// Function pulled from phpBB's smtp.php
-function smtp_get_response($socket, $response, $line = __LINE__)
+/**
+ * Essentially an return code reader for a socket. Don't use this unless you're writing mail code and smtp_send_email doesn't cut it. Ported from phpBB's smtp.php.
+ * @param socket A socket resource
+ * @param string The expected response from the server, this needs to be exactly three characters.
+ */
+
+function smtp_get_response($socket, $response, $line = __LINE__)
{
- $server_response = '';
- while (substr($server_response, 3, 1) != ' ')
- {
- if (!($server_response = fgets($socket, 256)))
- {
+ $server_response = '';
+ while (substr($server_response, 3, 1) != ' ')
+ {
+ if (!($server_response = fgets($socket, 256)))
+ {
die_friendly('SMTP Error', "
Ran into problems sending mail. Response: $server_response
");
- }
+ }
}
+/**
+ * Wrapper for smtp_send_email_core that takes the sender as the fourth parameter instead of additional headers.
+ * @param string E-mail address to send to
+ * @param string Subject line
+ * @param string The body of the message
+ * @param string Address of the sender
+ */
+
function smtp_send_email($to, $subject, $message, $from)
{
return smtp_send_email_core($to, $subject, $message, "From: <$from>\n");
}
-// Replacement or substitute for PHP's mail command
-// Ported from phpBB - copyright (C) phpBB group, GPL.
+/**
+ * Replacement or substitute for PHP's mail() builtin function.
+ * @param string E-mail address to send to
+ * @param string Subject line
+ * @param string The body of the message
+ * @param string Message headers, separated by a single newline ("\n")
+ * @copyright (C) phpBB Group
+ * @license GPL
+ */
+
function smtp_send_email_core($mail_to, $subject, $message, $headers = '')
{
- global $board_config;
-
- // Fix any bare linefeeds in the message to make it RFC821 Compliant.
- $message = preg_replace("#(? 1)
- {
- $headers = join("\n", $headers);
- }
- else
- {
- $headers = $headers[0];
- }
- }
- $headers = chop($headers);
+ if ($headers != '')
+ {
+ if (is_array($headers))
+ {
+ if (sizeof($headers) > 1)
+ {
+ $headers = join("\n", $headers);
+ }
+ else
+ {
+ $headers = $headers[0];
+ }
+ }
+ $headers = chop($headers);
- // Make sure there are no bare linefeeds in the headers
- $headers = preg_replace('#(?\r\n");
- smtp_get_response($socket, "250", __LINE__);
+ // From this point onward most server response codes should be 250
+ // Specify who the mail is from....
+ enano_fputs($socket, "MAIL FROM: <" . getConfig('contact_email') . ">\r\n");
+ smtp_get_response($socket, "250", __LINE__);
- // Specify each user to send to and build to header.
- $to_header = '';
+ // Specify each user to send to and build to header.
+ $to_header = '';
- // Add an additional bit of error checking to the To field.
- $mail_to = (trim($mail_to) == '') ? 'Undisclosed-recipients:;' : trim($mail_to);
- if (preg_match('#[^ ]+\@[^ ]+#', $mail_to))
- {
- enano_fputs($socket, "RCPT TO: <$mail_to>\r\n");
- smtp_get_response($socket, "250", __LINE__);
- }
+ // Add an additional bit of error checking to the To field.
+ $mail_to = (trim($mail_to) == '') ? 'Undisclosed-recipients:;' : trim($mail_to);
+ if (preg_match('#[^ ]+\@[^ ]+#', $mail_to))
+ {
+ enano_fputs($socket, "RCPT TO: <$mail_to>\r\n");
+ smtp_get_response($socket, "250", __LINE__);
+ }
- // Ok now do the CC and BCC fields...
- @reset($bcc);
- while(list(, $bcc_address) = each($bcc))
- {
- // Add an additional bit of error checking to bcc header...
- $bcc_address = trim($bcc_address);
- if (preg_match('#[^ ]+\@[^ ]+#', $bcc_address))
- {
- enano_fputs($socket, "RCPT TO: <$bcc_address>\r\n");
- smtp_get_response($socket, "250", __LINE__);
- }
- }
+ // Ok now do the CC and BCC fields...
+ @reset($bcc);
+ while(list(, $bcc_address) = each($bcc))
+ {
+ // Add an additional bit of error checking to bcc header...
+ $bcc_address = trim($bcc_address);
+ if (preg_match('#[^ ]+\@[^ ]+#', $bcc_address))
+ {
+ enano_fputs($socket, "RCPT TO: <$bcc_address>\r\n");
+ smtp_get_response($socket, "250", __LINE__);
+ }
+ }
- @reset($cc);
- while(list(, $cc_address) = each($cc))
- {
- // Add an additional bit of error checking to cc header
- $cc_address = trim($cc_address);
- if (preg_match('#[^ ]+\@[^ ]+#', $cc_address))
- {
- enano_fputs($socket, "RCPT TO: <$cc_address>\r\n");
- smtp_get_response($socket, "250", __LINE__);
- }
- }
+ @reset($cc);
+ while(list(, $cc_address) = each($cc))
+ {
+ // Add an additional bit of error checking to cc header
+ $cc_address = trim($cc_address);
+ if (preg_match('#[^ ]+\@[^ ]+#', $cc_address))
+ {
+ enano_fputs($socket, "RCPT TO: <$cc_address>\r\n");
+ smtp_get_response($socket, "250", __LINE__);
+ }
+ }
- // Ok now we tell the server we are ready to start sending data
- enano_fputs($socket, "DATA\r\n");
+ // Ok now we tell the server we are ready to start sending data
+ enano_fputs($socket, "DATA\r\n");
- // This is the last response code we look for until the end of the message.
- smtp_get_response($socket, "354", __LINE__);
+ // This is the last response code we look for until the end of the message.
+ smtp_get_response($socket, "354", __LINE__);
- // Send the Subject Line...
- enano_fputs($socket, "Subject: $subject\r\n");
+ // Send the Subject Line...
+ enano_fputs($socket, "Subject: $subject\r\n");
- // Now the To Header.
- enano_fputs($socket, "To: $mail_to\r\n");
+ // Now the To Header.
+ enano_fputs($socket, "To: $mail_to\r\n");
- // Now any custom headers....
- enano_fputs($socket, "$headers\r\n\r\n");
+ // Now any custom headers....
+ enano_fputs($socket, "$headers\r\n\r\n");
- // Ok now we are ready for the message...
- enano_fputs($socket, "$message\r\n");
+ // Ok now we are ready for the message...
+ enano_fputs($socket, "$message\r\n");
- // Ok the all the ingredients are mixed in let's cook this puppy...
- enano_fputs($socket, ".\r\n");
- smtp_get_response($socket, "250", __LINE__);
+ // Ok the all the ingredients are mixed in let's cook this puppy...
+ enano_fputs($socket, ".\r\n");
+ smtp_get_response($socket, "250", __LINE__);
- // Now tell the server we are done and close the socket...
- enano_fputs($socket, "QUIT\r\n");
- fclose($socket);
+ // Now tell the server we are done and close the socket...
+ enano_fputs($socket, "QUIT\r\n");
+ fclose($socket);
- return TRUE;
+ return TRUE;
}
/**
@@ -918,85 +1183,41 @@
return $r;
}
+/**
+ * What kinda sh** was I thinking when I wrote this. Deprecated.
+ */
+
function _dualurlenc($t) {
return rawurlencode(rawurlencode($t));
}
-
+
+/**
+ * Badly named function to send back eval'able Javascript code with an error message. Deprecated, use JSON instead.
+ * @param string Message to send
+ */
+
function _die($t) {
$_ob = 'document.getElementById("ajaxEditContainer").innerHTML = unescape(\'' . rawurlencode('' . $t . '') . '\')';
die($_ob);
}
+/**
+ * Same as _die(), but sends an SQL backtrace with the error message, and doesn't halt execution.
+ * @param string Message to send
+ */
+
function jsdie($text) {
global $db, $session, $paths, $template, $plugins; // Common objects
$text = rawurlencode($text . "\n\nSQL Backtrace:\n" . $db->sql_backtrace());
echo 'document.getElementById("ajaxEditContainer").innerHTML = unescape(\''.$text.'\');';
}
-// HTML sanitizing function - written by Kallahar
-// Original function at: http://quickwired.com/kallahar/smallprojects/php_xss_filter_function.php
-
-// UNUSED - todo: remove this in gold or put it to use
-
-function RemoveXSS($val) {
- // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
- // this prevents some character re-spacing such as
- // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
- $val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);
-
- // straight replacements, the user should never need these since they're normal characters
- // this prevents like
- $search = 'abcdefghijklmnopqrstuvwxyz';
- $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
- $search .= '1234567890!@#$%^&*()';
- $search .= '~`";:?+/={}[]-_|\'\\';
- for ($i = 0; $i < strlen($search); $i++) {
- // ;? matches the ;, which is optional
- // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
-
- // @ @ search for the hex values
- $val = preg_replace('/([x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
- // @ @ 0{0,7} matches '0' zero to seven times
- $val = preg_replace('/({0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
- }
-
- // now the only remaining whitespace attacks are \t, \n, and \r
- $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
- $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
- $ra = array_merge($ra1, $ra2);
-
- $found = true; // keep replacing as long as the previous round replaced something
- while ($found == true) {
- $val_before = $val;
- for ($i = 0; $i < sizeof($ra); $i++) {
- $pattern = '/';
- for ($j = 0; $j < strlen($ra[$i]); $j++) {
- if ($j > 0) {
- $pattern .= '(';
- $pattern .= '([x|X]0{0,8}([9][a][b]);?)?';
- $pattern .= '|({0,8}([9][10][13]);?)?';
- $pattern .= ')?';
- }
- $pattern .= $ra[$i][$j];
- }
- $pattern .= '/i';
- $replacement = substr($ra[$i], 0, 2).''.substr($ra[$i], 2); // add in <> to nerf the tag
- $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
- if ($val_before == $val) {
- // no replacements were made, so exit the loop
- $found = false;
- }
- }
- }
- return $val;
-}
-
/**
* Capitalizes the first letter of a string
* @param $text string the text to be transformed
* @return string
*/
-
+
function capitalize_first_letter($text)
{
return strtoupper(substr($text, 0, 1)) . substr($text, 1);
@@ -1008,7 +1229,7 @@
* @param $value int the value to switch off
* @return bool
*/
-
+
function is_bit($bitfield, $value)
{
return ( $bitfield & $value ) ? true : false;
@@ -1019,7 +1240,7 @@
* @param $text the text to process
* @return string
*/
-
+
function trim_spaces($text)
{
$d = true;
@@ -1040,10 +1261,10 @@
* @param $inc int size of each block
* @return array
*/
-
+
function enano_str_split($text, $inc = 1)
{
- if($inc < 1)
+ if($inc < 1)
{
return false;
}
@@ -1078,10 +1299,10 @@
/**
* Generates and/or prints a human-readable backtrace
- * @param bool $return - if true, this function returns a string, otherwise returns null
+ * @param bool $return - if true, this function returns a string, otherwise returns null and prints the backtrace
* @return mixed
*/
-
+
function enano_debug_print_backtrace($return = false)
{
ob_start();
@@ -1109,7 +1330,7 @@
* @param optional string $suffix text after each hex character
* @return string
*/
-
+
function hexencode($text, $prefix = '%', $suffix = '')
{
$arr = enano_str_split($text);
@@ -1127,7 +1348,7 @@
* Enano-ese equivalent of get_magic_quotes_gpc()
* @return bool
*/
-
+
function enano_get_magic_quotes_gpc()
{
if(function_exists('get_magic_quotes_gpc'))
@@ -1145,7 +1366,7 @@
* @param array
* @return array
*/
-
+
function stripslashes_recurse($arr)
{
foreach($arr as $k => $xxxx)
@@ -1164,7 +1385,7 @@
* @param array
* @return array
*/
-
+
function strip_nul_chars($arr)
{
foreach($arr as $k => $xxxx_unused)
@@ -1179,7 +1400,7 @@
}
/**
- * If magic_quotes_gpc is on, calls stripslashes() on everything in $_GET/$_POST/$_COOKIE
+ * If magic_quotes_gpc is on, calls stripslashes() on everything in $_GET/$_POST/$_COOKIE. Also strips any NUL characters from incoming requests, as these are typically malicious.
* @ignore - this doesn't work too well in my tests
* @todo port version from the PHP manual
* @return void
@@ -1201,10 +1422,10 @@
/**
* A very basic single-character compression algorithm for binary strings/bitfields
- * @param string $bits the text to compress
+ * @param string $bits the text to compress, should be only 1s and 0s
* @return string
*/
-
+
function compress_bitfield($bits)
{
$crc32 = crc32($bits);
@@ -1272,7 +1493,7 @@
* @param string $bits the compressed bitfield
* @return string the uncompressed, original (we hope) bitfield OR bool false on error
*/
-
+
function uncompress_bitfield($bits)
{
if(substr($bits, 0, 4) != 'cbf:')
@@ -1352,7 +1573,7 @@
);
$collist[] = $field;
}
-
+
if ( $structure )
{
$db->sql_query('SET SQL_QUOTE_SHOW_CREATE = 0;');
@@ -1382,7 +1603,7 @@
$struct = implode("", $struct_arr);
}
}
-
+
// Structuring complete
if($data)
{
@@ -1441,7 +1662,7 @@
* Encodes a string value for use in an INSERT statement for given column type $type.
* @access private
*/
-
+
function mysql_encode_column($input, $type)
{
global $db, $session, $paths, $template, $plugins; // Common objects
@@ -1529,16 +1750,16 @@
function sanitize_html($html, $filter_php = true)
{
-
+
$html = preg_replace('#<([a-z]+)([\s]+)([^>]+?)'.htmlalternatives('javascript:').'(.+?)>(.*?)\\1>#is', '<\\1\\2\\3javascript:\\59>\\60</\\1>', $html);
$html = preg_replace('#<([a-z]+)([\s]+)([^>]+?)'.htmlalternatives('javascript:').'(.+?)>#is', '<\\1\\2\\3javascript:\\59>', $html);
-
+
if($filter_php)
$html = str_replace(
Array('', '%>'),
Array('<?php', '<?', '<%', '?>', '%>'),
$html);
-
+
$tag_whitelist = array_keys ( setupAttributeWhitelist() );
if ( !$filter_php )
$tag_whitelist[] = '?php';
@@ -1565,7 +1786,7 @@
$quote_char = $chr;
}
if ( $chr == '<' && !$in_tag && $next != '/' )
- {
+ {
// start of a tag
$tag_start = $i;
$in_tag = true;
@@ -1576,26 +1797,26 @@
$full_tag = substr($html, $tag_start, ( $i - $tag_start ) + 1 );
$l = strlen($tag_name) + 2;
$attribs_only = trim( substr($full_tag, $l, ( strlen($full_tag) - $l - 1 ) ) );
-
+
// Debugging message
// echo htmlspecialchars($full_tag) . ' ';
-
+
if ( !in_array($tag_name, $tag_whitelist) )
{
// Illegal tag
//echo $tag_name . ' ';
-
+
$s = ( empty($attribs_only) ) ? '' : ' ';
-
+
$sanitized = '<' . $tag_name . $s . $attribs_only . '>';
-
+
$html = substr($html, 0, $tag_start) . $sanitized . substr($html, $i + 1);
$html = str_replace('' . $tag_name . '>', '</' . $tag_name . '>', $html);
$new_i = $tag_start + strlen($sanitized);
-
+
$len = strlen($html);
$i = $new_i;
-
+
$in_tag = false;
$tag_name = '';
continue;
@@ -1606,14 +1827,14 @@
continue;
$f = fixTagAttributes( $attribs_only, $tag_name );
$s = ( empty($f) ) ? '' : ' ';
-
+
$sanitized = '<' . $tag_name . $f . '>';
$new_i = $tag_start + strlen($sanitized);
-
+
$html = substr($html, 0, $tag_start) . $sanitized . substr($html, $i + 1);
$len = strlen($html);
$i = $new_i;
-
+
$in_tag = false;
$tag_name = '';
continue;
@@ -1629,20 +1850,20 @@
$trk_name = false;
}
}
-
+
}
-
+
// Vulnerability from ha.ckers.org/xss.html:
//