From 7e48cf6266338bfdeb11e0283aef6a216d3ff20c Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 14:51:10 +0700 Subject: [PATCH 01/94] csrf_class --- protection/csrf/class_csrf.php | 104 +++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 protection/csrf/class_csrf.php diff --git a/protection/csrf/class_csrf.php b/protection/csrf/class_csrf.php new file mode 100644 index 00000000..90ef70f3 --- /dev/null +++ b/protection/csrf/class_csrf.php @@ -0,0 +1,104 @@ +"; + } + + /** + * Returns true if user-submitted POST token is + * identical to the previously stored SESSION token. + * Returns false otherwise. + */ + public static function isValid() + { + if (isset($_POST['token'])) + { + $user_token = $_POST['token']; + $stored_token = $_SESSION['token']; + return hash_equals($_SESSION['token'], $_POST['token']); + } + else + { + return false; + } + } + + /** + * You can simply check the token validity and + * handle the failure yourself, or you can use + * this "stop-everything-on-failure" method. + */ + public static function exitOnFailure() + { + if (!self::isValid()) + { + exit('Invalid Security Token.'); + } + } + + /** + * This doesn't have to be used but it + * checks to see if the token is recent. + */ + public static function isRecent() + { + if (isset($_SESSION['token_time'])) + { + $stored_time = $_SESSION['token_time']; + return ($stored_time + self::$max_elapsed) >= time(); + } + else + { + self::destroyToken(); + return false; + } + } +} From 0f9050905e53928ac118ae33185cd7185b0b4518 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 16:12:36 +0700 Subject: [PATCH 02/94] HTMLPurifier.autoload --- .../library/HTMLPurifier.autoload.php | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.autoload.php diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier.autoload.php b/protection/xss/htmlpurifier/library/HTMLPurifier.autoload.php new file mode 100644 index 00000000..d36d9959 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier.autoload.php @@ -0,0 +1,47 @@ + Date: Wed, 12 Sep 2018 16:13:51 +0700 Subject: [PATCH 03/94] another files in library --- .../library/HTMLPurifier.auto.php | 11 + .../library/HTMLPurifier.autoload-legacy.php | 15 + .../library/HTMLPurifier.composer.php | 4 + .../library/HTMLPurifier.func.php | 25 ++ .../library/HTMLPurifier.includes.php | 234 ++++++++++++++ .../library/HTMLPurifier.kses.php | 30 ++ .../library/HTMLPurifier.path.php | 11 + .../xss/htmlpurifier/library/HTMLPurifier.php | 292 ++++++++++++++++++ .../library/HTMLPurifier.safe-includes.php | 228 ++++++++++++++ 9 files changed, 850 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.auto.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.autoload-legacy.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.composer.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.func.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.includes.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.kses.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.path.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier.safe-includes.php diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier.auto.php b/protection/xss/htmlpurifier/library/HTMLPurifier.auto.php new file mode 100644 index 00000000..c810e87b --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier.auto.php @@ -0,0 +1,11 @@ +purify($html, $config); +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier.includes.php b/protection/xss/htmlpurifier/library/HTMLPurifier.includes.php new file mode 100644 index 00000000..c3318b3a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier.includes.php @@ -0,0 +1,234 @@ + $attributes) { + $allowed_elements[$element] = true; + foreach ($attributes as $attribute => $x) { + $allowed_attributes["$element.$attribute"] = true; + } + } + $config->set('HTML.AllowedElements', $allowed_elements); + $config->set('HTML.AllowedAttributes', $allowed_attributes); + if ($allowed_protocols !== null) { + $config->set('URI.AllowedSchemes', $allowed_protocols); + } + $purifier = new HTMLPurifier($config); + return $purifier->purify($string); +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier.path.php b/protection/xss/htmlpurifier/library/HTMLPurifier.path.php new file mode 100644 index 00000000..353492a1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier.path.php @@ -0,0 +1,11 @@ +config = HTMLPurifier_Config::create($config); + $this->strategy = new HTMLPurifier_Strategy_Core(); + } + + /** + * Adds a filter to process the output. First come first serve + * + * @param HTMLPurifier_Filter $filter HTMLPurifier_Filter object + */ + public function addFilter($filter) + { + trigger_error( + 'HTMLPurifier->addFilter() is deprecated, use configuration directives' . + ' in the Filter namespace or Filter.Custom', + E_USER_WARNING + ); + $this->filters[] = $filter; + } + + /** + * Filters an HTML snippet/document to be XSS-free and standards-compliant. + * + * @param string $html String of HTML to purify + * @param HTMLPurifier_Config $config Config object for this operation, + * if omitted, defaults to the config object specified during this + * object's construction. The parameter can also be any type + * that HTMLPurifier_Config::create() supports. + * + * @return string Purified HTML + */ + public function purify($html, $config = null) + { + // :TODO: make the config merge in, instead of replace + $config = $config ? HTMLPurifier_Config::create($config) : $this->config; + + // implementation is partially environment dependant, partially + // configuration dependant + $lexer = HTMLPurifier_Lexer::create($config); + + $context = new HTMLPurifier_Context(); + + // setup HTML generator + $this->generator = new HTMLPurifier_Generator($config, $context); + $context->register('Generator', $this->generator); + + // set up global context variables + if ($config->get('Core.CollectErrors')) { + // may get moved out if other facilities use it + $language_factory = HTMLPurifier_LanguageFactory::instance(); + $language = $language_factory->create($config, $context); + $context->register('Locale', $language); + + $error_collector = new HTMLPurifier_ErrorCollector($context); + $context->register('ErrorCollector', $error_collector); + } + + // setup id_accumulator context, necessary due to the fact that + // AttrValidator can be called from many places + $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context); + $context->register('IDAccumulator', $id_accumulator); + + $html = HTMLPurifier_Encoder::convertToUTF8($html, $config, $context); + + // setup filters + $filter_flags = $config->getBatch('Filter'); + $custom_filters = $filter_flags['Custom']; + unset($filter_flags['Custom']); + $filters = array(); + foreach ($filter_flags as $filter => $flag) { + if (!$flag) { + continue; + } + if (strpos($filter, '.') !== false) { + continue; + } + $class = "HTMLPurifier_Filter_$filter"; + $filters[] = new $class; + } + foreach ($custom_filters as $filter) { + // maybe "HTMLPurifier_Filter_$filter", but be consistent with AutoFormat + $filters[] = $filter; + } + $filters = array_merge($filters, $this->filters); + // maybe prepare(), but later + + for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) { + $html = $filters[$i]->preFilter($html, $config, $context); + } + + // purified HTML + $html = + $this->generator->generateFromTokens( + // list of tokens + $this->strategy->execute( + // list of un-purified tokens + $lexer->tokenizeHTML( + // un-purified HTML + $html, + $config, + $context + ), + $config, + $context + ) + ); + + for ($i = $filter_size - 1; $i >= 0; $i--) { + $html = $filters[$i]->postFilter($html, $config, $context); + } + + $html = HTMLPurifier_Encoder::convertFromUTF8($html, $config, $context); + $this->context =& $context; + return $html; + } + + /** + * Filters an array of HTML snippets + * + * @param string[] $array_of_html Array of html snippets + * @param HTMLPurifier_Config $config Optional config object for this operation. + * See HTMLPurifier::purify() for more details. + * + * @return string[] Array of purified HTML + */ + public function purifyArray($array_of_html, $config = null) + { + $context_array = array(); + foreach ($array_of_html as $key => $html) { + $array_of_html[$key] = $this->purify($html, $config); + $context_array[$key] = $this->context; + } + $this->context = $context_array; + return $array_of_html; + } + + /** + * Singleton for enforcing just one HTML Purifier in your system + * + * @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype + * HTMLPurifier instance to overload singleton with, + * or HTMLPurifier_Config instance to configure the + * generated version with. + * + * @return HTMLPurifier + */ + public static function instance($prototype = null) + { + if (!self::$instance || $prototype) { + if ($prototype instanceof HTMLPurifier) { + self::$instance = $prototype; + } elseif ($prototype) { + self::$instance = new HTMLPurifier($prototype); + } else { + self::$instance = new HTMLPurifier(); + } + } + return self::$instance; + } + + /** + * Singleton for enforcing just one HTML Purifier in your system + * + * @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype + * HTMLPurifier instance to overload singleton with, + * or HTMLPurifier_Config instance to configure the + * generated version with. + * + * @return HTMLPurifier + * @note Backwards compatibility, see instance() + */ + public static function getInstance($prototype = null) + { + return HTMLPurifier::instance($prototype); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier.safe-includes.php b/protection/xss/htmlpurifier/library/HTMLPurifier.safe-includes.php new file mode 100644 index 00000000..852a0b85 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier.safe-includes.php @@ -0,0 +1,228 @@ + Date: Wed, 12 Sep 2018 17:02:47 +0700 Subject: [PATCH 04/94] protect against xss --- documentation/index.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/documentation/index.php b/documentation/index.php index ffa0a10c..f3fb0dd6 100644 --- a/documentation/index.php +++ b/documentation/index.php @@ -11,13 +11,18 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); include(TR_INCLUDE_PATH.'vitals.inc.php'); include(TR_INCLUDE_PATH.'handbook_pages.inc.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); global $handbook_pages; if (isset($_GET['p'])) { - $p = htmlentities($_GET['p']); + $p = $purifier->purify(htmlentities($_GET['p'])); } else { // go to first handbook page defined in $handbook_pages foreach ($handbook_pages as $page_key => $page_value) From 522d65d305c46535f5ecabc770487adaf076ae3f Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 17:09:09 +0700 Subject: [PATCH 05/94] protect against csrf and xss 1. add paths for protecting against csrf and xss 2. check Token is valid and recent --- profile/index.php | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/profile/index.php b/profile/index.php index c5808a44..0a252408 100644 --- a/profile/index.php +++ b/profile/index.php @@ -11,8 +11,11 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/UsersDAO.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); unset($_SESSION['course_id']); global $_current_user; @@ -32,13 +35,15 @@ } if (isset($_POST['submit'])) { - if (isset($_POST['is_author'])) $is_author = 1; - else $is_author = 0; + if (Token::isValid() AND Token::isRecent()) + { + if (isset($_POST['is_author'])) $is_author = 1; + else $is_author = 0; - $usersDAO = new UsersDAO(); - $user_row = $usersDAO->getUserByID($_SESSION['user_id']); + $usersDAO = new UsersDAO(); + $user_row = $usersDAO->getUserByID($_SESSION['user_id']); - if ($usersDAO->Update($_SESSION['user_id'], + if ($usersDAO->Update($_SESSION['user_id'], $user_row['user_group_id'], $user_row['login'], $user_row['email'], @@ -54,8 +59,12 @@ $_POST['postal_code'], $_POST['status'])) + { + $msg->addFeedback('PROFILE_UPDATED'); + } + } else { - $msg->addFeedback('PROFILE_UPDATED'); + $msg->addError('INVALID_TOKEN'); } } @@ -72,4 +81,4 @@ $onload = 'document.form.first_name.focus();'; $savant->display('profile/index.tmpl.php'); -?> \ No newline at end of file +?> From d94f4beb5265ca9174751b85b10d681e07614419 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 17:11:43 +0700 Subject: [PATCH 06/94] protect against csrf and xss 1. add paths for protecting csrf and xss 2. check Token is valid and recent --- profile/change_email.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/profile/change_email.php b/profile/change_email.php index 497308e2..8a355512 100644 --- a/profile/change_email.php +++ b/profile/change_email.php @@ -11,8 +11,11 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/UsersDAO.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); global $_current_user; @@ -31,10 +34,12 @@ exit; } -if (isset($_POST['submit'])) +if (isset($_POST['submit'])) { - $this_password = $_POST['form_password_hidden']; - + if (Token::isValid() AND Token::isRecent()) + { + $this_password = $_POST['form_password_hidden']; + // password check if (!empty($this_password)) { @@ -55,7 +60,7 @@ header('Location: change_email.php'); exit; } - + // email check if ($_POST['email'] == '') { @@ -78,6 +83,7 @@ if (!$msg->containsErrors()) { + if (defined('TR_EMAIL_CONFIRMATION') && TR_EMAIL_CONFIRMATION) { //send confirmation email @@ -110,6 +116,10 @@ $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); } } + } else + { + $msg->addError('INVALID_TOKEN'); + } } $row = $_current_user->getInfo(); @@ -122,4 +132,4 @@ $savant->assign('row', $row); $savant->display('profile/change_email.tmpl.php'); -?> \ No newline at end of file +?> From 50c408bb33be4253ddaef4df87d4ba3013ad1ea9 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 17:14:39 +0700 Subject: [PATCH 07/94] protect against csrf and xss 1. add paths for protecting against csrf and xss 2. check Token is valid and recent --- profile/change_password.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/profile/change_password.php b/profile/change_password.php index 0f5ac868..6a78a600 100644 --- a/profile/change_password.php +++ b/profile/change_password.php @@ -11,7 +11,11 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); global $_current_user; @@ -29,12 +33,14 @@ } if (isset($_POST['submit'])) { - if (!empty($_POST['form_old_password_hidden'])) + if (Token::isValid() AND Token::isRecent()) + { + if (!empty($_POST['form_old_password_hidden'])) { //check if old password entered is correct if ($row = $_current_user->getInfo()) { - if ($row['password'] != $_POST['form_old_password_hidden']) + if ($row['password'] != $purifier->purify($_POST['form_old_password_hidden'])) { $msg->addError('WRONG_PASSWORD'); Header('Location: change_password.php'); @@ -64,8 +70,9 @@ } if (!$msg->containsErrors()) { + // insert into the db. - $password = $_POST['form_password_hidden']; + $password = $purifier->purify($_POST['form_password_hidden']); if (!$_current_user->setPassword($password)) { @@ -77,9 +84,13 @@ $msg->addFeedback('PASSWORD_CHANGED'); } + } else + { + $msg->addError('INVALID_TOKEN'); + } } /* template starts here */ $savant->display('profile/change_password.tmpl.php'); -?> \ No newline at end of file +?> From 077d9c3b642f9c7809e36af06387e5fc17403722 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 17:19:25 +0700 Subject: [PATCH 08/94] protect against xss and csrf 1. start session, add Token 2. autocomplete = "off" --- themes/default/profile/index.tmpl.php | 35 +++++++++++++++++---------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/themes/default/profile/index.tmpl.php b/themes/default/profile/index.tmpl.php index 8fe32d75..8d47ea0f 100644 --- a/themes/default/profile/index.tmpl.php +++ b/themes/default/profile/index.tmpl.php @@ -10,11 +10,19 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + // show or hide the author information based on the status of the checkbox "author content" global $onload; $onload = "if (jQuery('#is_author').attr('checked')) jQuery('#table_is_author').show(); else jQuery('#table_is_author').hide();"; require(TR_INCLUDE_PATH.'header.inc.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + //Timer $mtime = microtime(); $mtime = explode(' ', $mtime); @@ -22,7 +30,7 @@ $starttime = $mtime; ?> -
+ @@ -38,7 +46,7 @@ : - row['login'])); ?> + purify(stripslashes(htmlspecialchars($this->row['login']))); ?> @@ -50,17 +58,17 @@ *: - + *: - + - onclick="if (this.checked) jQuery('#table_is_author').show('slow'); else jQuery('#table_is_author').hide('slow');" /> + onclick="if (this.checked) jQuery('#table_is_author').show('slow'); else jQuery('#table_is_author').hide('slow');" /> @@ -70,37 +78,37 @@ - + - + - + - + - + - + - +
:
:
:
:
:
:
:
@@ -111,6 +119,7 @@

+

@@ -124,4 +133,4 @@
- \ No newline at end of file + From ed15eb7d71abc8c9798566c51199636d491634bf Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 17:21:03 +0700 Subject: [PATCH 09/94] protect against xss and csrf 1. start session, add Token 2. autocomplete="off" --- themes/default/profile/change_email.tmpl.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/themes/default/profile/change_email.tmpl.php b/themes/default/profile/change_email.tmpl.php index acb4bce6..8fe54796 100644 --- a/themes/default/profile/change_email.tmpl.php +++ b/themes/default/profile/change_email.tmpl.php @@ -10,9 +10,17 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + global $onload; $onload = 'document.form.form_password.focus();'; -require(TR_INCLUDE_PATH.'header.inc.php'); +require(TR_INCLUDE_PATH.'header.inc.php'); + +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); ?> @@ -29,7 +37,7 @@ function encrypt_password()
-
+ @@ -49,13 +57,14 @@ function encrypt_password() s with a . + + $ws_accum =& $initial_ws; + + foreach ($children as $node) { + if ($node instanceof HTMLPurifier_Node_Comment) { + $ws_accum[] = $node; + continue; + } + switch ($node->name) { + case 'tbody': + $tbody_mode = true; + // fall through + case 'tr': + $content[] = $node; + $ws_accum =& $content; + break; + case 'caption': + // there can only be one caption! + if ($caption !== false) break; + $caption = $node; + $ws_accum =& $after_caption_ws; + break; + case 'thead': + $tbody_mode = true; + // XXX This breaks rendering properties with + // Firefox, which never floats a to + // the top. Ever. (Our scheme will float the + // first to the top.) So maybe + // s that are not first should be + // turned into ? Very tricky, indeed. + if ($thead === false) { + $thead = $node; + $ws_accum =& $after_thead_ws; + } else { + // Oops, there's a second one! What + // should we do? Current behavior is to + // transmutate the first and last entries into + // tbody tags, and then put into content. + // Maybe a better idea is to *attach + // it* to the existing thead or tfoot? + // We don't do this, because Firefox + // doesn't float an extra tfoot to the + // bottom like it does for the first one. + $node->name = 'tbody'; + $content[] = $node; + $ws_accum =& $content; + } + break; + case 'tfoot': + // see above for some aveats + $tbody_mode = true; + if ($tfoot === false) { + $tfoot = $node; + $ws_accum =& $after_tfoot_ws; + } else { + $node->name = 'tbody'; + $content[] = $node; + $ws_accum =& $content; + } + break; + case 'colgroup': + case 'col': + $cols[] = $node; + $ws_accum =& $cols; + break; + case '#PCDATA': + // How is whitespace handled? We treat is as sticky to + // the *end* of the previous element. So all of the + // nonsense we have worked on is to keep things + // together. + if (!empty($node->is_whitespace)) { + $ws_accum[] = $node; + } + break; + } + } + + if (empty($content)) { + return false; + } + + $ret = $initial_ws; + if ($caption !== false) { + $ret[] = $caption; + $ret = array_merge($ret, $after_caption_ws); + } + if ($cols !== false) { + $ret = array_merge($ret, $cols); + } + if ($thead !== false) { + $ret[] = $thead; + $ret = array_merge($ret, $after_thead_ws); + } + if ($tfoot !== false) { + $ret[] = $tfoot; + $ret = array_merge($ret, $after_tfoot_ws); + } + + if ($tbody_mode) { + // we have to shuffle tr into tbody + $current_tr_tbody = null; + + foreach($content as $node) { + switch ($node->name) { + case 'tbody': + $current_tr_tbody = null; + $ret[] = $node; + break; + case 'tr': + if ($current_tr_tbody === null) { + $current_tr_tbody = new HTMLPurifier_Node_Element('tbody'); + $ret[] = $current_tr_tbody; + } + $current_tr_tbody->children[] = $node; + break; + case '#PCDATA': + //assert($node->is_whitespace); + if ($current_tr_tbody === null) { + $ret[] = $node; + } else { + $current_tr_tbody->children[] = $node; + } + break; + } + } + } else { + $ret = array_merge($ret, $content); + } + + return $ret; + + } +} + +// vim: et sw=4 sts=4 From 08b2110c0e541b977e0622f4b2492e10338d495e Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:38:42 +0700 Subject: [PATCH 24/94] Add files via upload --- .../library/HTMLPurifier/AttrDef/CSS.php | 136 +++++++++++ .../HTMLPurifier/AttrDef/CSS/AlphaValue.php | 34 +++ .../HTMLPurifier/AttrDef/CSS/Background.php | 111 +++++++++ .../AttrDef/CSS/BackgroundPosition.php | 157 +++++++++++++ .../HTMLPurifier/AttrDef/CSS/Border.php | 56 +++++ .../HTMLPurifier/AttrDef/CSS/Color.php | 161 +++++++++++++ .../HTMLPurifier/AttrDef/CSS/Composite.php | 48 ++++ .../AttrDef/CSS/DenyElementDecorator.php | 44 ++++ .../HTMLPurifier/AttrDef/CSS/Filter.php | 77 ++++++ .../library/HTMLPurifier/AttrDef/CSS/Font.php | 176 ++++++++++++++ .../HTMLPurifier/AttrDef/CSS/FontFamily.php | 219 ++++++++++++++++++ .../HTMLPurifier/AttrDef/CSS/Ident.php | 32 +++ .../AttrDef/CSS/ImportantDecorator.php | 56 +++++ .../HTMLPurifier/AttrDef/CSS/Length.php | 77 ++++++ .../HTMLPurifier/AttrDef/CSS/ListStyle.php | 112 +++++++++ .../HTMLPurifier/AttrDef/CSS/Multiple.php | 71 ++++++ .../HTMLPurifier/AttrDef/CSS/Number.php | 84 +++++++ .../HTMLPurifier/AttrDef/CSS/Percentage.php | 54 +++++ .../AttrDef/CSS/TextDecoration.php | 46 ++++ .../library/HTMLPurifier/AttrDef/CSS/URI.php | 77 ++++++ .../library/HTMLPurifier/AttrDef/Clone.php | 44 ++++ .../library/HTMLPurifier/AttrDef/Enum.php | 73 ++++++ .../HTMLPurifier/AttrDef/HTML/Bool.php | 48 ++++ .../HTMLPurifier/AttrDef/HTML/Class.php | 48 ++++ .../HTMLPurifier/AttrDef/HTML/Color.php | 51 ++++ .../HTMLPurifier/AttrDef/HTML/FrameTarget.php | 38 +++ .../library/HTMLPurifier/AttrDef/HTML/ID.php | 113 +++++++++ .../HTMLPurifier/AttrDef/HTML/Length.php | 56 +++++ .../HTMLPurifier/AttrDef/HTML/LinkTypes.php | 72 ++++++ .../HTMLPurifier/AttrDef/HTML/MultiLength.php | 60 +++++ .../HTMLPurifier/AttrDef/HTML/Nmtokens.php | 70 ++++++ .../HTMLPurifier/AttrDef/HTML/Pixels.php | 76 ++++++ .../library/HTMLPurifier/AttrDef/Integer.php | 91 ++++++++ .../library/HTMLPurifier/AttrDef/Lang.php | 86 +++++++ .../library/HTMLPurifier/AttrDef/Switch.php | 53 +++++ .../library/HTMLPurifier/AttrDef/Text.php | 21 ++ .../library/HTMLPurifier/AttrDef/URI.php | 111 +++++++++ .../HTMLPurifier/AttrDef/URI/Email.php | 20 ++ .../AttrDef/URI/Email/SimpleCheck.php | 29 +++ .../library/HTMLPurifier/AttrDef/URI/Host.php | 138 +++++++++++ .../library/HTMLPurifier/AttrDef/URI/IPv4.php | 45 ++++ .../library/HTMLPurifier/AttrDef/URI/IPv6.php | 89 +++++++ .../HTMLPurifier/AttrTransform/Background.php | 28 +++ .../HTMLPurifier/AttrTransform/BdoDir.php | 27 +++ .../HTMLPurifier/AttrTransform/BgColor.php | 28 +++ .../HTMLPurifier/AttrTransform/BoolToCSS.php | 47 ++++ .../HTMLPurifier/AttrTransform/Border.php | 26 +++ .../HTMLPurifier/AttrTransform/EnumToCSS.php | 68 ++++++ .../AttrTransform/ImgRequired.php | 47 ++++ .../HTMLPurifier/AttrTransform/ImgSpace.php | 61 +++++ .../HTMLPurifier/AttrTransform/Input.php | 56 +++++ .../HTMLPurifier/AttrTransform/Lang.php | 31 +++ .../HTMLPurifier/AttrTransform/Length.php | 45 ++++ .../HTMLPurifier/AttrTransform/Name.php | 33 +++ .../HTMLPurifier/AttrTransform/NameSync.php | 41 ++++ .../HTMLPurifier/AttrTransform/Nofollow.php | 52 +++++ .../HTMLPurifier/AttrTransform/SafeEmbed.php | 25 ++ .../HTMLPurifier/AttrTransform/SafeObject.php | 28 +++ .../HTMLPurifier/AttrTransform/SafeParam.php | 79 +++++++ .../AttrTransform/ScriptRequired.php | 23 ++ .../AttrTransform/TargetBlank.php | 45 ++++ .../AttrTransform/TargetNoopener.php | 37 +++ .../AttrTransform/TargetNoreferrer.php | 37 +++ .../HTMLPurifier/AttrTransform/Textarea.php | 27 +++ 64 files changed, 4151 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeParam.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php new file mode 100644 index 00000000..369db1e7 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php @@ -0,0 +1,136 @@ +parseCDATA($css); + + $definition = $config->getCSSDefinition(); + $allow_duplicates = $config->get("CSS.AllowDuplicates"); + + + // According to the CSS2.1 spec, the places where a + // non-delimiting semicolon can appear are in strings + // escape sequences. So here is some dumb hack to + // handle quotes. + $len = strlen($css); + $accum = ""; + $declarations = array(); + $quoted = false; + for ($i = 0; $i < $len; $i++) { + $c = strcspn($css, ";'\"", $i); + $accum .= substr($css, $i, $c); + $i += $c; + if ($i == $len) break; + $d = $css[$i]; + if ($quoted) { + $accum .= $d; + if ($d == $quoted) { + $quoted = false; + } + } else { + if ($d == ";") { + $declarations[] = $accum; + $accum = ""; + } else { + $accum .= $d; + $quoted = $d; + } + } + } + if ($accum != "") $declarations[] = $accum; + + $propvalues = array(); + $new_declarations = ''; + + /** + * Name of the current CSS property being validated. + */ + $property = false; + $context->register('CurrentCSSProperty', $property); + + foreach ($declarations as $declaration) { + if (!$declaration) { + continue; + } + if (!strpos($declaration, ':')) { + continue; + } + list($property, $value) = explode(':', $declaration, 2); + $property = trim($property); + $value = trim($value); + $ok = false; + do { + if (isset($definition->info[$property])) { + $ok = true; + break; + } + if (ctype_lower($property)) { + break; + } + $property = strtolower($property); + if (isset($definition->info[$property])) { + $ok = true; + break; + } + } while (0); + if (!$ok) { + continue; + } + // inefficient call, since the validator will do this again + if (strtolower(trim($value)) !== 'inherit') { + // inherit works for everything (but only on the base property) + $result = $definition->info[$property]->validate( + $value, + $config, + $context + ); + } else { + $result = 'inherit'; + } + if ($result === false) { + continue; + } + if ($allow_duplicates) { + $new_declarations .= "$property:$result;"; + } else { + $propvalues[$property] = $result; + } + } + + $context->destroy('CurrentCSSProperty'); + + // procedure does not write the new CSS simultaneously, so it's + // slightly inefficient, but it's the only way of getting rid of + // duplicates. Perhaps config to optimize it, but not now. + + foreach ($propvalues as $prop => $value) { + $new_declarations .= "$prop:$value;"; + } + + return $new_declarations ? $new_declarations : false; + + } + +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php new file mode 100644 index 00000000..1a30e8fe --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php @@ -0,0 +1,34 @@ + 1.0) { + $result = '1'; + } + return $result; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php new file mode 100644 index 00000000..ecd6e276 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php @@ -0,0 +1,111 @@ +getCSSDefinition(); + $this->info['background-color'] = $def->info['background-color']; + $this->info['background-image'] = $def->info['background-image']; + $this->info['background-repeat'] = $def->info['background-repeat']; + $this->info['background-attachment'] = $def->info['background-attachment']; + $this->info['background-position'] = $def->info['background-position']; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + // regular pre-processing + $string = $this->parseCDATA($string); + if ($string === '') { + return false; + } + + // munge rgb() decl if necessary + $string = $this->mungeRgb($string); + + // assumes URI doesn't have spaces in it + $bits = explode(' ', $string); // bits to process + + $caught = array(); + $caught['color'] = false; + $caught['image'] = false; + $caught['repeat'] = false; + $caught['attachment'] = false; + $caught['position'] = false; + + $i = 0; // number of catches + + foreach ($bits as $bit) { + if ($bit === '') { + continue; + } + foreach ($caught as $key => $status) { + if ($key != 'position') { + if ($status !== false) { + continue; + } + $r = $this->info['background-' . $key]->validate($bit, $config, $context); + } else { + $r = $bit; + } + if ($r === false) { + continue; + } + if ($key == 'position') { + if ($caught[$key] === false) { + $caught[$key] = ''; + } + $caught[$key] .= $r . ' '; + } else { + $caught[$key] = $r; + } + $i++; + break; + } + } + + if (!$i) { + return false; + } + if ($caught['position'] !== false) { + $caught['position'] = $this->info['background-position']-> + validate($caught['position'], $config, $context); + } + + $ret = array(); + foreach ($caught as $value) { + if ($value === false) { + continue; + } + $ret[] = $value; + } + + if (empty($ret)) { + return false; + } + return implode(' ', $ret); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php new file mode 100644 index 00000000..f95de5bb --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php @@ -0,0 +1,157 @@ + | | left | center | right + ] + [ + | | top | center | bottom + ]? + ] | + [ // this signifies that the vertical and horizontal adjectives + // can be arbitrarily ordered, however, there can only be two, + // one of each, or none at all + [ + left | center | right + ] || + [ + top | center | bottom + ] + ] + top, left = 0% + center, (none) = 50% + bottom, right = 100% +*/ + +/* QuirksMode says: + keyword + length/percentage must be ordered correctly, as per W3C + + Internet Explorer and Opera, however, support arbitrary ordering. We + should fix it up. + + Minor issue though, not strictly necessary. +*/ + +// control freaks may appreciate the ability to convert these to +// percentages or something, but it's not necessary + +/** + * Validates the value of background-position. + */ +class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef +{ + + /** + * @type HTMLPurifier_AttrDef_CSS_Length + */ + protected $length; + + /** + * @type HTMLPurifier_AttrDef_CSS_Percentage + */ + protected $percentage; + + public function __construct() + { + $this->length = new HTMLPurifier_AttrDef_CSS_Length(); + $this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage(); + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $string = $this->parseCDATA($string); + $bits = explode(' ', $string); + + $keywords = array(); + $keywords['h'] = false; // left, right + $keywords['v'] = false; // top, bottom + $keywords['ch'] = false; // center (first word) + $keywords['cv'] = false; // center (second word) + $measures = array(); + + $i = 0; + + $lookup = array( + 'top' => 'v', + 'bottom' => 'v', + 'left' => 'h', + 'right' => 'h', + 'center' => 'c' + ); + + foreach ($bits as $bit) { + if ($bit === '') { + continue; + } + + // test for keyword + $lbit = ctype_lower($bit) ? $bit : strtolower($bit); + if (isset($lookup[$lbit])) { + $status = $lookup[$lbit]; + if ($status == 'c') { + if ($i == 0) { + $status = 'ch'; + } else { + $status = 'cv'; + } + } + $keywords[$status] = $lbit; + $i++; + } + + // test for length + $r = $this->length->validate($bit, $config, $context); + if ($r !== false) { + $measures[] = $r; + $i++; + } + + // test for percentage + $r = $this->percentage->validate($bit, $config, $context); + if ($r !== false) { + $measures[] = $r; + $i++; + } + } + + if (!$i) { + return false; + } // no valid values were caught + + $ret = array(); + + // first keyword + if ($keywords['h']) { + $ret[] = $keywords['h']; + } elseif ($keywords['ch']) { + $ret[] = $keywords['ch']; + $keywords['cv'] = false; // prevent re-use: center = center center + } elseif (count($measures)) { + $ret[] = array_shift($measures); + } + + if ($keywords['v']) { + $ret[] = $keywords['v']; + } elseif ($keywords['cv']) { + $ret[] = $keywords['cv']; + } elseif (count($measures)) { + $ret[] = array_shift($measures); + } + + if (empty($ret)) { + return false; + } + return implode(' ', $ret); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php new file mode 100644 index 00000000..bd310ff2 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php @@ -0,0 +1,56 @@ +getCSSDefinition(); + $this->info['border-width'] = $def->info['border-width']; + $this->info['border-style'] = $def->info['border-style']; + $this->info['border-top-color'] = $def->info['border-top-color']; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $string = $this->parseCDATA($string); + $string = $this->mungeRgb($string); + $bits = explode(' ', $string); + $done = array(); // segments we've finished + $ret = ''; // return value + foreach ($bits as $bit) { + foreach ($this->info as $propname => $validator) { + if (isset($done[$propname])) { + continue; + } + $r = $validator->validate($bit, $config, $context); + if ($r !== false) { + $ret .= $r . ' '; + $done[$propname] = true; + break; + } + } + } + return rtrim($ret); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php new file mode 100644 index 00000000..d1b1b3c1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php @@ -0,0 +1,161 @@ +alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue(); + } + + /** + * @param string $color + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($color, $config, $context) + { + static $colors = null; + if ($colors === null) { + $colors = $config->get('Core.ColorKeywords'); + } + + $color = trim($color); + if ($color === '') { + return false; + } + + $lower = strtolower($color); + if (isset($colors[$lower])) { + return $colors[$lower]; + } + + if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) { + $length = strlen($color); + if (strpos($color, ')') !== $length - 1) { + return false; + } + + // get used function : rgb, rgba, hsl or hsla + $function = $matches[1]; + + $parameters_size = 3; + $alpha_channel = false; + if (substr($function, -1) === 'a') { + $parameters_size = 4; + $alpha_channel = true; + } + + /* + * Allowed types for values : + * parameter_position => [type => max_value] + */ + $allowed_types = array( + 1 => array('percentage' => 100, 'integer' => 255), + 2 => array('percentage' => 100, 'integer' => 255), + 3 => array('percentage' => 100, 'integer' => 255), + ); + $allow_different_types = false; + + if (strpos($function, 'hsl') !== false) { + $allowed_types = array( + 1 => array('integer' => 360), + 2 => array('percentage' => 100), + 3 => array('percentage' => 100), + ); + $allow_different_types = true; + } + + $values = trim(str_replace($function, '', $color), ' ()'); + + $parts = explode(',', $values); + if (count($parts) !== $parameters_size) { + return false; + } + + $type = false; + $new_parts = array(); + $i = 0; + + foreach ($parts as $part) { + $i++; + $part = trim($part); + + if ($part === '') { + return false; + } + + // different check for alpha channel + if ($alpha_channel === true && $i === count($parts)) { + $result = $this->alpha->validate($part, $config, $context); + + if ($result === false) { + return false; + } + + $new_parts[] = (string)$result; + continue; + } + + if (substr($part, -1) === '%') { + $current_type = 'percentage'; + } else { + $current_type = 'integer'; + } + + if (!array_key_exists($current_type, $allowed_types[$i])) { + return false; + } + + if (!$type) { + $type = $current_type; + } + + if ($allow_different_types === false && $type != $current_type) { + return false; + } + + $max_value = $allowed_types[$i][$current_type]; + + if ($current_type == 'integer') { + // Return value between range 0 -> $max_value + $new_parts[] = (int)max(min($part, $max_value), 0); + } elseif ($current_type == 'percentage') { + $new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%'; + } + } + + $new_values = implode(',', $new_parts); + + $color = $function . '(' . $new_values . ')'; + } else { + // hexadecimal handling + if ($color[0] === '#') { + $hex = substr($color, 1); + } else { + $hex = $color; + $color = '#' . $color; + } + $length = strlen($hex); + if ($length !== 3 && $length !== 6) { + return false; + } + if (!ctype_xdigit($hex)) { + return false; + } + } + return $color; + } + +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php new file mode 100644 index 00000000..38900232 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php @@ -0,0 +1,48 @@ +defs = $defs; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + foreach ($this->defs as $i => $def) { + $result = $this->defs[$i]->validate($string, $config, $context); + if ($result !== false) { + return $result; + } + } + return false; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php new file mode 100644 index 00000000..ff0d897e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php @@ -0,0 +1,44 @@ +def = $def; + $this->element = $element; + } + + /** + * Checks if CurrentToken is set and equal to $this->element + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $token = $context->get('CurrentToken', true); + if ($token && $token->name == $this->element) { + return false; + } + return $this->def->validate($string, $config, $context); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php new file mode 100644 index 00000000..019722a4 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php @@ -0,0 +1,77 @@ +intValidator = new HTMLPurifier_AttrDef_Integer(); + } + + /** + * @param string $value + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($value, $config, $context) + { + $value = $this->parseCDATA($value); + if ($value === 'none') { + return $value; + } + // if we looped this we could support multiple filters + $function_length = strcspn($value, '('); + $function = trim(substr($value, 0, $function_length)); + if ($function !== 'alpha' && + $function !== 'Alpha' && + $function !== 'progid:DXImageTransform.Microsoft.Alpha' + ) { + return false; + } + $cursor = $function_length + 1; + $parameters_length = strcspn($value, ')', $cursor); + $parameters = substr($value, $cursor, $parameters_length); + $params = explode(',', $parameters); + $ret_params = array(); + $lookup = array(); + foreach ($params as $param) { + list($key, $value) = explode('=', $param); + $key = trim($key); + $value = trim($value); + if (isset($lookup[$key])) { + continue; + } + if ($key !== 'opacity') { + continue; + } + $value = $this->intValidator->validate($value, $config, $context); + if ($value === false) { + continue; + } + $int = (int)$value; + if ($int > 100) { + $value = '100'; + } + if ($int < 0) { + $value = '0'; + } + $ret_params[] = "$key=$value"; + $lookup[$key] = true; + } + $ret_parameters = implode(',', $ret_params); + $ret_function = "$function($ret_parameters)"; + return $ret_function; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php new file mode 100644 index 00000000..b9b63f8e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php @@ -0,0 +1,176 @@ +getCSSDefinition(); + $this->info['font-style'] = $def->info['font-style']; + $this->info['font-variant'] = $def->info['font-variant']; + $this->info['font-weight'] = $def->info['font-weight']; + $this->info['font-size'] = $def->info['font-size']; + $this->info['line-height'] = $def->info['line-height']; + $this->info['font-family'] = $def->info['font-family']; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + static $system_fonts = array( + 'caption' => true, + 'icon' => true, + 'menu' => true, + 'message-box' => true, + 'small-caption' => true, + 'status-bar' => true + ); + + // regular pre-processing + $string = $this->parseCDATA($string); + if ($string === '') { + return false; + } + + // check if it's one of the keywords + $lowercase_string = strtolower($string); + if (isset($system_fonts[$lowercase_string])) { + return $lowercase_string; + } + + $bits = explode(' ', $string); // bits to process + $stage = 0; // this indicates what we're looking for + $caught = array(); // which stage 0 properties have we caught? + $stage_1 = array('font-style', 'font-variant', 'font-weight'); + $final = ''; // output + + for ($i = 0, $size = count($bits); $i < $size; $i++) { + if ($bits[$i] === '') { + continue; + } + switch ($stage) { + case 0: // attempting to catch font-style, font-variant or font-weight + foreach ($stage_1 as $validator_name) { + if (isset($caught[$validator_name])) { + continue; + } + $r = $this->info[$validator_name]->validate( + $bits[$i], + $config, + $context + ); + if ($r !== false) { + $final .= $r . ' '; + $caught[$validator_name] = true; + break; + } + } + // all three caught, continue on + if (count($caught) >= 3) { + $stage = 1; + } + if ($r !== false) { + break; + } + case 1: // attempting to catch font-size and perhaps line-height + $found_slash = false; + if (strpos($bits[$i], '/') !== false) { + list($font_size, $line_height) = + explode('/', $bits[$i]); + if ($line_height === '') { + // ooh, there's a space after the slash! + $line_height = false; + $found_slash = true; + } + } else { + $font_size = $bits[$i]; + $line_height = false; + } + $r = $this->info['font-size']->validate( + $font_size, + $config, + $context + ); + if ($r !== false) { + $final .= $r; + // attempt to catch line-height + if ($line_height === false) { + // we need to scroll forward + for ($j = $i + 1; $j < $size; $j++) { + if ($bits[$j] === '') { + continue; + } + if ($bits[$j] === '/') { + if ($found_slash) { + return false; + } else { + $found_slash = true; + continue; + } + } + $line_height = $bits[$j]; + break; + } + } else { + // slash already found + $found_slash = true; + $j = $i; + } + if ($found_slash) { + $i = $j; + $r = $this->info['line-height']->validate( + $line_height, + $config, + $context + ); + if ($r !== false) { + $final .= '/' . $r; + } + } + $final .= ' '; + $stage = 2; + break; + } + return false; + case 2: // attempting to catch font-family + $font_family = + implode(' ', array_slice($bits, $i, $size - $i)); + $r = $this->info['font-family']->validate( + $font_family, + $config, + $context + ); + if ($r !== false) { + $final .= $r . ' '; + // processing completed successfully + return rtrim($final); + } + return false; + } + } + return false; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php new file mode 100644 index 00000000..f9af36d7 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php @@ -0,0 +1,219 @@ +mask = '_- '; + for ($c = 'a'; $c <= 'z'; $c++) { + $this->mask .= $c; + } + for ($c = 'A'; $c <= 'Z'; $c++) { + $this->mask .= $c; + } + for ($c = '0'; $c <= '9'; $c++) { + $this->mask .= $c; + } // cast-y, but should be fine + // special bytes used by UTF-8 + for ($i = 0x80; $i <= 0xFF; $i++) { + // We don't bother excluding invalid bytes in this range, + // because the our restriction of well-formed UTF-8 will + // prevent these from ever occurring. + $this->mask .= chr($i); + } + + /* + PHP's internal strcspn implementation is + O(length of string * length of mask), making it inefficient + for large masks. However, it's still faster than + preg_match 8) + for (p = s1;;) { + spanp = s2; + do { + if (*spanp == c || p == s1_end) { + return p - s1; + } + } while (spanp++ < (s2_end - 1)); + c = *++p; + } + */ + // possible optimization: invert the mask. + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + static $generic_names = array( + 'serif' => true, + 'sans-serif' => true, + 'monospace' => true, + 'fantasy' => true, + 'cursive' => true + ); + $allowed_fonts = $config->get('CSS.AllowedFonts'); + + // assume that no font names contain commas in them + $fonts = explode(',', $string); + $final = ''; + foreach ($fonts as $font) { + $font = trim($font); + if ($font === '') { + continue; + } + // match a generic name + if (isset($generic_names[$font])) { + if ($allowed_fonts === null || isset($allowed_fonts[$font])) { + $final .= $font . ', '; + } + continue; + } + // match a quoted name + if ($font[0] === '"' || $font[0] === "'") { + $length = strlen($font); + if ($length <= 2) { + continue; + } + $quote = $font[0]; + if ($font[$length - 1] !== $quote) { + continue; + } + $font = substr($font, 1, $length - 2); + } + + $font = $this->expandCSSEscape($font); + + // $font is a pure representation of the font name + + if ($allowed_fonts !== null && !isset($allowed_fonts[$font])) { + continue; + } + + if (ctype_alnum($font) && $font !== '') { + // very simple font, allow it in unharmed + $final .= $font . ', '; + continue; + } + + // bugger out on whitespace. form feed (0C) really + // shouldn't show up regardless + $font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font); + + // Here, there are various classes of characters which need + // to be treated differently: + // - Alphanumeric characters are essentially safe. We + // handled these above. + // - Spaces require quoting, though most parsers will do + // the right thing if there aren't any characters that + // can be misinterpreted + // - Dashes rarely occur, but they fairly unproblematic + // for parsing/rendering purposes. + // The above characters cover the majority of Western font + // names. + // - Arbitrary Unicode characters not in ASCII. Because + // most parsers give little thought to Unicode, treatment + // of these codepoints is basically uniform, even for + // punctuation-like codepoints. These characters can + // show up in non-Western pages and are supported by most + // major browsers, for example: "MS 明朝" is a + // legitimate font-name + // . See + // the CSS3 spec for more examples: + // + // You can see live samples of these on the Internet: + // + // However, most of these fonts have ASCII equivalents: + // for example, 'MS Mincho', and it's considered + // professional to use ASCII font names instead of + // Unicode font names. Thanks Takeshi Terada for + // providing this information. + // The following characters, to my knowledge, have not been + // used to name font names. + // - Single quote. While theoretically you might find a + // font name that has a single quote in its name (serving + // as an apostrophe, e.g. Dave's Scribble), I haven't + // been able to find any actual examples of this. + // Internet Explorer's cssText translation (which I + // believe is invoked by innerHTML) normalizes any + // quoting to single quotes, and fails to escape single + // quotes. (Note that this is not IE's behavior for all + // CSS properties, just some sort of special casing for + // font-family). So a single quote *cannot* be used + // safely in the font-family context if there will be an + // innerHTML/cssText translation. Note that Firefox 3.x + // does this too. + // - Double quote. In IE, these get normalized to + // single-quotes, no matter what the encoding. (Fun + // fact, in IE8, the 'content' CSS property gained + // support, where they special cased to preserve encoded + // double quotes, but still translate unadorned double + // quotes into single quotes.) So, because their + // fixpoint behavior is identical to single quotes, they + // cannot be allowed either. Firefox 3.x displays + // single-quote style behavior. + // - Backslashes are reduced by one (so \\ -> \) every + // iteration, so they cannot be used safely. This shows + // up in IE7, IE8 and FF3 + // - Semicolons, commas and backticks are handled properly. + // - The rest of the ASCII punctuation is handled properly. + // We haven't checked what browsers do to unadorned + // versions, but this is not important as long as the + // browser doesn't /remove/ surrounding quotes (as IE does + // for HTML). + // + // With these results in hand, we conclude that there are + // various levels of safety: + // - Paranoid: alphanumeric, spaces and dashes(?) + // - International: Paranoid + non-ASCII Unicode + // - Edgy: Everything except quotes, backslashes + // - NoJS: Standards compliance, e.g. sod IE. Note that + // with some judicious character escaping (since certain + // types of escaping doesn't work) this is theoretically + // OK as long as innerHTML/cssText is not called. + // We believe that international is a reasonable default + // (that we will implement now), and once we do more + // extensive research, we may feel comfortable with dropping + // it down to edgy. + + // Edgy: alphanumeric, spaces, dashes, underscores and Unicode. Use of + // str(c)spn assumes that the string was already well formed + // Unicode (which of course it is). + if (strspn($font, $this->mask) !== strlen($font)) { + continue; + } + + // Historical: + // In the absence of innerHTML/cssText, these ugly + // transforms don't pose a security risk (as \\ and \" + // might--these escapes are not supported by most browsers). + // We could try to be clever and use single-quote wrapping + // when there is a double quote present, but I have choosen + // not to implement that. (NOTE: you can reduce the amount + // of escapes by one depending on what quoting style you use) + // $font = str_replace('\\', '\\5C ', $font); + // $font = str_replace('"', '\\22 ', $font); + // $font = str_replace("'", '\\27 ', $font); + + // font possibly with spaces, requires quoting + $final .= "'$font', "; + } + $final = rtrim($final, ', '); + if ($final === '') { + return false; + } + return $final; + } + +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php new file mode 100644 index 00000000..5f13edfd --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php @@ -0,0 +1,32 @@ +def = $def; + $this->allow = $allow; + } + + /** + * Intercepts and removes !important if necessary + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + // test for ! and important tokens + $string = trim($string); + $is_important = false; + // :TODO: optimization: test directly for !important and ! important + if (strlen($string) >= 9 && substr($string, -9) === 'important') { + $temp = rtrim(substr($string, 0, -9)); + // use a temp, because we might want to restore important + if (strlen($temp) >= 1 && substr($temp, -1) === '!') { + $string = rtrim(substr($temp, 0, -1)); + $is_important = true; + } + } + $string = $this->def->validate($string, $config, $context); + if ($this->allow && $is_important) { + $string .= ' !important'; + } + return $string; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php new file mode 100644 index 00000000..88da41d9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php @@ -0,0 +1,77 @@ +min = $min !== null ? HTMLPurifier_Length::make($min) : null; + $this->max = $max !== null ? HTMLPurifier_Length::make($max) : null; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $string = $this->parseCDATA($string); + + // Optimizations + if ($string === '') { + return false; + } + if ($string === '0') { + return '0'; + } + if (strlen($string) === 1) { + return false; + } + + $length = HTMLPurifier_Length::make($string); + if (!$length->isValid()) { + return false; + } + + if ($this->min) { + $c = $length->compareTo($this->min); + if ($c === false) { + return false; + } + if ($c < 0) { + return false; + } + } + if ($this->max) { + $c = $length->compareTo($this->max); + if ($c === false) { + return false; + } + if ($c > 0) { + return false; + } + } + return $length->toString(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php new file mode 100644 index 00000000..b4cce9a9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php @@ -0,0 +1,112 @@ +getCSSDefinition(); + $this->info['list-style-type'] = $def->info['list-style-type']; + $this->info['list-style-position'] = $def->info['list-style-position']; + $this->info['list-style-image'] = $def->info['list-style-image']; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + // regular pre-processing + $string = $this->parseCDATA($string); + if ($string === '') { + return false; + } + + // assumes URI doesn't have spaces in it + $bits = explode(' ', strtolower($string)); // bits to process + + $caught = array(); + $caught['type'] = false; + $caught['position'] = false; + $caught['image'] = false; + + $i = 0; // number of catches + $none = false; + + foreach ($bits as $bit) { + if ($i >= 3) { + return; + } // optimization bit + if ($bit === '') { + continue; + } + foreach ($caught as $key => $status) { + if ($status !== false) { + continue; + } + $r = $this->info['list-style-' . $key]->validate($bit, $config, $context); + if ($r === false) { + continue; + } + if ($r === 'none') { + if ($none) { + continue; + } else { + $none = true; + } + if ($key == 'image') { + continue; + } + } + $caught[$key] = $r; + $i++; + break; + } + } + + if (!$i) { + return false; + } + + $ret = array(); + + // construct type + if ($caught['type']) { + $ret[] = $caught['type']; + } + + // construct image + if ($caught['image']) { + $ret[] = $caught['image']; + } + + // construct position + if ($caught['position']) { + $ret[] = $caught['position']; + } + + if (empty($ret)) { + return false; + } + return implode(' ', $ret); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php new file mode 100644 index 00000000..4efb6c04 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php @@ -0,0 +1,71 @@ +single = $single; + $this->max = $max; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $string = $this->mungeRgb($this->parseCDATA($string)); + if ($string === '') { + return false; + } + $parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n + $length = count($parts); + $final = ''; + for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) { + if (ctype_space($parts[$i])) { + continue; + } + $result = $this->single->validate($parts[$i], $config, $context); + if ($result !== false) { + $final .= $result . ' '; + $num++; + } + } + if ($final === '') { + return false; + } + return rtrim($final); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php new file mode 100644 index 00000000..c78f6c9d --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php @@ -0,0 +1,84 @@ +non_negative = $non_negative; + } + + /** + * @param string $number + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return string|bool + * @warning Some contexts do not pass $config, $context. These + * variables should not be used without checking HTMLPurifier_Length + */ + public function validate($number, $config, $context) + { + $number = $this->parseCDATA($number); + + if ($number === '') { + return false; + } + if ($number === '0') { + return '0'; + } + + $sign = ''; + switch ($number[0]) { + case '-': + if ($this->non_negative) { + return false; + } + $sign = '-'; + case '+': + $number = substr($number, 1); + } + + if (ctype_digit($number)) { + $number = ltrim($number, '0'); + return $number ? $sign . $number : '0'; + } + + // Period is the only non-numeric character allowed + if (strpos($number, '.') === false) { + return false; + } + + list($left, $right) = explode('.', $number, 2); + + if ($left === '' && $right === '') { + return false; + } + if ($left !== '' && !ctype_digit($left)) { + return false; + } + + $left = ltrim($left, '0'); + $right = rtrim($right, '0'); + + if ($right === '') { + return $left ? $sign . $left : '0'; + } elseif (!ctype_digit($right)) { + return false; + } + return $sign . $left . '.' . $right; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php new file mode 100644 index 00000000..aac1a6f5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php @@ -0,0 +1,54 @@ +number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative); + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $string = $this->parseCDATA($string); + + if ($string === '') { + return false; + } + $length = strlen($string); + if ($length === 1) { + return false; + } + if ($string[$length - 1] !== '%') { + return false; + } + + $number = substr($string, 0, $length - 1); + $number = $this->number_def->validate($number, $config, $context); + + if ($number === false) { + return false; + } + return "$number%"; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php new file mode 100644 index 00000000..3992de0e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php @@ -0,0 +1,46 @@ + true, + 'overline' => true, + 'underline' => true, + ); + + $string = strtolower($this->parseCDATA($string)); + + if ($string === 'none') { + return $string; + } + + $parts = explode(' ', $string); + $final = ''; + foreach ($parts as $part) { + if (isset($allowed_values[$part])) { + $final .= $part . ' '; + } + } + $final = rtrim($final); + if ($final === '') { + return false; + } + return $final; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php new file mode 100644 index 00000000..3d18b328 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php @@ -0,0 +1,77 @@ +parseCDATA($uri_string); + if (strpos($uri_string, 'url(') !== 0) { + return false; + } + $uri_string = substr($uri_string, 4); + if (strlen($uri_string) == 0) { + return false; + } + $new_length = strlen($uri_string) - 1; + if ($uri_string[$new_length] != ')') { + return false; + } + $uri = trim(substr($uri_string, 0, $new_length)); + + if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) { + $quote = $uri[0]; + $new_length = strlen($uri) - 1; + if ($uri[$new_length] !== $quote) { + return false; + } + $uri = substr($uri, 1, $new_length - 1); + } + + $uri = $this->expandCSSEscape($uri); + + $result = parent::validate($uri, $config, $context); + + if ($result === false) { + return false; + } + + // extra sanity check; should have been done by URI + $result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result); + + // suspicious characters are ()'; we're going to percent encode + // them for safety. + $result = str_replace(array('(', ')', "'"), array('%28', '%29', '%27'), $result); + + // there's an extra bug where ampersands lose their escaping on + // an innerHTML cycle, so a very unlucky query parameter could + // then change the meaning of the URL. Unfortunately, there's + // not much we can do about that... + return "url(\"$result\")"; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php new file mode 100644 index 00000000..b181d1bc --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php @@ -0,0 +1,44 @@ +clone = $clone; + } + + /** + * @param string $v + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($v, $config, $context) + { + return $this->clone->validate($v, $config, $context); + } + + /** + * @param string $string + * @return HTMLPurifier_AttrDef + */ + public function make($string) + { + return clone $this->clone; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php new file mode 100644 index 00000000..b40122b6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php @@ -0,0 +1,73 @@ +valid_values = array_flip($valid_values); + $this->case_sensitive = $case_sensitive; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $string = trim($string); + if (!$this->case_sensitive) { + // we may want to do full case-insensitive libraries + $string = ctype_lower($string) ? $string : strtolower($string); + } + $result = isset($this->valid_values[$string]); + + return $result ? $string : false; + } + + /** + * @param string $string In form of comma-delimited list of case-insensitive + * valid values. Example: "foo,bar,baz". Prepend "s:" to make + * case sensitive + * @return HTMLPurifier_AttrDef_Enum + */ + public function make($string) + { + if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') { + $string = substr($string, 2); + $sensitive = true; + } else { + $sensitive = false; + } + $values = explode(',', $string); + return new HTMLPurifier_AttrDef_Enum($values, $sensitive); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php new file mode 100644 index 00000000..953a36a6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php @@ -0,0 +1,48 @@ +name = $name; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + return $this->name; + } + + /** + * @param string $string Name of attribute + * @return HTMLPurifier_AttrDef_HTML_Bool + */ + public function make($string) + { + return new HTMLPurifier_AttrDef_HTML_Bool($string); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php new file mode 100644 index 00000000..b874c7e1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php @@ -0,0 +1,48 @@ +getDefinition('HTML')->doctype->name; + if ($name == "XHTML 1.1" || $name == "XHTML 2.0") { + return parent::split($string, $config, $context); + } else { + return preg_split('/\s+/', $string); + } + } + + /** + * @param array $tokens + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + protected function filter($tokens, $config, $context) + { + $allowed = $config->get('Attr.AllowedClasses'); + $forbidden = $config->get('Attr.ForbiddenClasses'); + $ret = array(); + foreach ($tokens as $token) { + if (($allowed === null || isset($allowed[$token])) && + !isset($forbidden[$token]) && + // We need this O(n) check because of PHP's array + // implementation that casts -0 to 0. + !in_array($token, $ret, true) + ) { + $ret[] = $token; + } + } + return $ret; + } +} diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php new file mode 100644 index 00000000..25c93fc6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php @@ -0,0 +1,51 @@ +get('Core.ColorKeywords'); + } + + $string = trim($string); + + if (empty($string)) { + return false; + } + $lower = strtolower($string); + if (isset($colors[$lower])) { + return $colors[$lower]; + } + if ($string[0] === '#') { + $hex = substr($string, 1); + } else { + $hex = $string; + } + + $length = strlen($hex); + if ($length !== 3 && $length !== 6) { + return false; + } + if (!ctype_xdigit($hex)) { + return false; + } + if ($length === 3) { + $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; + } + return "#$hex"; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php new file mode 100644 index 00000000..7446b6da --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php @@ -0,0 +1,38 @@ +valid_values === false) { + $this->valid_values = $config->get('Attr.AllowedFrameTargets'); + } + return parent::validate($string, $config, $context); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php new file mode 100644 index 00000000..7e464ba5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php @@ -0,0 +1,113 @@ +selector = $selector; + } + + /** + * @param string $id + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($id, $config, $context) + { + if (!$this->selector && !$config->get('Attr.EnableID')) { + return false; + } + + $id = trim($id); // trim it first + + if ($id === '') { + return false; + } + + $prefix = $config->get('Attr.IDPrefix'); + if ($prefix !== '') { + $prefix .= $config->get('Attr.IDPrefixLocal'); + // prevent re-appending the prefix + if (strpos($id, $prefix) !== 0) { + $id = $prefix . $id; + } + } elseif ($config->get('Attr.IDPrefixLocal') !== '') { + trigger_error( + '%Attr.IDPrefixLocal cannot be used unless ' . + '%Attr.IDPrefix is set', + E_USER_WARNING + ); + } + + if (!$this->selector) { + $id_accumulator =& $context->get('IDAccumulator'); + if (isset($id_accumulator->ids[$id])) { + return false; + } + } + + // we purposely avoid using regex, hopefully this is faster + + if ($config->get('Attr.ID.HTML5') === true) { + if (preg_match('/[\t\n\x0b\x0c ]/', $id)) { + return false; + } + } else { + if (ctype_alpha($id)) { + // OK + } else { + if (!ctype_alpha(@$id[0])) { + return false; + } + // primitive style of regexps, I suppose + $trim = trim( + $id, + 'A..Za..z0..9:-._' + ); + if ($trim !== '') { + return false; + } + } + } + + $regexp = $config->get('Attr.IDBlacklistRegexp'); + if ($regexp && preg_match($regexp, $id)) { + return false; + } + + if (!$this->selector) { + $id_accumulator->add($id); + } + + // if no change was made to the ID, return the result + // else, return the new id if stripping whitespace made it + // valid, or return false. + return $id; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php new file mode 100644 index 00000000..c8f51886 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php @@ -0,0 +1,56 @@ + 100) { + return '100%'; + } + return ((string)$points) . '%'; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php new file mode 100644 index 00000000..3f56934f --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php @@ -0,0 +1,72 @@ + 'AllowedRel', + 'rev' => 'AllowedRev' + ); + if (!isset($configLookup[$name])) { + trigger_error( + 'Unrecognized attribute name for link ' . + 'relationship.', + E_USER_ERROR + ); + return; + } + $this->name = $configLookup[$name]; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $allowed = $config->get('Attr.' . $this->name); + if (empty($allowed)) { + return false; + } + + $string = $this->parseCDATA($string); + $parts = explode(' ', $string); + + // lookup to prevent duplicates + $ret_lookup = array(); + foreach ($parts as $part) { + $part = strtolower(trim($part)); + if (!isset($allowed[$part])) { + continue; + } + $ret_lookup[$part] = true; + } + + if (empty($ret_lookup)) { + return false; + } + $string = implode(' ', array_keys($ret_lookup)); + return $string; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php new file mode 100644 index 00000000..eb713e15 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php @@ -0,0 +1,60 @@ +split($string, $config, $context); + $tokens = $this->filter($tokens, $config, $context); + if (empty($tokens)) { + return false; + } + return implode(' ', $tokens); + } + + /** + * Splits a space separated list of tokens into its constituent parts. + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + protected function split($string, $config, $context) + { + // OPTIMIZABLE! + // do the preg_match, capture all subpatterns for reformulation + + // we don't support U+00A1 and up codepoints or + // escaping because I don't know how to do that with regexps + // and plus it would complicate optimization efforts (you never + // see that anyway). + $pattern = '/(?:(?<=\s)|\A)' . // look behind for space or string start + '((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)' . + '(?:(?=\s)|\z)/'; // look ahead for space or string end + preg_match_all($pattern, $string, $matches); + return $matches[1]; + } + + /** + * Template method for removing certain tokens based on arbitrary criteria. + * @note If we wanted to be really functional, we'd do an array_filter + * with a callback. But... we're not. + * @param array $tokens + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + protected function filter($tokens, $config, $context) + { + return $tokens; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php new file mode 100644 index 00000000..1a68f238 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php @@ -0,0 +1,76 @@ +max = $max; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $string = trim($string); + if ($string === '0') { + return $string; + } + if ($string === '') { + return false; + } + $length = strlen($string); + if (substr($string, $length - 2) == 'px') { + $string = substr($string, 0, $length - 2); + } + if (!is_numeric($string)) { + return false; + } + $int = (int)$string; + + if ($int < 0) { + return '0'; + } + + // upper-bound value, extremely high values can + // crash operating systems, see + // WARNING, above link WILL crash you if you're using Windows + + if ($this->max !== null && $int > $this->max) { + return (string)$this->max; + } + return (string)$int; + } + + /** + * @param string $string + * @return HTMLPurifier_AttrDef + */ + public function make($string) + { + if ($string === '') { + $max = null; + } else { + $max = (int)$string; + } + $class = get_class($this); + return new $class($max); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php new file mode 100644 index 00000000..c98376d7 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php @@ -0,0 +1,91 @@ +negative = $negative; + $this->zero = $zero; + $this->positive = $positive; + } + + /** + * @param string $integer + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($integer, $config, $context) + { + $integer = $this->parseCDATA($integer); + if ($integer === '') { + return false; + } + + // we could possibly simply typecast it to integer, but there are + // certain fringe cases that must not return an integer. + + // clip leading sign + if ($this->negative && $integer[0] === '-') { + $digits = substr($integer, 1); + if ($digits === '0') { + $integer = '0'; + } // rm minus sign for zero + } elseif ($this->positive && $integer[0] === '+') { + $digits = $integer = substr($integer, 1); // rm unnecessary plus + } else { + $digits = $integer; + } + + // test if it's numeric + if (!ctype_digit($digits)) { + return false; + } + + // perform scope tests + if (!$this->zero && $integer == 0) { + return false; + } + if (!$this->positive && $integer > 0) { + return false; + } + if (!$this->negative && $integer < 0) { + return false; + } + + return $integer; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php new file mode 100644 index 00000000..6ad0f799 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php @@ -0,0 +1,86 @@ + 8 || !ctype_alnum($subtags[1])) { + return $new_string; + } + if (!ctype_lower($subtags[1])) { + $subtags[1] = strtolower($subtags[1]); + } + + $new_string .= '-' . $subtags[1]; + if ($num_subtags == 2) { + return $new_string; + } + + // process all other subtags, index 2 and up + for ($i = 2; $i < $num_subtags; $i++) { + $length = strlen($subtags[$i]); + if ($length == 0 || $length > 8 || !ctype_alnum($subtags[$i])) { + return $new_string; + } + if (!ctype_lower($subtags[$i])) { + $subtags[$i] = strtolower($subtags[$i]); + } + $new_string .= '-' . $subtags[$i]; + } + return $new_string; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php new file mode 100644 index 00000000..078291f5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php @@ -0,0 +1,53 @@ +tag = $tag; + $this->withTag = $with_tag; + $this->withoutTag = $without_tag; + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $token = $context->get('CurrentToken', true); + if (!$token || $token->name !== $this->tag) { + return $this->withoutTag->validate($string, $config, $context); + } else { + return $this->withTag->validate($string, $config, $context); + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php new file mode 100644 index 00000000..9f23bac4 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php @@ -0,0 +1,21 @@ +parseCDATA($string); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php new file mode 100644 index 00000000..a1097cd9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php @@ -0,0 +1,111 @@ +parser = new HTMLPurifier_URIParser(); + $this->embedsResource = (bool)$embeds_resource; + } + + /** + * @param string $string + * @return HTMLPurifier_AttrDef_URI + */ + public function make($string) + { + $embeds = ($string === 'embedded'); + return new HTMLPurifier_AttrDef_URI($embeds); + } + + /** + * @param string $uri + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($uri, $config, $context) + { + if ($config->get('URI.Disable')) { + return false; + } + + $uri = $this->parseCDATA($uri); + + // parse the URI + $uri = $this->parser->parse($uri); + if ($uri === false) { + return false; + } + + // add embedded flag to context for validators + $context->register('EmbeddedURI', $this->embedsResource); + + $ok = false; + do { + + // generic validation + $result = $uri->validate($config, $context); + if (!$result) { + break; + } + + // chained filtering + $uri_def = $config->getDefinition('URI'); + $result = $uri_def->filter($uri, $config, $context); + if (!$result) { + break; + } + + // scheme-specific validation + $scheme_obj = $uri->getSchemeObj($config, $context); + if (!$scheme_obj) { + break; + } + if ($this->embedsResource && !$scheme_obj->browsable) { + break; + } + $result = $scheme_obj->validate($uri, $config, $context); + if (!$result) { + break; + } + + // Post chained filtering + $result = $uri_def->postFilter($uri, $config, $context); + if (!$result) { + break; + } + + // survived gauntlet + $ok = true; + + } while (false); + + $context->destroy('EmbeddedURI'); + if (!$ok) { + return false; + } + // back to string + return $uri->toString(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php new file mode 100644 index 00000000..846d3881 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php @@ -0,0 +1,20 @@ +" + // that needs more percent encoding to be done + if ($string == '') { + return false; + } + $string = trim($string); + $result = preg_match('/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i', $string); + return $result ? $string : false; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php new file mode 100644 index 00000000..c1e2e3c5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php @@ -0,0 +1,138 @@ +ipv4 = new HTMLPurifier_AttrDef_URI_IPv4(); + $this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6(); + } + + /** + * @param string $string + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($string, $config, $context) + { + $length = strlen($string); + // empty hostname is OK; it's usually semantically equivalent: + // the default host as defined by a URI scheme is used: + // + // If the URI scheme defines a default for host, then that + // default applies when the host subcomponent is undefined + // or when the registered name is empty (zero length). + if ($string === '') { + return ''; + } + if ($length > 1 && $string[0] === '[' && $string[$length - 1] === ']') { + //IPv6 + $ip = substr($string, 1, $length - 2); + $valid = $this->ipv6->validate($ip, $config, $context); + if ($valid === false) { + return false; + } + return '[' . $valid . ']'; + } + + // need to do checks on unusual encodings too + $ipv4 = $this->ipv4->validate($string, $config, $context); + if ($ipv4 !== false) { + return $ipv4; + } + + // A regular domain name. + + // This doesn't match I18N domain names, but we don't have proper IRI support, + // so force users to insert Punycode. + + // There is not a good sense in which underscores should be + // allowed, since it's technically not! (And if you go as + // far to allow everything as specified by the DNS spec... + // well, that's literally everything, modulo some space limits + // for the components and the overall name (which, by the way, + // we are NOT checking!). So we (arbitrarily) decide this: + // let's allow underscores wherever we would have allowed + // hyphens, if they are enabled. This is a pretty good match + // for browser behavior, for example, a large number of browsers + // cannot handle foo_.example.com, but foo_bar.example.com is + // fairly well supported. + $underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : ''; + + // Based off of RFC 1738, but amended so that + // as per RFC 3696, the top label need only not be all numeric. + // The productions describing this are: + $a = '[a-z]'; // alpha + $an = '[a-z0-9]'; // alphanum + $and = "[a-z0-9-$underscore]"; // alphanum | "-" + // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum + $domainlabel = "$an(?:$and*$an)?"; + // AMENDED as per RFC 3696 + // toplabel = alphanum | alphanum *( alphanum | "-" ) alphanum + // side condition: not all numeric + $toplabel = "$an(?:$and*$an)?"; + // hostname = *( domainlabel "." ) toplabel [ "." ] + if (preg_match("/^(?:$domainlabel\.)*($toplabel)\.?$/i", $string, $matches)) { + if (!ctype_digit($matches[1])) { + return $string; + } + } + + // PHP 5.3 and later support this functionality natively + if (function_exists('idn_to_ascii')) { + $string = idn_to_ascii($string, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46); + + // If we have Net_IDNA2 support, we can support IRIs by + // punycoding them. (This is the most portable thing to do, + // since otherwise we have to assume browsers support + } elseif ($config->get('Core.EnableIDNA')) { + $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true)); + // we need to encode each period separately + $parts = explode('.', $string); + try { + $new_parts = array(); + foreach ($parts as $part) { + $encodable = false; + for ($i = 0, $c = strlen($part); $i < $c; $i++) { + if (ord($part[$i]) > 0x7a) { + $encodable = true; + break; + } + } + if (!$encodable) { + $new_parts[] = $part; + } else { + $new_parts[] = $idna->encode($part); + } + } + $string = implode('.', $new_parts); + } catch (Exception $e) { + // XXX error reporting + } + } + // Try again + if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) { + return $string; + } + return false; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php new file mode 100644 index 00000000..bbc8a77e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php @@ -0,0 +1,45 @@ +ip4) { + $this->_loadRegex(); + } + + if (preg_match('#^' . $this->ip4 . '$#s', $aIP)) { + return $aIP; + } + return false; + } + + /** + * Lazy load function to prevent regex from being stuffed in + * cache. + */ + protected function _loadRegex() + { + $oct = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'; // 0-255 + $this->ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})"; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php new file mode 100644 index 00000000..67f148bd --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php @@ -0,0 +1,89 @@ +ip4) { + $this->_loadRegex(); + } + + $original = $aIP; + + $hex = '[0-9a-fA-F]'; + $blk = '(?:' . $hex . '{1,4})'; + $pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128 + + // prefix check + if (strpos($aIP, '/') !== false) { + if (preg_match('#' . $pre . '$#s', $aIP, $find)) { + $aIP = substr($aIP, 0, 0 - strlen($find[0])); + unset($find); + } else { + return false; + } + } + + // IPv4-compatiblity check + if (preg_match('#(?<=:' . ')' . $this->ip4 . '$#s', $aIP, $find)) { + $aIP = substr($aIP, 0, 0 - strlen($find[0])); + $ip = explode('.', $find[0]); + $ip = array_map('dechex', $ip); + $aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3]; + unset($find, $ip); + } + + // compression check + $aIP = explode('::', $aIP); + $c = count($aIP); + if ($c > 2) { + return false; + } elseif ($c == 2) { + list($first, $second) = $aIP; + $first = explode(':', $first); + $second = explode(':', $second); + + if (count($first) + count($second) > 8) { + return false; + } + + while (count($first) < 8) { + array_push($first, '0'); + } + + array_splice($first, 8 - count($second), 8, $second); + $aIP = $first; + unset($first, $second); + } else { + $aIP = explode(':', $aIP[0]); + } + $c = count($aIP); + + if ($c != 8) { + return false; + } + + // All the pieces should be 16-bit hex strings. Are they? + foreach ($aIP as $piece) { + if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece))) { + return false; + } + } + return $original; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php new file mode 100644 index 00000000..f0f00068 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php @@ -0,0 +1,28 @@ +confiscateAttr($attr, 'background'); + // some validation should happen here + + $this->prependCSS($attr, "background-image:url($background);"); + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php new file mode 100644 index 00000000..86dcb17e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php @@ -0,0 +1,27 @@ +get('Attr.DefaultTextDir'); + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php new file mode 100644 index 00000000..e45e9ba3 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php @@ -0,0 +1,28 @@ +confiscateAttr($attr, 'bgcolor'); + // some validation should happen here + + $this->prependCSS($attr, "background-color:$bgcolor;"); + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php new file mode 100644 index 00000000..29d7ff26 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php @@ -0,0 +1,47 @@ +attr = $attr; + $this->css = $css; + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr[$this->attr])) { + return $attr; + } + unset($attr[$this->attr]); + $this->prependCSS($attr, $this->css); + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php new file mode 100644 index 00000000..90a8dea8 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php @@ -0,0 +1,26 @@ +confiscateAttr($attr, 'border'); + // some validation should happen here + $this->prependCSS($attr, "border:{$border_width}px solid;"); + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php new file mode 100644 index 00000000..e2bfbf00 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php @@ -0,0 +1,68 @@ +attr = $attr; + $this->enumToCSS = $enum_to_css; + $this->caseSensitive = (bool)$case_sensitive; + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr[$this->attr])) { + return $attr; + } + + $value = trim($attr[$this->attr]); + unset($attr[$this->attr]); + + if (!$this->caseSensitive) { + $value = strtolower($value); + } + + if (!isset($this->enumToCSS[$value])) { + return $attr; + } + $this->prependCSS($attr, $this->enumToCSS[$value]); + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php new file mode 100644 index 00000000..335f0033 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php @@ -0,0 +1,47 @@ +get('Core.RemoveInvalidImg')) { + return $attr; + } + $attr['src'] = $config->get('Attr.DefaultInvalidImage'); + $src = false; + } + + if (!isset($attr['alt'])) { + if ($src) { + $alt = $config->get('Attr.DefaultImageAlt'); + if ($alt === null) { + $attr['alt'] = basename($attr['src']); + } else { + $attr['alt'] = $alt; + } + } else { + $attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt'); + } + } + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php new file mode 100644 index 00000000..aec42aea --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php @@ -0,0 +1,61 @@ + array('left', 'right'), + 'vspace' => array('top', 'bottom') + ); + + /** + * @param string $attr + */ + public function __construct($attr) + { + $this->attr = $attr; + if (!isset($this->css[$attr])) { + trigger_error(htmlspecialchars($attr) . ' is not valid space attribute'); + } + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr[$this->attr])) { + return $attr; + } + + $width = $this->confiscateAttr($attr, $this->attr); + // some validation could happen here + + if (!isset($this->css[$this->attr])) { + return $attr; + } + + $style = ''; + foreach ($this->css[$this->attr] as $suffix) { + $property = "margin-$suffix"; + $style .= "$property:{$width}px;"; + } + $this->prependCSS($attr, $style); + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php new file mode 100644 index 00000000..17a2ce4c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php @@ -0,0 +1,56 @@ +pixels = new HTMLPurifier_AttrDef_HTML_Pixels(); + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr['type'])) { + $t = 'text'; + } else { + $t = strtolower($attr['type']); + } + if (isset($attr['checked']) && $t !== 'radio' && $t !== 'checkbox') { + unset($attr['checked']); + } + if (isset($attr['maxlength']) && $t !== 'text' && $t !== 'password') { + unset($attr['maxlength']); + } + if (isset($attr['size']) && $t !== 'text' && $t !== 'password') { + $result = $this->pixels->validate($attr['size'], $config, $context); + if ($result === false) { + unset($attr['size']); + } else { + $attr['size'] = $result; + } + } + if (isset($attr['src']) && $t !== 'image') { + unset($attr['src']); + } + if (!isset($attr['value']) && ($t === 'radio' || $t === 'checkbox')) { + $attr['value'] = ''; + } + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php new file mode 100644 index 00000000..591b8ca7 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php @@ -0,0 +1,31 @@ +name = $name; + $this->cssName = $css_name ? $css_name : $name; + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr[$this->name])) { + return $attr; + } + $length = $this->confiscateAttr($attr, $this->name); + if (ctype_digit($length)) { + $length .= 'px'; + } + $this->prependCSS($attr, $this->cssName . ":$length;"); + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php new file mode 100644 index 00000000..a874d0f7 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php @@ -0,0 +1,33 @@ +get('HTML.Attr.Name.UseCDATA')) { + return $attr; + } + if (!isset($attr['name'])) { + return $attr; + } + $id = $this->confiscateAttr($attr, 'name'); + if (isset($attr['id'])) { + return $attr; + } + $attr['id'] = $id; + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php new file mode 100644 index 00000000..457f8110 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php @@ -0,0 +1,41 @@ +idDef = new HTMLPurifier_AttrDef_HTML_ID(); + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr['name'])) { + return $attr; + } + $name = $attr['name']; + if (isset($attr['id']) && $attr['id'] === $name) { + return $attr; + } + $result = $this->idDef->validate($name, $config, $context); + if ($result === false) { + unset($attr['name']); + } else { + $attr['name'] = $result; + } + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php new file mode 100644 index 00000000..25173c21 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php @@ -0,0 +1,52 @@ +parser = new HTMLPurifier_URIParser(); + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr['href'])) { + return $attr; + } + + // XXX Kind of inefficient + $url = $this->parser->parse($attr['href']); + $scheme = $url->getSchemeObj($config, $context); + + if ($scheme->browsable && !$url->isLocal($config, $context)) { + if (isset($attr['rel'])) { + $rels = explode(' ', $attr['rel']); + if (!in_array('nofollow', $rels)) { + $rels[] = 'nofollow'; + } + $attr['rel'] = implode(' ', $rels); + } else { + $attr['rel'] = 'nofollow'; + } + } + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php new file mode 100644 index 00000000..98ebf49b --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php @@ -0,0 +1,25 @@ +uri = new HTMLPurifier_AttrDef_URI(true); // embedded + $this->wmode = new HTMLPurifier_AttrDef_Enum(array('window', 'opaque', 'transparent')); + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + // If we add support for other objects, we'll need to alter the + // transforms. + switch ($attr['name']) { + // application/x-shockwave-flash + // Keep this synchronized with Injector/SafeObject.php + case 'allowScriptAccess': + $attr['value'] = 'never'; + break; + case 'allowNetworking': + $attr['value'] = 'internal'; + break; + case 'allowFullScreen': + if ($config->get('HTML.FlashAllowFullScreen')) { + $attr['value'] = ($attr['value'] == 'true') ? 'true' : 'false'; + } else { + $attr['value'] = 'false'; + } + break; + case 'wmode': + $attr['value'] = $this->wmode->validate($attr['value'], $config, $context); + break; + case 'movie': + case 'src': + $attr['name'] = "movie"; + $attr['value'] = $this->uri->validate($attr['value'], $config, $context); + break; + case 'flashvars': + // we're going to allow arbitrary inputs to the SWF, on + // the reasoning that it could only hack the SWF, not us. + break; + // add other cases to support other param name/value pairs + default: + $attr['name'] = $attr['value'] = null; + } + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php new file mode 100644 index 00000000..49445b43 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php @@ -0,0 +1,23 @@ + + */ +class HTMLPurifier_AttrTransform_ScriptRequired extends HTMLPurifier_AttrTransform +{ + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr['type'])) { + $attr['type'] = 'text/javascript'; + } + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php new file mode 100644 index 00000000..f66dcf8c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php @@ -0,0 +1,45 @@ +parser = new HTMLPurifier_URIParser(); + } + + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (!isset($attr['href'])) { + return $attr; + } + + // XXX Kind of inefficient + $url = $this->parser->parse($attr['href']); + $scheme = $url->getSchemeObj($config, $context); + + if ($scheme->browsable && !$url->isBenign($config, $context)) { + $attr['target'] = '_blank'; + } + return $attr; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php new file mode 100644 index 00000000..ab4c0972 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php @@ -0,0 +1,37 @@ + + */ +class HTMLPurifier_AttrTransform_Textarea extends HTMLPurifier_AttrTransform +{ + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + // Calculated from Firefox + if (!isset($attr['cols'])) { + $attr['cols'] = '22'; + } + if (!isset($attr['rows'])) { + $attr['rows'] = '3'; + } + return $attr; + } +} + +// vim: et sw=4 sts=4 From 9b6426cf2070d028d800a3a266d56dc6432fc0ee Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:40:36 +0700 Subject: [PATCH 25/94] Add files via upload --- .../ConfigSchema/Builder/ConfigSchema.php | 143 ++++++------------ .../ConfigSchema/Interchange/Directive.php | 89 +++++++++++ .../ConfigSchema/Interchange/Id.php | 58 +++++++ 3 files changed, 195 insertions(+), 95 deletions(-) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php index a25ab319..1174575e 100644 --- a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php @@ -1,95 +1,48 @@ -directives as $d) { - - $schema->add( - - $d->id->key, - - $d->default, - - $d->type, - - $d->typeAllowsNull - - ); - - if ($d->allowed !== null) { - - $schema->addAllowedValues( - - $d->id->key, - - $d->allowed - - ); - - } - - foreach ($d->aliases as $alias) { - - $schema->addAlias( - - $alias->key, - - $d->id->key - - ); - - } - - if ($d->valueAliases !== null) { - - $schema->addValueAliases( - - $d->id->key, - - $d->valueAliases - - ); - - } - - } - - $schema->postProcess(); - - return $schema; - - } - -} - - - -// vim: et sw=4 sts=4 +directives as $d) { + $schema->add( + $d->id->key, + $d->default, + $d->type, + $d->typeAllowsNull + ); + if ($d->allowed !== null) { + $schema->addAllowedValues( + $d->id->key, + $d->allowed + ); + } + foreach ($d->aliases as $alias) { + $schema->addAlias( + $alias->key, + $d->id->key + ); + } + if ($d->valueAliases !== null) { + $schema->addValueAliases( + $d->id->key, + $d->valueAliases + ); + } + } + $schema->postProcess(); + return $schema; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php new file mode 100644 index 00000000..4c39c5c6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php @@ -0,0 +1,89 @@ + true). + * Null if all values are allowed. + * @type array + */ + public $allowed; + + /** + * List of aliases for the directive. + * e.g. array(new HTMLPurifier_ConfigSchema_Interchange_Id('Ns', 'Dir'))). + * @type HTMLPurifier_ConfigSchema_Interchange_Id[] + */ + public $aliases = array(); + + /** + * Hash of value aliases, e.g. array('alt' => 'real'). Null if value + * aliasing is disabled (necessary for non-scalar types). + * @type array + */ + public $valueAliases; + + /** + * Version of HTML Purifier the directive was introduced, e.g. '1.3.1'. + * Null if the directive has always existed. + * @type string + */ + public $version; + + /** + * ID of directive that supercedes this old directive. + * Null if not deprecated. + * @type HTMLPurifier_ConfigSchema_Interchange_Id + */ + public $deprecatedUse; + + /** + * Version of HTML Purifier this directive was deprecated. Null if not + * deprecated. + * @type string + */ + public $deprecatedVersion; + + /** + * List of external projects this directive depends on, e.g. array('CSSTidy'). + * @type array + */ + public $external = array(); +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php new file mode 100644 index 00000000..3ee81711 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php @@ -0,0 +1,58 @@ +key = $key; + } + + /** + * @return string + * @warning This is NOT magic, to ensure that people don't abuse SPL and + * cause problems for PHP 5.0 support. + */ + public function toString() + { + return $this->key; + } + + /** + * @return string + */ + public function getRootNamespace() + { + return substr($this->key, 0, strpos($this->key, ".")); + } + + /** + * @return string + */ + public function getDirective() + { + return substr($this->key, strpos($this->key, ".") + 1); + } + + /** + * @param string $id + * @return HTMLPurifier_ConfigSchema_Interchange_Id + */ + public static function make($id) + { + return new HTMLPurifier_ConfigSchema_Interchange_Id($id); + } +} + +// vim: et sw=4 sts=4 From c23f2c380181ba1368a96c8c7a46c1161a2925d5 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:44:05 +0700 Subject: [PATCH 26/94] Add files via upload --- .../schema/Attr.AllowedClasses.txt | 8 ++ .../schema/Attr.AllowedFrameTargets.txt | 12 +++ .../ConfigSchema/schema/Attr.AllowedRel.txt | 9 +++ .../ConfigSchema/schema/Attr.AllowedRev.txt | 9 +++ .../schema/Attr.ClassUseCDATA.txt | 19 +++++ .../schema/Attr.DefaultImageAlt.txt | 11 +++ .../schema/Attr.DefaultInvalidImage.txt | 9 +++ .../schema/Attr.DefaultInvalidImageAlt.txt | 8 ++ .../schema/Attr.DefaultTextDir.txt | 10 +++ .../ConfigSchema/schema/Attr.EnableID.txt | 16 ++++ .../schema/Attr.ForbiddenClasses.txt | 8 ++ .../ConfigSchema/schema/Attr.ID.HTML5.txt | 10 +++ .../ConfigSchema/schema/Attr.IDBlacklist.txt | 5 ++ .../schema/Attr.IDBlacklistRegexp.txt | 9 +++ .../ConfigSchema/schema/Attr.IDPrefix.txt | 12 +++ .../schema/Attr.IDPrefixLocal.txt | 14 ++++ .../schema/AutoFormat.AutoParagraph.txt | 31 ++++++++ .../ConfigSchema/schema/AutoFormat.Custom.txt | 12 +++ .../schema/AutoFormat.DisplayLinkURI.txt | 11 +++ .../schema/AutoFormat.Linkify.txt | 12 +++ .../AutoFormat.PurifierLinkify.DocURL.txt | 12 +++ .../schema/AutoFormat.PurifierLinkify.txt | 12 +++ .../AutoFormat.RemoveEmpty.Predicate.txt | 14 ++++ ...rmat.RemoveEmpty.RemoveNbsp.Exceptions.txt | 11 +++ .../AutoFormat.RemoveEmpty.RemoveNbsp.txt | 15 ++++ .../schema/AutoFormat.RemoveEmpty.txt | 46 ++++++++++++ ...utoFormat.RemoveSpansWithoutAttributes.txt | 11 +++ .../schema/CSS.AllowDuplicates.txt | 11 +++ .../schema/CSS.AllowImportant.txt | 8 ++ .../ConfigSchema/schema/CSS.AllowTricky.txt | 11 +++ .../ConfigSchema/schema/CSS.AllowedFonts.txt | 12 +++ .../schema/CSS.AllowedProperties.txt | 18 +++++ .../ConfigSchema/schema/CSS.DefinitionRev.txt | 11 +++ .../schema/CSS.ForbiddenProperties.txt | 13 ++++ .../ConfigSchema/schema/CSS.MaxImgLength.txt | 16 ++++ .../ConfigSchema/schema/CSS.Proprietary.txt | 10 +++ .../ConfigSchema/schema/CSS.Trusted.txt | 9 +++ .../schema/Cache.DefinitionImpl.txt | 14 ++++ .../schema/Cache.SerializerPath.txt | 13 ++++ .../schema/Cache.SerializerPermissions.txt | 16 ++++ .../schema/Core.AggressivelyFixLt.txt | 18 +++++ .../schema/Core.AggressivelyRemoveScript.txt | 16 ++++ .../schema/Core.AllowHostnameUnderscore.txt | 16 ++++ .../schema/Core.CollectErrors.txt | 12 +++ .../schema/Core.ColorKeywords.txt | 29 ++++++++ .../schema/Core.ConvertDocumentToFragment.txt | 14 ++++ .../Core.DirectLexLineNumberSyncInterval.txt | 17 +++++ .../schema/Core.DisableExcludes.txt | 14 ++++ .../ConfigSchema/schema/Core.EnableIDNA.txt | 9 +++ .../ConfigSchema/schema/Core.Encoding.txt | 15 ++++ .../schema/Core.EscapeInvalidChildren.txt | 12 +++ .../schema/Core.EscapeInvalidTags.txt | 7 ++ .../schema/Core.EscapeNonASCIICharacters.txt | 13 ++++ .../schema/Core.HiddenElements.txt | 19 +++++ .../ConfigSchema/schema/Core.Language.txt | 10 +++ .../schema/Core.LegacyEntityDecoder.txt | 36 +++++++++ .../ConfigSchema/schema/Core.LexerImpl.txt | 34 +++++++++ .../schema/Core.MaintainLineNumbers.txt | 16 ++++ .../schema/Core.NormalizeNewlines.txt | 11 +++ .../schema/Core.RemoveInvalidImg.txt | 12 +++ .../Core.RemoveProcessingInstructions.txt | 11 +++ .../schema/Core.RemoveScriptContents.txt | 12 +++ .../ConfigSchema/schema/Filter.Custom.txt | 11 +++ .../Filter.ExtractStyleBlocks.Escaping.txt | 14 ++++ .../Filter.ExtractStyleBlocks.Scope.txt | 29 ++++++++ .../Filter.ExtractStyleBlocks.TidyImpl.txt | 16 ++++ .../schema/Filter.ExtractStyleBlocks.txt | 74 +++++++++++++++++++ .../ConfigSchema/schema/Filter.YouTube.txt | 16 ++++ .../ConfigSchema/schema/HTML.Allowed.txt | 25 +++++++ .../schema/HTML.AllowedAttributes.txt | 19 +++++ .../schema/HTML.AllowedComments.txt | 10 +++ .../schema/HTML.AllowedCommentsRegexp.txt | 15 ++++ .../schema/HTML.AllowedElements.txt | 23 ++++++ .../schema/HTML.AllowedModules.txt | 20 +++++ .../schema/HTML.Attr.Name.UseCDATA.txt | 11 +++ .../ConfigSchema/schema/HTML.BlockWrapper.txt | 18 +++++ .../ConfigSchema/schema/HTML.CoreModules.txt | 23 ++++++ .../schema/HTML.CustomDoctype.txt | 9 +++ .../ConfigSchema/schema/HTML.DefinitionID.txt | 33 +++++++++ .../schema/HTML.DefinitionRev.txt | 16 ++++ .../ConfigSchema/schema/HTML.Doctype.txt | 11 +++ .../schema/HTML.FlashAllowFullScreen.txt | 11 +++ .../schema/HTML.ForbiddenAttributes.txt | 21 ++++++ .../schema/HTML.ForbiddenElements.txt | 20 +++++ .../ConfigSchema/schema/HTML.MaxImgLength.txt | 14 ++++ .../ConfigSchema/schema/HTML.Nofollow.txt | 7 ++ .../ConfigSchema/schema/HTML.Parent.txt | 12 +++ .../ConfigSchema/schema/HTML.Proprietary.txt | 12 +++ .../ConfigSchema/schema/HTML.SafeEmbed.txt | 13 ++++ .../ConfigSchema/schema/HTML.SafeIframe.txt | 13 ++++ .../ConfigSchema/schema/HTML.SafeObject.txt | 13 ++++ .../schema/HTML.SafeScripting.txt | 10 +++ .../ConfigSchema/schema/HTML.Strict.txt | 9 +++ .../ConfigSchema/schema/HTML.TargetBlank.txt | 8 ++ .../schema/HTML.TargetNoopener.txt | 10 +++ .../schema/HTML.TargetNoreferrer.txt | 9 +++ .../ConfigSchema/schema/HTML.TidyAdd.txt | 8 ++ .../ConfigSchema/schema/HTML.TidyLevel.txt | 24 ++++++ .../ConfigSchema/schema/HTML.TidyRemove.txt | 8 ++ .../ConfigSchema/schema/HTML.Trusted.txt | 9 +++ 100 files changed, 1495 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ID.HTML5.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowDuplicates.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyRemoveScript.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LegacyEntityDecoder.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoopener.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt new file mode 100644 index 00000000..4a42382e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt @@ -0,0 +1,8 @@ +Attr.AllowedClasses +TYPE: lookup/null +VERSION: 4.0.0 +DEFAULT: null +--DESCRIPTION-- +List of allowed class values in the class attribute. By default, this is null, +which means all classes are allowed. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt new file mode 100644 index 00000000..b033eb51 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt @@ -0,0 +1,12 @@ +Attr.AllowedFrameTargets +TYPE: lookup +DEFAULT: array() +--DESCRIPTION-- +Lookup table of all allowed link frame targets. Some commonly used link +targets include _blank, _self, _parent and _top. Values should be +lowercase, as validation will be done in a case-sensitive manner despite +W3C's recommendation. XHTML 1.0 Strict does not permit the target attribute +so this directive will have no effect in that doctype. XHTML 1.1 does not +enable the Target module by default, you will have to manually enable it +(see the module documentation for more details.) +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt new file mode 100644 index 00000000..ed72a9d5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt @@ -0,0 +1,9 @@ +Attr.AllowedRel +TYPE: lookup +VERSION: 1.6.0 +DEFAULT: array() +--DESCRIPTION-- +List of allowed forward document relationships in the rel attribute. Common +values may be nofollow or print. By default, this is empty, meaning that no +document relationships are allowed. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt new file mode 100644 index 00000000..1ae672d0 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt @@ -0,0 +1,9 @@ +Attr.AllowedRev +TYPE: lookup +VERSION: 1.6.0 +DEFAULT: array() +--DESCRIPTION-- +List of allowed reverse document relationships in the rev attribute. This +attribute is a bit of an edge-case; if you don't know what it is for, stay +away. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt new file mode 100644 index 00000000..119a9d2c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt @@ -0,0 +1,19 @@ +Attr.ClassUseCDATA +TYPE: bool/null +DEFAULT: null +VERSION: 4.0.0 +--DESCRIPTION-- +If null, class will auto-detect the doctype and, if matching XHTML 1.1 or +XHTML 2.0, will use the restrictive NMTOKENS specification of class. Otherwise, +it will use a relaxed CDATA definition. If true, the relaxed CDATA definition +is forced; if false, the NMTOKENS definition is forced. To get behavior +of HTML Purifier prior to 4.0.0, set this directive to false. + +Some rational behind the auto-detection: +in previous versions of HTML Purifier, it was assumed that the form of +class was NMTOKENS, as specified by the XHTML Modularization (representing +XHTML 1.1 and XHTML 2.0). The DTDs for HTML 4.01 and XHTML 1.0, however +specify class as CDATA. HTML 5 effectively defines it as CDATA, but +with the additional constraint that each name should be unique (this is not +explicitly outlined in previous specifications). +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt new file mode 100644 index 00000000..80b1431c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt @@ -0,0 +1,11 @@ +Attr.DefaultImageAlt +TYPE: string/null +DEFAULT: null +VERSION: 3.2.0 +--DESCRIPTION-- +This is the content of the alt tag of an image if the user had not +previously specified an alt attribute. This applies to all images without +a valid alt attribute, as opposed to %Attr.DefaultInvalidImageAlt, which +only applies to invalid images, and overrides in the case of an invalid image. +Default behavior with null is to use the basename of the src tag for the alt. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt new file mode 100644 index 00000000..c51000d1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt @@ -0,0 +1,9 @@ +Attr.DefaultInvalidImage +TYPE: string +DEFAULT: '' +--DESCRIPTION-- +This is the default image an img tag will be pointed to if it does not have +a valid src attribute. In future versions, we may allow the image tag to +be removed completely, but due to design issues, this is not possible right +now. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt new file mode 100644 index 00000000..c1ec4b03 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt @@ -0,0 +1,8 @@ +Attr.DefaultInvalidImageAlt +TYPE: string +DEFAULT: 'Invalid image' +--DESCRIPTION-- +This is the content of the alt tag of an invalid image if the user had not +previously specified an alt attribute. It has no effect when the image is +valid but there was no alt attribute present. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt new file mode 100644 index 00000000..f57dcc40 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt @@ -0,0 +1,10 @@ +Attr.DefaultTextDir +TYPE: string +DEFAULT: 'ltr' +--DESCRIPTION-- +Defines the default text direction (ltr or rtl) of the document being +parsed. This generally is the same as the value of the dir attribute in +HTML, or ltr if that is not specified. +--ALLOWED-- +'ltr', 'rtl' +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt new file mode 100644 index 00000000..9b93a557 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt @@ -0,0 +1,16 @@ +Attr.EnableID +TYPE: bool +DEFAULT: false +VERSION: 1.2.0 +--DESCRIPTION-- +Allows the ID attribute in HTML. This is disabled by default due to the +fact that without proper configuration user input can easily break the +validation of a webpage by specifying an ID that is already on the +surrounding HTML. If you don't mind throwing caution to the wind, enable +this directive, but I strongly recommend you also consider blacklisting IDs +you use (%Attr.IDBlacklist) or prefixing all user supplied IDs +(%Attr.IDPrefix). When set to true HTML Purifier reverts to the behavior of +pre-1.2.0 versions. +--ALIASES-- +HTML.EnableAttrID +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt new file mode 100644 index 00000000..fed8954c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt @@ -0,0 +1,8 @@ +Attr.ForbiddenClasses +TYPE: lookup +VERSION: 4.0.0 +DEFAULT: array() +--DESCRIPTION-- +List of forbidden class values in the class attribute. By default, this is +empty, which means that no classes are forbidden. See also %Attr.AllowedClasses. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ID.HTML5.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ID.HTML5.txt new file mode 100644 index 00000000..c48e62fb --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ID.HTML5.txt @@ -0,0 +1,10 @@ +Attr.ID.HTML5 +TYPE: bool/null +DEFAULT: null +VERSION: 4.8.0 +--DESCRIPTION-- +In HTML5, restrictions on the format of the id attribute have been significantly +relaxed, such that any string is valid so long as it contains no spaces and +is at least one character. In lieu of a general HTML5 compatibility flag, +set this configuration directive to true to use the relaxed rules. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt new file mode 100644 index 00000000..52168bb5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt @@ -0,0 +1,5 @@ +Attr.IDBlacklist +TYPE: list +DEFAULT: array() +DESCRIPTION: Array of IDs not allowed in the document. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt new file mode 100644 index 00000000..7b850430 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt @@ -0,0 +1,9 @@ +Attr.IDBlacklistRegexp +TYPE: string/null +VERSION: 1.6.0 +DEFAULT: NULL +--DESCRIPTION-- +PCRE regular expression to be matched against all IDs. If the expression is +matches, the ID is rejected. Use this with care: may cause significant +degradation. ID matching is done after all other validation. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt new file mode 100644 index 00000000..57813827 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt @@ -0,0 +1,12 @@ +Attr.IDPrefix +TYPE: string +VERSION: 1.2.0 +DEFAULT: '' +--DESCRIPTION-- +String to prefix to IDs. If you have no idea what IDs your pages may use, +you may opt to simply add a prefix to all user-submitted ID attributes so +that they are still usable, but will not conflict with core page IDs. +Example: setting the directive to 'user_' will result in a user submitted +'foo' to become 'user_foo' Be sure to set %HTML.EnableAttrID to true +before using this. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt new file mode 100644 index 00000000..f91fcd60 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt @@ -0,0 +1,14 @@ +Attr.IDPrefixLocal +TYPE: string +VERSION: 1.2.0 +DEFAULT: '' +--DESCRIPTION-- +Temporary prefix for IDs used in conjunction with %Attr.IDPrefix. If you +need to allow multiple sets of user content on web page, you may need to +have a seperate prefix that changes with each iteration. This way, +seperately submitted user content displayed on the same page doesn't +clobber each other. Ideal values are unique identifiers for the content it +represents (i.e. the id of the row in the database). Be sure to add a +seperator (like an underscore) at the end. Warning: this directive will +not work unless %Attr.IDPrefix is set to a non-empty value! +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt new file mode 100644 index 00000000..2d7f94e0 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt @@ -0,0 +1,31 @@ +AutoFormat.AutoParagraph +TYPE: bool +VERSION: 2.0.1 +DEFAULT: false +--DESCRIPTION-- + +

+ This directive turns on auto-paragraphing, where double newlines are + converted in to paragraphs whenever possible. Auto-paragraphing: +

+
    +
  • Always applies to inline elements or text in the root node,
  • +
  • Applies to inline elements or text with double newlines in nodes + that allow paragraph tags,
  • +
  • Applies to double newlines in paragraph tags
  • +
+

+ p tags must be allowed for this directive to take effect. + We do not use br tags for paragraphing, as that is + semantically incorrect. +

+

+ To prevent auto-paragraphing as a content-producer, refrain from using + double-newlines except to specify a new paragraph or in contexts where + it has special meaning (whitespace usually has no meaning except in + tags like pre, so this should not be difficult.) To prevent + the paragraphing of inline text adjacent to block elements, wrap them + in div tags (the behavior is slightly different outside of + the root node.) +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt new file mode 100644 index 00000000..2eb1974f --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt @@ -0,0 +1,12 @@ +AutoFormat.Custom +TYPE: list +VERSION: 2.0.1 +DEFAULT: array() +--DESCRIPTION-- + +

+ This directive can be used to add custom auto-format injectors. + Specify an array of injector names (class name minus the prefix) + or concrete implementations. Injector class must exist. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt new file mode 100644 index 00000000..c955de7f --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt @@ -0,0 +1,11 @@ +AutoFormat.DisplayLinkURI +TYPE: bool +VERSION: 3.2.0 +DEFAULT: false +--DESCRIPTION-- +

+ This directive turns on the in-text display of URIs in <a> tags, and disables + those links. For example, example becomes + example (http://example.com). +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt new file mode 100644 index 00000000..328b2b2b --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt @@ -0,0 +1,12 @@ +AutoFormat.Linkify +TYPE: bool +VERSION: 2.0.1 +DEFAULT: false +--DESCRIPTION-- + +

+ This directive turns on linkification, auto-linking http, ftp and + https URLs. a tags with the href attribute + must be allowed. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt new file mode 100644 index 00000000..d0532b6b --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt @@ -0,0 +1,12 @@ +AutoFormat.PurifierLinkify.DocURL +TYPE: string +VERSION: 2.0.1 +DEFAULT: '#%s' +ALIASES: AutoFormatParam.PurifierLinkifyDocURL +--DESCRIPTION-- +

+ Location of configuration documentation to link to, let %s substitute + into the configuration's namespace and directive names sans the percent + sign. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt new file mode 100644 index 00000000..f3ab259a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt @@ -0,0 +1,12 @@ +AutoFormat.PurifierLinkify +TYPE: bool +VERSION: 2.0.1 +DEFAULT: false +--DESCRIPTION-- + +

+ Internal auto-formatter that converts configuration directives in + syntax %Namespace.Directive to links. a tags + with the href attribute must be allowed. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt new file mode 100644 index 00000000..376f771e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt @@ -0,0 +1,14 @@ +AutoFormat.RemoveEmpty.Predicate +TYPE: hash +VERSION: 4.7.0 +DEFAULT: array('colgroup' => array(), 'th' => array(), 'td' => array(), 'iframe' => array('src')) +--DESCRIPTION-- +

+ Given that an element has no contents, it will be removed by default, unless + this predicate dictates otherwise. The predicate can either be an associative + map from tag name to list of attributes that must be present for the element + to be considered preserved: thus, the default always preserves colgroup, + th and td, and also iframe if it + has a src. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt new file mode 100644 index 00000000..219d04ac --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt @@ -0,0 +1,11 @@ +AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions +TYPE: lookup +VERSION: 4.0.0 +DEFAULT: array('td' => true, 'th' => true) +--DESCRIPTION-- +

+ When %AutoFormat.RemoveEmpty and %AutoFormat.RemoveEmpty.RemoveNbsp + are enabled, this directive defines what HTML elements should not be + removede if they have only a non-breaking space in them. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt new file mode 100644 index 00000000..5f355d66 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt @@ -0,0 +1,15 @@ +AutoFormat.RemoveEmpty.RemoveNbsp +TYPE: bool +VERSION: 4.0.0 +DEFAULT: false +--DESCRIPTION-- +

+ When enabled, HTML Purifier will treat any elements that contain only + non-breaking spaces as well as regular whitespace as empty, and remove + them when %AutoForamt.RemoveEmpty is enabled. +

+

+ See %AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions for a list of elements + that don't have this behavior applied to them. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt new file mode 100644 index 00000000..6b5a7a5c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt @@ -0,0 +1,46 @@ +AutoFormat.RemoveEmpty +TYPE: bool +VERSION: 3.2.0 +DEFAULT: false +--DESCRIPTION-- +

+ When enabled, HTML Purifier will attempt to remove empty elements that + contribute no semantic information to the document. The following types + of nodes will be removed: +

+
  • + Tags with no attributes and no content, and that are not empty + elements (remove <a></a> but not + <br />), and +
  • +
  • + Tags with no content, except for:
      +
    • The colgroup element, or
    • +
    • + Elements with the id or name attribute, + when those attributes are permitted on those elements. +
    • +
  • +
+

+ Please be very careful when using this functionality; while it may not + seem that empty elements contain useful information, they can alter the + layout of a document given appropriate styling. This directive is most + useful when you are processing machine-generated HTML, please avoid using + it on regular user HTML. +

+

+ Elements that contain only whitespace will be treated as empty. Non-breaking + spaces, however, do not count as whitespace. See + %AutoFormat.RemoveEmpty.RemoveNbsp for alternate behavior. +

+

+ This algorithm is not perfect; you may still notice some empty tags, + particularly if a node had elements, but those elements were later removed + because they were not permitted in that context, or tags that, after + being auto-closed by another tag, where empty. This is for safety reasons + to prevent clever code from breaking validation. The general rule of thumb: + if a tag looked empty on the way in, it will get removed; if HTML Purifier + made it empty, it will stay. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt new file mode 100644 index 00000000..a448770e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt @@ -0,0 +1,11 @@ +AutoFormat.RemoveSpansWithoutAttributes +TYPE: bool +VERSION: 4.0.1 +DEFAULT: false +--DESCRIPTION-- +

+ This directive causes span tags without any attributes + to be removed. It will also remove spans that had all attributes + removed during processing. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowDuplicates.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowDuplicates.txt new file mode 100644 index 00000000..acfeab3c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowDuplicates.txt @@ -0,0 +1,11 @@ +CSS.AllowDuplicates +TYPE: bool +DEFAULT: false +VERSION: 4.8.0 +--DESCRIPTION-- +

+ By default, HTML Purifier removes duplicate CSS properties, + like color:red; color:blue. If this is set to + true, duplicate properties are allowed. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt new file mode 100644 index 00000000..8096eb01 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt @@ -0,0 +1,8 @@ +CSS.AllowImportant +TYPE: bool +DEFAULT: false +VERSION: 3.1.0 +--DESCRIPTION-- +This parameter determines whether or not !important cascade modifiers should +be allowed in user CSS. If false, !important will stripped. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt new file mode 100644 index 00000000..9d34debc --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt @@ -0,0 +1,11 @@ +CSS.AllowTricky +TYPE: bool +DEFAULT: false +VERSION: 3.1.0 +--DESCRIPTION-- +This parameter determines whether or not to allow "tricky" CSS properties and +values. Tricky CSS properties/values can drastically modify page layout or +be used for deceptive practices but do not directly constitute a security risk. +For example, display:none; is considered a tricky property that +will only be allowed if this directive is set to true. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt new file mode 100644 index 00000000..7c2b5476 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt @@ -0,0 +1,12 @@ +CSS.AllowedFonts +TYPE: lookup/null +VERSION: 4.3.0 +DEFAULT: NULL +--DESCRIPTION-- +

+ Allows you to manually specify a set of allowed fonts. If + NULL, all fonts are allowed. This directive + affects generic names (serif, sans-serif, monospace, cursive, + fantasy) as well as specific font families. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt new file mode 100644 index 00000000..f1ba513c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt @@ -0,0 +1,18 @@ +CSS.AllowedProperties +TYPE: lookup/null +VERSION: 3.1.0 +DEFAULT: NULL +--DESCRIPTION-- + +

+ If HTML Purifier's style attributes set is unsatisfactory for your needs, + you can overload it with your own list of tags to allow. Note that this + method is subtractive: it does its job by taking away from HTML Purifier + usual feature set, so you cannot add an attribute that HTML Purifier never + supported in the first place. +

+

+ Warning: If another directive conflicts with the + elements here, that directive will win and override. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt new file mode 100644 index 00000000..96b41082 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt @@ -0,0 +1,11 @@ +CSS.DefinitionRev +TYPE: int +VERSION: 2.0.0 +DEFAULT: 1 +--DESCRIPTION-- + +

+ Revision identifier for your custom definition. See + %HTML.DefinitionRev for details. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt new file mode 100644 index 00000000..923e8e99 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt @@ -0,0 +1,13 @@ +CSS.ForbiddenProperties +TYPE: lookup +VERSION: 4.2.0 +DEFAULT: array() +--DESCRIPTION-- +

+ This is the logical inverse of %CSS.AllowedProperties, and it will + override that directive or any other directive. If possible, + %CSS.AllowedProperties is recommended over this directive, + because it can sometimes be difficult to tell whether or not you've + forbidden all of the CSS properties you truly would like to disallow. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt new file mode 100644 index 00000000..3808581e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt @@ -0,0 +1,16 @@ +CSS.MaxImgLength +TYPE: string/null +DEFAULT: '1200px' +VERSION: 3.1.1 +--DESCRIPTION-- +

+ This parameter sets the maximum allowed length on img tags, + effectively the width and height properties. + Only absolute units of measurement (in, pt, pc, mm, cm) and pixels (px) are allowed. This is + in place to prevent imagecrash attacks, disable with null at your own risk. + This directive is similar to %HTML.MaxImgLength, and both should be + concurrently edited, although there are + subtle differences in the input format (the CSS max is a number with + a unit). +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt new file mode 100644 index 00000000..8a26f228 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt @@ -0,0 +1,10 @@ +CSS.Proprietary +TYPE: bool +VERSION: 3.0.0 +DEFAULT: false +--DESCRIPTION-- + +

+ Whether or not to allow safe, proprietary CSS values. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt new file mode 100644 index 00000000..917ec42b --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt @@ -0,0 +1,9 @@ +CSS.Trusted +TYPE: bool +VERSION: 4.2.1 +DEFAULT: false +--DESCRIPTION-- +Indicates whether or not the user's CSS input is trusted or not. If the +input is trusted, a more expansive set of allowed properties. See +also %HTML.Trusted. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt new file mode 100644 index 00000000..afc6a87a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt @@ -0,0 +1,14 @@ +Cache.DefinitionImpl +TYPE: string/null +VERSION: 2.0.0 +DEFAULT: 'Serializer' +--DESCRIPTION-- + +This directive defines which method to use when caching definitions, +the complex data-type that makes HTML Purifier tick. Set to null +to disable caching (not recommended, as you will see a definite +performance degradation). + +--ALIASES-- +Core.DefinitionCache +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt new file mode 100644 index 00000000..668f248a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt @@ -0,0 +1,13 @@ +Cache.SerializerPath +TYPE: string/null +VERSION: 2.0.0 +DEFAULT: NULL +--DESCRIPTION-- + +

+ Absolute path with no trailing slash to store serialized definitions in. + Default is within the + HTML Purifier library inside DefinitionCache/Serializer. This + path must be writable by the webserver. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt new file mode 100644 index 00000000..f6059e67 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt @@ -0,0 +1,16 @@ +Cache.SerializerPermissions +TYPE: int/null +VERSION: 4.3.0 +DEFAULT: 0755 +--DESCRIPTION-- + +

+ Directory permissions of the files and directories created inside + the DefinitionCache/Serializer or other custom serializer path. +

+

+ In HTML Purifier 4.8.0, this also supports NULL, + which means that no chmod'ing or directory creation shall + occur. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt new file mode 100644 index 00000000..e0fa378e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt @@ -0,0 +1,18 @@ +Core.AggressivelyFixLt +TYPE: bool +VERSION: 2.1.0 +DEFAULT: true +--DESCRIPTION-- +

+ This directive enables aggressive pre-filter fixes HTML Purifier can + perform in order to ensure that open angled-brackets do not get killed + during parsing stage. Enabling this will result in two preg_replace_callback + calls and at least two preg_replace calls for every HTML document parsed; + if your users make very well-formed HTML, you can set this directive false. + This has no effect when DirectLex is used. +

+

+ Notice: This directive's default turned from false to true + in HTML Purifier 3.2.0. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyRemoveScript.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyRemoveScript.txt new file mode 100644 index 00000000..fb140b69 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyRemoveScript.txt @@ -0,0 +1,16 @@ +Core.AggressivelyRemoveScript +TYPE: bool +VERSION: 4.9.0 +DEFAULT: true +--DESCRIPTION-- +

+ This directive enables aggressive pre-filter removal of + script tags. This is not necessary for security, + but it can help work around a bug in libxml where embedded + HTML elements inside script sections cause the parser to + choke. To revert to pre-4.9.0 behavior, set this to false. + This directive has no effect if %Core.Trusted is true, + %Core.RemoveScriptContents is false, or %Core.HiddenElements + does not contain script. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt new file mode 100644 index 00000000..405d36f1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt @@ -0,0 +1,16 @@ +Core.AllowHostnameUnderscore +TYPE: bool +VERSION: 4.6.0 +DEFAULT: false +--DESCRIPTION-- +

+ By RFC 1123, underscores are not permitted in host names. + (This is in contrast to the specification for DNS, RFC + 2181, which allows underscores.) + However, most browsers do the right thing when faced with + an underscore in the host name, and so some poorly written + websites are written with the expectation this should work. + Setting this parameter to true relaxes our allowed character + check so that underscores are permitted. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt new file mode 100644 index 00000000..c6ea0699 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt @@ -0,0 +1,12 @@ +Core.CollectErrors +TYPE: bool +VERSION: 2.0.0 +DEFAULT: false +--DESCRIPTION-- + +Whether or not to collect errors found while filtering the document. This +is a useful way to give feedback to your users. Warning: +Currently this feature is very patchy and experimental, with lots of +possible error messages not yet implemented. It will not cause any +problems, but it may not help your users either. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt new file mode 100644 index 00000000..f7823982 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt @@ -0,0 +1,29 @@ +Core.ColorKeywords +TYPE: hash +VERSION: 2.0.0 +--DEFAULT-- +array ( + 'maroon' => '#800000', + 'red' => '#FF0000', + 'orange' => '#FFA500', + 'yellow' => '#FFFF00', + 'olive' => '#808000', + 'purple' => '#800080', + 'fuchsia' => '#FF00FF', + 'white' => '#FFFFFF', + 'lime' => '#00FF00', + 'green' => '#008000', + 'navy' => '#000080', + 'blue' => '#0000FF', + 'aqua' => '#00FFFF', + 'teal' => '#008080', + 'black' => '#000000', + 'silver' => '#C0C0C0', + 'gray' => '#808080', +) +--DESCRIPTION-- + +Lookup array of color names to six digit hexadecimal number corresponding +to color, with preceding hash mark. Used when parsing colors. The lookup +is done in a case-insensitive manner. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt new file mode 100644 index 00000000..656d3783 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt @@ -0,0 +1,14 @@ +Core.ConvertDocumentToFragment +TYPE: bool +DEFAULT: true +--DESCRIPTION-- + +This parameter determines whether or not the filter should convert +input that is a full document with html and body tags to a fragment +of just the contents of a body tag. This parameter is simply something +HTML Purifier can do during an edge-case: for most inputs, this +processing is not necessary. + +--ALIASES-- +Core.AcceptFullDocuments +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt new file mode 100644 index 00000000..2f54e462 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt @@ -0,0 +1,17 @@ +Core.DirectLexLineNumberSyncInterval +TYPE: int +VERSION: 2.0.0 +DEFAULT: 0 +--DESCRIPTION-- + +

+ Specifies the number of tokens the DirectLex line number tracking + implementations should process before attempting to resyncronize the + current line count by manually counting all previous new-lines. When + at 0, this functionality is disabled. Lower values will decrease + performance, and this is only strictly necessary if the counting + algorithm is buggy (in which case you should report it as a bug). + This has no effect when %Core.MaintainLineNumbers is disabled or DirectLex is + not being used. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt new file mode 100644 index 00000000..3c63c923 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt @@ -0,0 +1,14 @@ +Core.DisableExcludes +TYPE: bool +DEFAULT: false +VERSION: 4.5.0 +--DESCRIPTION-- +

+ This directive disables SGML-style exclusions, e.g. the exclusion of + <object> in any descendant of a + <pre> tag. Disabling excludes will allow some + invalid documents to pass through HTML Purifier, but HTML Purifier + will also be less likely to accidentally remove large documents during + processing. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt new file mode 100644 index 00000000..7f498e7e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt @@ -0,0 +1,9 @@ +Core.EnableIDNA +TYPE: bool +DEFAULT: false +VERSION: 4.4.0 +--DESCRIPTION-- +Allows international domain names in URLs. This configuration option +requires the PEAR Net_IDNA2 module to be installed. It operates by +punycoding any internationalized host names for maximum portability. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt new file mode 100644 index 00000000..89e2ae34 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt @@ -0,0 +1,15 @@ +Core.Encoding +TYPE: istring +DEFAULT: 'utf-8' +--DESCRIPTION-- +If for some reason you are unable to convert all webpages to UTF-8, you can +use this directive as a stop-gap compatibility change to let HTML Purifier +deal with non UTF-8 input. This technique has notable deficiencies: +absolutely no characters outside of the selected character encoding will be +preserved, not even the ones that have been ampersand escaped (this is due +to a UTF-8 specific feature that automatically resolves all +entities), making it pretty useless for anything except the most I18N-blind +applications, although %Core.EscapeNonASCIICharacters offers fixes this +trouble with another tradeoff. This directive only accepts ISO-8859-1 if +iconv is not enabled. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt new file mode 100644 index 00000000..1cc3fcda --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt @@ -0,0 +1,12 @@ +Core.EscapeInvalidChildren +TYPE: bool +DEFAULT: false +--DESCRIPTION-- +

Warning: this configuration option is no longer does anything as of 4.6.0.

+ +

When true, a child is found that is not allowed in the context of the +parent element will be transformed into text as if it were ASCII. When +false, that element and all internal tags will be dropped, though text will +be preserved. There is no option for dropping the element but preserving +child nodes.

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt new file mode 100644 index 00000000..299775fa --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt @@ -0,0 +1,7 @@ +Core.EscapeInvalidTags +TYPE: bool +DEFAULT: false +--DESCRIPTION-- +When true, invalid tags will be written back to the document as plain text. +Otherwise, they are silently dropped. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt new file mode 100644 index 00000000..f50db2f9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt @@ -0,0 +1,13 @@ +Core.EscapeNonASCIICharacters +TYPE: bool +VERSION: 1.4.0 +DEFAULT: false +--DESCRIPTION-- +This directive overcomes a deficiency in %Core.Encoding by blindly +converting all non-ASCII characters into decimal numeric entities before +converting it to its native encoding. This means that even characters that +can be expressed in the non-UTF-8 encoding will be entity-ized, which can +be a real downer for encodings like Big5. It also assumes that the ASCII +repetoire is available, although this is the case for almost all encodings. +Anyway, use UTF-8! +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt new file mode 100644 index 00000000..c337e47f --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt @@ -0,0 +1,19 @@ +Core.HiddenElements +TYPE: lookup +--DEFAULT-- +array ( + 'script' => true, + 'style' => true, +) +--DESCRIPTION-- + +

+ This directive is a lookup array of elements which should have their + contents removed when they are not allowed by the HTML definition. + For example, the contents of a script tag are not + normally shown in a document, so if script tags are to be removed, + their contents should be removed to. This is opposed to a b + tag, which defines some presentational changes but does not hide its + contents. +

+--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt new file mode 100644 index 00000000..ed1f39b5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt @@ -0,0 +1,10 @@ +Core.Language +TYPE: string +VERSION: 2.0.0 +DEFAULT: 'en' +--DESCRIPTION-- + +ISO 639 language code for localizable things in HTML Purifier to use, +which is mainly error reporting. There is currently only an English (en) +translation, so this directive is currently useless. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LegacyEntityDecoder.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LegacyEntityDecoder.txt new file mode 100644 index 00000000..81d9ae4d --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LegacyEntityDecoder.txt @@ -0,0 +1,36 @@ +Core.LegacyEntityDecoder +TYPE: bool +VERSION: 4.9.0 +DEFAULT: false +--DESCRIPTION-- +

+ Prior to HTML Purifier 4.9.0, entities were decoded by performing + a global search replace for all entities whose decoded versions + did not have special meanings under HTML, and replaced them with + their decoded versions. We would match all entities, even if they did + not have a trailing semicolon, but only if there weren't any trailing + alphanumeric characters. +

+
- +

+

@@ -67,4 +76,4 @@ function encrypt_password() - \ No newline at end of file + From 597cb9c037d5ce8506f8f07a1db9398eac9b3272 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 17:22:42 +0700 Subject: [PATCH 10/94] protect against xss and csrf 1. start session, add Token 2. autocomplete="off" --- themes/default/profile/change_password.tmpl.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/themes/default/profile/change_password.tmpl.php b/themes/default/profile/change_password.tmpl.php index 913c1c14..2f6ca5a2 100644 --- a/themes/default/profile/change_password.tmpl.php +++ b/themes/default/profile/change_password.tmpl.php @@ -10,10 +10,17 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + global $onload; $onload = 'document.form.old_password.focus();'; require(TR_INCLUDE_PATH.'header.inc.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + ?> #i', '', $html); + } + + return $html; + } + + /** + * Takes a string of HTML (fragment or document) and returns the content + * @todo Consider making protected + */ + public function extractBody($html) + { + $matches = array(); + $result = preg_match('|(.*?)]*>(.*)|is', $html, $matches); + if ($result) { + // Make sure it's not in a comment + $comment_start = strrpos($matches[1], ''); + if ($comment_start === false || + ($comment_end !== false && $comment_end > $comment_start)) { + return $matches[2]; + } + } + return $html; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Node.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Node.php new file mode 100644 index 00000000..d7dcf623 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Node.php @@ -0,0 +1,49 @@ +preserve[$i] = true; + } + for ($i = 65; $i <= 90; $i++) { // upper-case + $this->preserve[$i] = true; + } + for ($i = 97; $i <= 122; $i++) { // lower-case + $this->preserve[$i] = true; + } + $this->preserve[45] = true; // Dash - + $this->preserve[46] = true; // Period . + $this->preserve[95] = true; // Underscore _ + $this->preserve[126]= true; // Tilde ~ + + // extra letters not to escape + if ($preserve !== false) { + for ($i = 0, $c = strlen($preserve); $i < $c; $i++) { + $this->preserve[ord($preserve[$i])] = true; + } + } + } + + /** + * Our replacement for urlencode, it encodes all non-reserved characters, + * as well as any extra characters that were instructed to be preserved. + * @note + * Assumes that the string has already been normalized, making any + * and all percent escape sequences valid. Percents will not be + * re-escaped, regardless of their status in $preserve + * @param string $string String to be encoded + * @return string Encoded string. + */ + public function encode($string) + { + $ret = ''; + for ($i = 0, $c = strlen($string); $i < $c; $i++) { + if ($string[$i] !== '%' && !isset($this->preserve[$int = ord($string[$i])])) { + $ret .= '%' . sprintf('%02X', $int); + } else { + $ret .= $string[$i]; + } + } + return $ret; + } + + /** + * Fix up percent-encoding by decoding unreserved characters and normalizing. + * @warning This function is affected by $preserve, even though the + * usual desired behavior is for this not to preserve those + * characters. Be careful when reusing instances of PercentEncoder! + * @param string $string String to normalize + * @return string + */ + public function normalize($string) + { + if ($string == '') { + return ''; + } + $parts = explode('%', $string); + $ret = array_shift($parts); + foreach ($parts as $part) { + $length = strlen($part); + if ($length < 2) { + $ret .= '%25' . $part; + continue; + } + $encoding = substr($part, 0, 2); + $text = substr($part, 2); + if (!ctype_xdigit($encoding)) { + $ret .= '%25' . $part; + continue; + } + $int = hexdec($encoding); + if (isset($this->preserve[$int])) { + $ret .= chr($int) . $text; + continue; + } + $encoding = strtoupper($encoding); + $ret .= '%' . $encoding . $text; + } + return $ret; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Printer.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Printer.php new file mode 100644 index 00000000..16acd415 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Printer.php @@ -0,0 +1,218 @@ +getAll(); + $context = new HTMLPurifier_Context(); + $this->generator = new HTMLPurifier_Generator($config, $context); + } + + /** + * Main function that renders object or aspect of that object + * @note Parameters vary depending on printer + */ + // function render() {} + + /** + * Returns a start tag + * @param string $tag Tag name + * @param array $attr Attribute array + * @return string + */ + protected function start($tag, $attr = array()) + { + return $this->generator->generateFromToken( + new HTMLPurifier_Token_Start($tag, $attr ? $attr : array()) + ); + } + + /** + * Returns an end tag + * @param string $tag Tag name + * @return string + */ + protected function end($tag) + { + return $this->generator->generateFromToken( + new HTMLPurifier_Token_End($tag) + ); + } + + /** + * Prints a complete element with content inside + * @param string $tag Tag name + * @param string $contents Element contents + * @param array $attr Tag attributes + * @param bool $escape whether or not to escape contents + * @return string + */ + protected function element($tag, $contents, $attr = array(), $escape = true) + { + return $this->start($tag, $attr) . + ($escape ? $this->escape($contents) : $contents) . + $this->end($tag); + } + + /** + * @param string $tag + * @param array $attr + * @return string + */ + protected function elementEmpty($tag, $attr = array()) + { + return $this->generator->generateFromToken( + new HTMLPurifier_Token_Empty($tag, $attr) + ); + } + + /** + * @param string $text + * @return string + */ + protected function text($text) + { + return $this->generator->generateFromToken( + new HTMLPurifier_Token_Text($text) + ); + } + + /** + * Prints a simple key/value row in a table. + * @param string $name Key + * @param mixed $value Value + * @return string + */ + protected function row($name, $value) + { + if (is_bool($value)) { + $value = $value ? 'On' : 'Off'; + } + return + $this->start('tr') . "\n" . + $this->element('th', $name) . "\n" . + $this->element('td', $value) . "\n" . + $this->end('tr'); + } + + /** + * Escapes a string for HTML output. + * @param string $string String to escape + * @return string + */ + protected function escape($string) + { + $string = HTMLPurifier_Encoder::cleanUTF8($string); + $string = htmlspecialchars($string, ENT_COMPAT, 'UTF-8'); + return $string; + } + + /** + * Takes a list of strings and turns them into a single list + * @param string[] $array List of strings + * @param bool $polite Bool whether or not to add an end before the last + * @return string + */ + protected function listify($array, $polite = false) + { + if (empty($array)) { + return 'None'; + } + $ret = ''; + $i = count($array); + foreach ($array as $value) { + $i--; + $ret .= $value; + if ($i > 0 && !($polite && $i == 1)) { + $ret .= ', '; + } + if ($polite && $i == 1) { + $ret .= 'and '; + } + } + return $ret; + } + + /** + * Retrieves the class of an object without prefixes, as well as metadata + * @param object $obj Object to determine class of + * @param string $sec_prefix Further prefix to remove + * @return string + */ + protected function getClass($obj, $sec_prefix = '') + { + static $five = null; + if ($five === null) { + $five = version_compare(PHP_VERSION, '5', '>='); + } + $prefix = 'HTMLPurifier_' . $sec_prefix; + if (!$five) { + $prefix = strtolower($prefix); + } + $class = str_replace($prefix, '', get_class($obj)); + $lclass = strtolower($class); + $class .= '('; + switch ($lclass) { + case 'enum': + $values = array(); + foreach ($obj->valid_values as $value => $bool) { + $values[] = $value; + } + $class .= implode(', ', $values); + break; + case 'css_composite': + $values = array(); + foreach ($obj->defs as $def) { + $values[] = $this->getClass($def, $sec_prefix); + } + $class .= implode(', ', $values); + break; + case 'css_multiple': + $class .= $this->getClass($obj->single, $sec_prefix) . ', '; + $class .= $obj->max; + break; + case 'css_denyelementdecorator': + $class .= $this->getClass($obj->def, $sec_prefix) . ', '; + $class .= $obj->element; + break; + case 'css_importantdecorator': + $class .= $this->getClass($obj->def, $sec_prefix); + if ($obj->allow) { + $class .= ', !important'; + } + break; + } + $class .= ')'; + return $class; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/PropertyList.php b/protection/xss/htmlpurifier/library/HTMLPurifier/PropertyList.php new file mode 100644 index 00000000..d27fd53e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/PropertyList.php @@ -0,0 +1,122 @@ +parent = $parent; + } + + /** + * Recursively retrieves the value for a key + * @param string $name + * @throws HTMLPurifier_Exception + */ + public function get($name) + { + if ($this->has($name)) { + return $this->data[$name]; + } + // possible performance bottleneck, convert to iterative if necessary + if ($this->parent) { + return $this->parent->get($name); + } + throw new HTMLPurifier_Exception("Key '$name' not found"); + } + + /** + * Sets the value of a key, for this plist + * @param string $name + * @param mixed $value + */ + public function set($name, $value) + { + $this->data[$name] = $value; + } + + /** + * Returns true if a given key exists + * @param string $name + * @return bool + */ + public function has($name) + { + return array_key_exists($name, $this->data); + } + + /** + * Resets a value to the value of it's parent, usually the default. If + * no value is specified, the entire plist is reset. + * @param string $name + */ + public function reset($name = null) + { + if ($name == null) { + $this->data = array(); + } else { + unset($this->data[$name]); + } + } + + /** + * Squashes this property list and all of its property lists into a single + * array, and returns the array. This value is cached by default. + * @param bool $force If true, ignores the cache and regenerates the array. + * @return array + */ + public function squash($force = false) + { + if ($this->cache !== null && !$force) { + return $this->cache; + } + if ($this->parent) { + return $this->cache = array_merge($this->parent->squash($force), $this->data); + } else { + return $this->cache = $this->data; + } + } + + /** + * Returns the parent plist. + * @return HTMLPurifier_PropertyList + */ + public function getParent() + { + return $this->parent; + } + + /** + * Sets the parent plist. + * @param HTMLPurifier_PropertyList $plist Parent plist + */ + public function setParent($plist) + { + $this->parent = $plist; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php b/protection/xss/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php new file mode 100644 index 00000000..1e707e2a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php @@ -0,0 +1,42 @@ +l = strlen($filter); + $this->filter = $filter; + } + + /** + * @return bool + */ + public function accept() + { + $key = $this->getInnerIterator()->key(); + if (strncmp($key, $this->filter, $this->l) !== 0) { + return false; + } + return true; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Queue.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Queue.php new file mode 100644 index 00000000..a75894d4 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Queue.php @@ -0,0 +1,56 @@ +input = $input; + $this->output = array(); + } + + /** + * Shifts an element off the front of the queue. + */ + public function shift() { + if (empty($this->output)) { + $this->output = array_reverse($this->input); + $this->input = array(); + } + if (empty($this->output)) { + return NULL; + } + return array_pop($this->output); + } + + /** + * Pushes an element onto the front of the queue. + */ + public function push($x) { + array_push($this->input, $x); + } + + /** + * Checks if it's empty. + */ + public function isEmpty() { + return empty($this->input) && empty($this->output); + } +} diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Strategy.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Strategy.php new file mode 100644 index 00000000..291eb83c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Strategy.php @@ -0,0 +1,26 @@ +accessed[$index] = true; + return parent::offsetGet($index); + } + + /** + * Returns a lookup array of all array indexes that have been accessed. + * @return array in form array($index => true). + */ + public function getAccessed() + { + return $this->accessed; + } + + /** + * Resets the access array. + */ + public function resetAccessed() + { + $this->accessed = array(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/StringHashParser.php b/protection/xss/htmlpurifier/library/HTMLPurifier/StringHashParser.php new file mode 100644 index 00000000..05abd837 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/StringHashParser.php @@ -0,0 +1,136 @@ + 'DefaultKeyValue', + * 'KEY' => 'Value', + * 'KEY2' => 'Value2', + * 'MULTILINE-KEY' => "Multiline\nvalue.\n", + * ) + * + * We use this as an easy to use file-format for configuration schema + * files, but the class itself is usage agnostic. + * + * You can use ---- to forcibly terminate parsing of a single string-hash; + * this marker is used in multi string-hashes to delimit boundaries. + */ +class HTMLPurifier_StringHashParser +{ + + /** + * @type string + */ + public $default = 'ID'; + + /** + * Parses a file that contains a single string-hash. + * @param string $file + * @return array + */ + public function parseFile($file) + { + if (!file_exists($file)) { + return false; + } + $fh = fopen($file, 'r'); + if (!$fh) { + return false; + } + $ret = $this->parseHandle($fh); + fclose($fh); + return $ret; + } + + /** + * Parses a file that contains multiple string-hashes delimited by '----' + * @param string $file + * @return array + */ + public function parseMultiFile($file) + { + if (!file_exists($file)) { + return false; + } + $ret = array(); + $fh = fopen($file, 'r'); + if (!$fh) { + return false; + } + while (!feof($fh)) { + $ret[] = $this->parseHandle($fh); + } + fclose($fh); + return $ret; + } + + /** + * Internal parser that acepts a file handle. + * @note While it's possible to simulate in-memory parsing by using + * custom stream wrappers, if such a use-case arises we should + * factor out the file handle into its own class. + * @param resource $fh File handle with pointer at start of valid string-hash + * block. + * @return array + */ + protected function parseHandle($fh) + { + $state = false; + $single = false; + $ret = array(); + do { + $line = fgets($fh); + if ($line === false) { + break; + } + $line = rtrim($line, "\n\r"); + if (!$state && $line === '') { + continue; + } + if ($line === '----') { + break; + } + if (strncmp('--#', $line, 3) === 0) { + // Comment + continue; + } elseif (strncmp('--', $line, 2) === 0) { + // Multiline declaration + $state = trim($line, '- '); + if (!isset($ret[$state])) { + $ret[$state] = ''; + } + continue; + } elseif (!$state) { + $single = true; + if (strpos($line, ':') !== false) { + // Single-line declaration + list($state, $line) = explode(':', $line, 2); + $line = trim($line); + } else { + // Use default declaration + $state = $this->default; + } + } + if ($single) { + $ret[$state] = $line; + $single = false; + $state = false; + } else { + $ret[$state] .= "$line\n"; + } + } while (!feof($fh)); + return $ret; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/TagTransform.php b/protection/xss/htmlpurifier/library/HTMLPurifier/TagTransform.php new file mode 100644 index 00000000..0f481bfd --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/TagTransform.php @@ -0,0 +1,37 @@ +line = $l; + $this->col = $c; + } + + /** + * Convenience function for DirectLex settings line/col position. + * @param int $l + * @param int $c + */ + public function rawPosition($l, $c) + { + if ($c === -1) { + $l++; + } + $this->line = $l; + $this->col = $c; + } + + /** + * Converts a token into its corresponding node. + */ + abstract public function toNode(); +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/TokenFactory.php b/protection/xss/htmlpurifier/library/HTMLPurifier/TokenFactory.php new file mode 100644 index 00000000..e016b80e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/TokenFactory.php @@ -0,0 +1,118 @@ +p_start = new HTMLPurifier_Token_Start('', array()); + $this->p_end = new HTMLPurifier_Token_End(''); + $this->p_empty = new HTMLPurifier_Token_Empty('', array()); + $this->p_text = new HTMLPurifier_Token_Text(''); + $this->p_comment = new HTMLPurifier_Token_Comment(''); + } + + /** + * Creates a HTMLPurifier_Token_Start. + * @param string $name Tag name + * @param array $attr Associative array of attributes + * @return HTMLPurifier_Token_Start Generated HTMLPurifier_Token_Start + */ + public function createStart($name, $attr = array()) + { + $p = clone $this->p_start; + $p->__construct($name, $attr); + return $p; + } + + /** + * Creates a HTMLPurifier_Token_End. + * @param string $name Tag name + * @return HTMLPurifier_Token_End Generated HTMLPurifier_Token_End + */ + public function createEnd($name) + { + $p = clone $this->p_end; + $p->__construct($name); + return $p; + } + + /** + * Creates a HTMLPurifier_Token_Empty. + * @param string $name Tag name + * @param array $attr Associative array of attributes + * @return HTMLPurifier_Token_Empty Generated HTMLPurifier_Token_Empty + */ + public function createEmpty($name, $attr = array()) + { + $p = clone $this->p_empty; + $p->__construct($name, $attr); + return $p; + } + + /** + * Creates a HTMLPurifier_Token_Text. + * @param string $data Data of text token + * @return HTMLPurifier_Token_Text Generated HTMLPurifier_Token_Text + */ + public function createText($data) + { + $p = clone $this->p_text; + $p->__construct($data); + return $p; + } + + /** + * Creates a HTMLPurifier_Token_Comment. + * @param string $data Data of comment token + * @return HTMLPurifier_Token_Comment Generated HTMLPurifier_Token_Comment + */ + public function createComment($data) + { + $p = clone $this->p_comment; + $p->__construct($data); + return $p; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/URI.php b/protection/xss/htmlpurifier/library/HTMLPurifier/URI.php new file mode 100644 index 00000000..1a4705a0 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/URI.php @@ -0,0 +1,316 @@ +scheme = is_null($scheme) || ctype_lower($scheme) ? $scheme : strtolower($scheme); + $this->userinfo = $userinfo; + $this->host = $host; + $this->port = is_null($port) ? $port : (int)$port; + $this->path = $path; + $this->query = $query; + $this->fragment = $fragment; + } + + /** + * Retrieves a scheme object corresponding to the URI's scheme/default + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return HTMLPurifier_URIScheme Scheme object appropriate for validating this URI + */ + public function getSchemeObj($config, $context) + { + $registry = HTMLPurifier_URISchemeRegistry::instance(); + if ($this->scheme !== null) { + $scheme_obj = $registry->getScheme($this->scheme, $config, $context); + if (!$scheme_obj) { + return false; + } // invalid scheme, clean it out + } else { + // no scheme: retrieve the default one + $def = $config->getDefinition('URI'); + $scheme_obj = $def->getDefaultScheme($config, $context); + if (!$scheme_obj) { + if ($def->defaultScheme !== null) { + // something funky happened to the default scheme object + trigger_error( + 'Default scheme object "' . $def->defaultScheme . '" was not readable', + E_USER_WARNING + ); + } // suppress error if it's null + return false; + } + } + return $scheme_obj; + } + + /** + * Generic validation method applicable for all schemes. May modify + * this URI in order to get it into a compliant form. + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool True if validation/filtering succeeds, false if failure + */ + public function validate($config, $context) + { + // ABNF definitions from RFC 3986 + $chars_sub_delims = '!$&\'()*+,;='; + $chars_gen_delims = ':/?#[]@'; + $chars_pchar = $chars_sub_delims . ':@'; + + // validate host + if (!is_null($this->host)) { + $host_def = new HTMLPurifier_AttrDef_URI_Host(); + $this->host = $host_def->validate($this->host, $config, $context); + if ($this->host === false) { + $this->host = null; + } + } + + // validate scheme + // NOTE: It's not appropriate to check whether or not this + // scheme is in our registry, since a URIFilter may convert a + // URI that we don't allow into one we do. So instead, we just + // check if the scheme can be dropped because there is no host + // and it is our default scheme. + if (!is_null($this->scheme) && is_null($this->host) || $this->host === '') { + // support for relative paths is pretty abysmal when the + // scheme is present, so axe it when possible + $def = $config->getDefinition('URI'); + if ($def->defaultScheme === $this->scheme) { + $this->scheme = null; + } + } + + // validate username + if (!is_null($this->userinfo)) { + $encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . ':'); + $this->userinfo = $encoder->encode($this->userinfo); + } + + // validate port + if (!is_null($this->port)) { + if ($this->port < 1 || $this->port > 65535) { + $this->port = null; + } + } + + // validate path + $segments_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/'); + if (!is_null($this->host)) { // this catches $this->host === '' + // path-abempty (hier and relative) + // http://www.example.com/my/path + // //www.example.com/my/path (looks odd, but works, and + // recognized by most browsers) + // (this set is valid or invalid on a scheme by scheme + // basis, so we'll deal with it later) + // file:///my/path + // ///my/path + $this->path = $segments_encoder->encode($this->path); + } elseif ($this->path !== '') { + if ($this->path[0] === '/') { + // path-absolute (hier and relative) + // http:/my/path + // /my/path + if (strlen($this->path) >= 2 && $this->path[1] === '/') { + // This could happen if both the host gets stripped + // out + // http://my/path + // //my/path + $this->path = ''; + } else { + $this->path = $segments_encoder->encode($this->path); + } + } elseif (!is_null($this->scheme)) { + // path-rootless (hier) + // http:my/path + // Short circuit evaluation means we don't need to check nz + $this->path = $segments_encoder->encode($this->path); + } else { + // path-noscheme (relative) + // my/path + // (once again, not checking nz) + $segment_nc_encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . '@'); + $c = strpos($this->path, '/'); + if ($c !== false) { + $this->path = + $segment_nc_encoder->encode(substr($this->path, 0, $c)) . + $segments_encoder->encode(substr($this->path, $c)); + } else { + $this->path = $segment_nc_encoder->encode($this->path); + } + } + } else { + // path-empty (hier and relative) + $this->path = ''; // just to be safe + } + + // qf = query and fragment + $qf_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/?'); + + if (!is_null($this->query)) { + $this->query = $qf_encoder->encode($this->query); + } + + if (!is_null($this->fragment)) { + $this->fragment = $qf_encoder->encode($this->fragment); + } + return true; + } + + /** + * Convert URI back to string + * @return string URI appropriate for output + */ + public function toString() + { + // reconstruct authority + $authority = null; + // there is a rendering difference between a null authority + // (http:foo-bar) and an empty string authority + // (http:///foo-bar). + if (!is_null($this->host)) { + $authority = ''; + if (!is_null($this->userinfo)) { + $authority .= $this->userinfo . '@'; + } + $authority .= $this->host; + if (!is_null($this->port)) { + $authority .= ':' . $this->port; + } + } + + // Reconstruct the result + // One might wonder about parsing quirks from browsers after + // this reconstruction. Unfortunately, parsing behavior depends + // on what *scheme* was employed (file:///foo is handled *very* + // differently than http:///foo), so unfortunately we have to + // defer to the schemes to do the right thing. + $result = ''; + if (!is_null($this->scheme)) { + $result .= $this->scheme . ':'; + } + if (!is_null($authority)) { + $result .= '//' . $authority; + } + $result .= $this->path; + if (!is_null($this->query)) { + $result .= '?' . $this->query; + } + if (!is_null($this->fragment)) { + $result .= '#' . $this->fragment; + } + + return $result; + } + + /** + * Returns true if this URL might be considered a 'local' URL given + * the current context. This is true when the host is null, or + * when it matches the host supplied to the configuration. + * + * Note that this does not do any scheme checking, so it is mostly + * only appropriate for metadata that doesn't care about protocol + * security. isBenign is probably what you actually want. + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool + */ + public function isLocal($config, $context) + { + if ($this->host === null) { + return true; + } + $uri_def = $config->getDefinition('URI'); + if ($uri_def->host === $this->host) { + return true; + } + return false; + } + + /** + * Returns true if this URL should be considered a 'benign' URL, + * that is: + * + * - It is a local URL (isLocal), and + * - It has a equal or better level of security + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool + */ + public function isBenign($config, $context) + { + if (!$this->isLocal($config, $context)) { + return false; + } + + $scheme_obj = $this->getSchemeObj($config, $context); + if (!$scheme_obj) { + return false; + } // conservative approach + + $current_scheme_obj = $config->getDefinition('URI')->getDefaultScheme($config, $context); + if ($current_scheme_obj->secure) { + if (!$scheme_obj->secure) { + return false; + } + } + return true; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/URIDefinition.php b/protection/xss/htmlpurifier/library/HTMLPurifier/URIDefinition.php new file mode 100644 index 00000000..dbc2a752 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/URIDefinition.php @@ -0,0 +1,112 @@ +registerFilter(new HTMLPurifier_URIFilter_DisableExternal()); + $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternalResources()); + $this->registerFilter(new HTMLPurifier_URIFilter_DisableResources()); + $this->registerFilter(new HTMLPurifier_URIFilter_HostBlacklist()); + $this->registerFilter(new HTMLPurifier_URIFilter_SafeIframe()); + $this->registerFilter(new HTMLPurifier_URIFilter_MakeAbsolute()); + $this->registerFilter(new HTMLPurifier_URIFilter_Munge()); + } + + public function registerFilter($filter) + { + $this->registeredFilters[$filter->name] = $filter; + } + + public function addFilter($filter, $config) + { + $r = $filter->prepare($config); + if ($r === false) return; // null is ok, for backwards compat + if ($filter->post) { + $this->postFilters[$filter->name] = $filter; + } else { + $this->filters[$filter->name] = $filter; + } + } + + protected function doSetup($config) + { + $this->setupMemberVariables($config); + $this->setupFilters($config); + } + + protected function setupFilters($config) + { + foreach ($this->registeredFilters as $name => $filter) { + if ($filter->always_load) { + $this->addFilter($filter, $config); + } else { + $conf = $config->get('URI.' . $name); + if ($conf !== false && $conf !== null) { + $this->addFilter($filter, $config); + } + } + } + unset($this->registeredFilters); + } + + protected function setupMemberVariables($config) + { + $this->host = $config->get('URI.Host'); + $base_uri = $config->get('URI.Base'); + if (!is_null($base_uri)) { + $parser = new HTMLPurifier_URIParser(); + $this->base = $parser->parse($base_uri); + $this->defaultScheme = $this->base->scheme; + if (is_null($this->host)) $this->host = $this->base->host; + } + if (is_null($this->defaultScheme)) $this->defaultScheme = $config->get('URI.DefaultScheme'); + } + + public function getDefaultScheme($config, $context) + { + return HTMLPurifier_URISchemeRegistry::instance()->getScheme($this->defaultScheme, $config, $context); + } + + public function filter(&$uri, $config, $context) + { + foreach ($this->filters as $name => $f) { + $result = $f->filter($uri, $config, $context); + if (!$result) return false; + } + return true; + } + + public function postFilter(&$uri, $config, $context) + { + foreach ($this->postFilters as $name => $f) { + $result = $f->filter($uri, $config, $context); + if (!$result) return false; + } + return true; + } + +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/URIFilter.php b/protection/xss/htmlpurifier/library/HTMLPurifier/URIFilter.php new file mode 100644 index 00000000..0333ea34 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/URIFilter.php @@ -0,0 +1,74 @@ +percentEncoder = new HTMLPurifier_PercentEncoder(); + } + + /** + * Parses a URI. + * @param $uri string URI to parse + * @return HTMLPurifier_URI representation of URI. This representation has + * not been validated yet and may not conform to RFC. + */ + public function parse($uri) + { + $uri = $this->percentEncoder->normalize($uri); + + // Regexp is as per Appendix B. + // Note that ["<>] are an addition to the RFC's recommended + // characters, because they represent external delimeters. + $r_URI = '!'. + '(([a-zA-Z0-9\.\+\-]+):)?'. // 2. Scheme + '(//([^/?#"<>]*))?'. // 4. Authority + '([^?#"<>]*)'. // 5. Path + '(\?([^#"<>]*))?'. // 7. Query + '(#([^"<>]*))?'. // 8. Fragment + '!'; + + $matches = array(); + $result = preg_match($r_URI, $uri, $matches); + + if (!$result) return false; // *really* invalid URI + + // seperate out parts + $scheme = !empty($matches[1]) ? $matches[2] : null; + $authority = !empty($matches[3]) ? $matches[4] : null; + $path = $matches[5]; // always present, can be empty + $query = !empty($matches[6]) ? $matches[7] : null; + $fragment = !empty($matches[8]) ? $matches[9] : null; + + // further parse authority + if ($authority !== null) { + $r_authority = "/^((.+?)@)?(\[[^\]]+\]|[^:]*)(:(\d*))?/"; + $matches = array(); + preg_match($r_authority, $authority, $matches); + $userinfo = !empty($matches[1]) ? $matches[2] : null; + $host = !empty($matches[3]) ? $matches[3] : ''; + $port = !empty($matches[4]) ? (int) $matches[5] : null; + } else { + $port = $host = $userinfo = null; + } + + return new HTMLPurifier_URI( + $scheme, $userinfo, $host, $port, $path, $query, $fragment); + } + +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/URIScheme.php b/protection/xss/htmlpurifier/library/HTMLPurifier/URIScheme.php new file mode 100644 index 00000000..03602abe --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/URIScheme.php @@ -0,0 +1,102 @@ +, resolves edge cases + * with making relative URIs absolute + * @type bool + */ + public $hierarchical = false; + + /** + * Whether or not the URI may omit a hostname when the scheme is + * explicitly specified, ala file:///path/to/file. As of writing, + * 'file' is the only scheme that browsers support his properly. + * @type bool + */ + public $may_omit_host = false; + + /** + * Validates the components of a URI for a specific scheme. + * @param HTMLPurifier_URI $uri Reference to a HTMLPurifier_URI object + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool success or failure + */ + abstract public function doValidate(&$uri, $config, $context); + + /** + * Public interface for validating components of a URI. Performs a + * bunch of default actions. Don't overload this method. + * @param HTMLPurifier_URI $uri Reference to a HTMLPurifier_URI object + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool success or failure + */ + public function validate(&$uri, $config, $context) + { + if ($this->default_port == $uri->port) { + $uri->port = null; + } + // kludge: browsers do funny things when the scheme but not the + // authority is set + if (!$this->may_omit_host && + // if the scheme is present, a missing host is always in error + (!is_null($uri->scheme) && ($uri->host === '' || is_null($uri->host))) || + // if the scheme is not present, a *blank* host is in error, + // since this translates into '///path' which most browsers + // interpret as being 'http://path'. + (is_null($uri->scheme) && $uri->host === '') + ) { + do { + if (is_null($uri->scheme)) { + if (substr($uri->path, 0, 2) != '//') { + $uri->host = null; + break; + } + // URI is '////path', so we cannot nullify the + // host to preserve semantics. Try expanding the + // hostname instead (fall through) + } + // first see if we can manually insert a hostname + $host = $config->get('URI.Host'); + if (!is_null($host)) { + $uri->host = $host; + } else { + // we can't do anything sensible, reject the URL. + return false; + } + } while (false); + } + return $this->doValidate($uri, $config, $context); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php b/protection/xss/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php new file mode 100644 index 00000000..24280638 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php @@ -0,0 +1,81 @@ +get('URI.AllowedSchemes'); + if (!$config->get('URI.OverrideAllowedSchemes') && + !isset($allowed_schemes[$scheme]) + ) { + return; + } + + if (isset($this->schemes[$scheme])) { + return $this->schemes[$scheme]; + } + if (!isset($allowed_schemes[$scheme])) { + return; + } + + $class = 'HTMLPurifier_URIScheme_' . $scheme; + if (!class_exists($class)) { + return; + } + $this->schemes[$scheme] = new $class(); + return $this->schemes[$scheme]; + } + + /** + * Registers a custom scheme to the cache, bypassing reflection. + * @param string $scheme Scheme name + * @param HTMLPurifier_URIScheme $scheme_obj + */ + public function register($scheme, $scheme_obj) + { + $this->schemes[$scheme] = $scheme_obj; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/UnitConverter.php b/protection/xss/htmlpurifier/library/HTMLPurifier/UnitConverter.php new file mode 100644 index 00000000..e663b327 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/UnitConverter.php @@ -0,0 +1,307 @@ + array( + 'px' => 3, // This is as per CSS 2.1 and Firefox. Your mileage may vary + 'pt' => 4, + 'pc' => 48, + 'in' => 288, + self::METRIC => array('pt', '0.352777778', 'mm'), + ), + self::METRIC => array( + 'mm' => 1, + 'cm' => 10, + self::ENGLISH => array('mm', '2.83464567', 'pt'), + ), + ); + + /** + * Minimum bcmath precision for output. + * @type int + */ + protected $outputPrecision; + + /** + * Bcmath precision for internal calculations. + * @type int + */ + protected $internalPrecision; + + /** + * Whether or not BCMath is available. + * @type bool + */ + private $bcmath; + + public function __construct($output_precision = 4, $internal_precision = 10, $force_no_bcmath = false) + { + $this->outputPrecision = $output_precision; + $this->internalPrecision = $internal_precision; + $this->bcmath = !$force_no_bcmath && function_exists('bcmul'); + } + + /** + * Converts a length object of one unit into another unit. + * @param HTMLPurifier_Length $length + * Instance of HTMLPurifier_Length to convert. You must validate() + * it before passing it here! + * @param string $to_unit + * Unit to convert to. + * @return HTMLPurifier_Length|bool + * @note + * About precision: This conversion function pays very special + * attention to the incoming precision of values and attempts + * to maintain a number of significant figure. Results are + * fairly accurate up to nine digits. Some caveats: + * - If a number is zero-padded as a result of this significant + * figure tracking, the zeroes will be eliminated. + * - If a number contains less than four sigfigs ($outputPrecision) + * and this causes some decimals to be excluded, those + * decimals will be added on. + */ + public function convert($length, $to_unit) + { + if (!$length->isValid()) { + return false; + } + + $n = $length->getN(); + $unit = $length->getUnit(); + + if ($n === '0' || $unit === false) { + return new HTMLPurifier_Length('0', false); + } + + $state = $dest_state = false; + foreach (self::$units as $k => $x) { + if (isset($x[$unit])) { + $state = $k; + } + if (isset($x[$to_unit])) { + $dest_state = $k; + } + } + if (!$state || !$dest_state) { + return false; + } + + // Some calculations about the initial precision of the number; + // this will be useful when we need to do final rounding. + $sigfigs = $this->getSigFigs($n); + if ($sigfigs < $this->outputPrecision) { + $sigfigs = $this->outputPrecision; + } + + // BCMath's internal precision deals only with decimals. Use + // our default if the initial number has no decimals, or increase + // it by how ever many decimals, thus, the number of guard digits + // will always be greater than or equal to internalPrecision. + $log = (int)floor(log(abs($n), 10)); + $cp = ($log < 0) ? $this->internalPrecision - $log : $this->internalPrecision; // internal precision + + for ($i = 0; $i < 2; $i++) { + + // Determine what unit IN THIS SYSTEM we need to convert to + if ($dest_state === $state) { + // Simple conversion + $dest_unit = $to_unit; + } else { + // Convert to the smallest unit, pending a system shift + $dest_unit = self::$units[$state][$dest_state][0]; + } + + // Do the conversion if necessary + if ($dest_unit !== $unit) { + $factor = $this->div(self::$units[$state][$unit], self::$units[$state][$dest_unit], $cp); + $n = $this->mul($n, $factor, $cp); + $unit = $dest_unit; + } + + // Output was zero, so bail out early. Shouldn't ever happen. + if ($n === '') { + $n = '0'; + $unit = $to_unit; + break; + } + + // It was a simple conversion, so bail out + if ($dest_state === $state) { + break; + } + + if ($i !== 0) { + // Conversion failed! Apparently, the system we forwarded + // to didn't have this unit. This should never happen! + return false; + } + + // Pre-condition: $i == 0 + + // Perform conversion to next system of units + $n = $this->mul($n, self::$units[$state][$dest_state][1], $cp); + $unit = self::$units[$state][$dest_state][2]; + $state = $dest_state; + + // One more loop around to convert the unit in the new system. + + } + + // Post-condition: $unit == $to_unit + if ($unit !== $to_unit) { + return false; + } + + // Useful for debugging: + //echo "
n";
+        //echo "$n\nsigfigs = $sigfigs\nnew_log = $new_log\nlog = $log\nrp = $rp\n
\n"; + + $n = $this->round($n, $sigfigs); + if (strpos($n, '.') !== false) { + $n = rtrim($n, '0'); + } + $n = rtrim($n, '.'); + + return new HTMLPurifier_Length($n, $unit); + } + + /** + * Returns the number of significant figures in a string number. + * @param string $n Decimal number + * @return int number of sigfigs + */ + public function getSigFigs($n) + { + $n = ltrim($n, '0+-'); + $dp = strpos($n, '.'); // decimal position + if ($dp === false) { + $sigfigs = strlen(rtrim($n, '0')); + } else { + $sigfigs = strlen(ltrim($n, '0.')); // eliminate extra decimal character + if ($dp !== 0) { + $sigfigs--; + } + } + return $sigfigs; + } + + /** + * Adds two numbers, using arbitrary precision when available. + * @param string $s1 + * @param string $s2 + * @param int $scale + * @return string + */ + private function add($s1, $s2, $scale) + { + if ($this->bcmath) { + return bcadd($s1, $s2, $scale); + } else { + return $this->scale((float)$s1 + (float)$s2, $scale); + } + } + + /** + * Multiples two numbers, using arbitrary precision when available. + * @param string $s1 + * @param string $s2 + * @param int $scale + * @return string + */ + private function mul($s1, $s2, $scale) + { + if ($this->bcmath) { + return bcmul($s1, $s2, $scale); + } else { + return $this->scale((float)$s1 * (float)$s2, $scale); + } + } + + /** + * Divides two numbers, using arbitrary precision when available. + * @param string $s1 + * @param string $s2 + * @param int $scale + * @return string + */ + private function div($s1, $s2, $scale) + { + if ($this->bcmath) { + return bcdiv($s1, $s2, $scale); + } else { + return $this->scale((float)$s1 / (float)$s2, $scale); + } + } + + /** + * Rounds a number according to the number of sigfigs it should have, + * using arbitrary precision when available. + * @param float $n + * @param int $sigfigs + * @return string + */ + private function round($n, $sigfigs) + { + $new_log = (int)floor(log(abs($n), 10)); // Number of digits left of decimal - 1 + $rp = $sigfigs - $new_log - 1; // Number of decimal places needed + $neg = $n < 0 ? '-' : ''; // Negative sign + if ($this->bcmath) { + if ($rp >= 0) { + $n = bcadd($n, $neg . '0.' . str_repeat('0', $rp) . '5', $rp + 1); + $n = bcdiv($n, '1', $rp); + } else { + // This algorithm partially depends on the standardized + // form of numbers that comes out of bcmath. + $n = bcadd($n, $neg . '5' . str_repeat('0', $new_log - $sigfigs), 0); + $n = substr($n, 0, $sigfigs + strlen($neg)) . str_repeat('0', $new_log - $sigfigs + 1); + } + return $n; + } else { + return $this->scale(round($n, $sigfigs - $new_log - 1), $rp + 1); + } + } + + /** + * Scales a float to $scale digits right of decimal point, like BCMath. + * @param float $r + * @param int $scale + * @return string + */ + private function scale($r, $scale) + { + if ($scale < 0) { + // The f sprintf type doesn't support negative numbers, so we + // need to cludge things manually. First get the string. + $r = sprintf('%.0f', (float)$r); + // Due to floating point precision loss, $r will more than likely + // look something like 4652999999999.9234. We grab one more digit + // than we need to precise from $r and then use that to round + // appropriately. + $precise = (string)round(substr($r, 0, strlen($r) + $scale), -1); + // Now we return it, truncating the zero that was rounded off. + return substr($precise, 0, -1) . str_repeat('0', -$scale + 1); + } + return sprintf('%.' . $scale . 'f', (float)$r); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/VarParser.php b/protection/xss/htmlpurifier/library/HTMLPurifier/VarParser.php new file mode 100644 index 00000000..4bf7771a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/VarParser.php @@ -0,0 +1,198 @@ + self::STRING, + 'istring' => self::ISTRING, + 'text' => self::TEXT, + 'itext' => self::ITEXT, + 'int' => self::INT, + 'float' => self::FLOAT, + 'bool' => self::BOOL, + 'lookup' => self::LOOKUP, + 'list' => self::ALIST, + 'hash' => self::HASH, + 'mixed' => self::MIXED + ); + + /** + * Lookup table of types that are string, and can have aliases or + * allowed value lists. + */ + public static $stringTypes = array( + self::STRING => true, + self::ISTRING => true, + self::TEXT => true, + self::ITEXT => true, + ); + + /** + * Validate a variable according to type. + * It may return NULL as a valid type if $allow_null is true. + * + * @param mixed $var Variable to validate + * @param int $type Type of variable, see HTMLPurifier_VarParser->types + * @param bool $allow_null Whether or not to permit null as a value + * @return string Validated and type-coerced variable + * @throws HTMLPurifier_VarParserException + */ + final public function parse($var, $type, $allow_null = false) + { + if (is_string($type)) { + if (!isset(HTMLPurifier_VarParser::$types[$type])) { + throw new HTMLPurifier_VarParserException("Invalid type '$type'"); + } else { + $type = HTMLPurifier_VarParser::$types[$type]; + } + } + $var = $this->parseImplementation($var, $type, $allow_null); + if ($allow_null && $var === null) { + return null; + } + // These are basic checks, to make sure nothing horribly wrong + // happened in our implementations. + switch ($type) { + case (self::STRING): + case (self::ISTRING): + case (self::TEXT): + case (self::ITEXT): + if (!is_string($var)) { + break; + } + if ($type == self::ISTRING || $type == self::ITEXT) { + $var = strtolower($var); + } + return $var; + case (self::INT): + if (!is_int($var)) { + break; + } + return $var; + case (self::FLOAT): + if (!is_float($var)) { + break; + } + return $var; + case (self::BOOL): + if (!is_bool($var)) { + break; + } + return $var; + case (self::LOOKUP): + case (self::ALIST): + case (self::HASH): + if (!is_array($var)) { + break; + } + if ($type === self::LOOKUP) { + foreach ($var as $k) { + if ($k !== true) { + $this->error('Lookup table contains value other than true'); + } + } + } elseif ($type === self::ALIST) { + $keys = array_keys($var); + if (array_keys($keys) !== $keys) { + $this->error('Indices for list are not uniform'); + } + } + return $var; + case (self::MIXED): + return $var; + default: + $this->errorInconsistent(get_class($this), $type); + } + $this->errorGeneric($var, $type); + } + + /** + * Actually implements the parsing. Base implementation does not + * do anything to $var. Subclasses should overload this! + * @param mixed $var + * @param int $type + * @param bool $allow_null + * @return string + */ + protected function parseImplementation($var, $type, $allow_null) + { + return $var; + } + + /** + * Throws an exception. + * @throws HTMLPurifier_VarParserException + */ + protected function error($msg) + { + throw new HTMLPurifier_VarParserException($msg); + } + + /** + * Throws an inconsistency exception. + * @note This should not ever be called. It would be called if we + * extend the allowed values of HTMLPurifier_VarParser without + * updating subclasses. + * @param string $class + * @param int $type + * @throws HTMLPurifier_Exception + */ + protected function errorInconsistent($class, $type) + { + throw new HTMLPurifier_Exception( + "Inconsistency in $class: " . HTMLPurifier_VarParser::getTypeName($type) . + " not implemented" + ); + } + + /** + * Generic error for if a type didn't work. + * @param mixed $var + * @param int $type + */ + protected function errorGeneric($var, $type) + { + $vtype = gettype($var); + $this->error("Expected type " . HTMLPurifier_VarParser::getTypeName($type) . ", got $vtype"); + } + + /** + * @param int $type + * @return string + */ + public static function getTypeName($type) + { + static $lookup; + if (!$lookup) { + // Lazy load the alternative lookup table + $lookup = array_flip(HTMLPurifier_VarParser::$types); + } + if (!isset($lookup[$type])) { + return 'unknown'; + } + return $lookup[$type]; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/VarParserException.php b/protection/xss/htmlpurifier/library/HTMLPurifier/VarParserException.php new file mode 100644 index 00000000..82e465d6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/VarParserException.php @@ -0,0 +1,11 @@ +front = $front; + $this->back = $back; + } + + /** + * Creates a zipper from an array, with a hole in the + * 0-index position. + * @param Array to zipper-ify. + * @return Tuple of zipper and element of first position. + */ + static public function fromArray($array) { + $z = new self(array(), array_reverse($array)); + $t = $z->delete(); // delete the "dummy hole" + return array($z, $t); + } + + /** + * Convert zipper back into a normal array, optionally filling in + * the hole with a value. (Usually you should supply a $t, unless you + * are at the end of the array.) + */ + public function toArray($t = NULL) { + $a = $this->front; + if ($t !== NULL) $a[] = $t; + for ($i = count($this->back)-1; $i >= 0; $i--) { + $a[] = $this->back[$i]; + } + return $a; + } + + /** + * Move hole to the next element. + * @param $t Element to fill hole with + * @return Original contents of new hole. + */ + public function next($t) { + if ($t !== NULL) array_push($this->front, $t); + return empty($this->back) ? NULL : array_pop($this->back); + } + + /** + * Iterated hole advancement. + * @param $t Element to fill hole with + * @param $i How many forward to advance hole + * @return Original contents of new hole, i away + */ + public function advance($t, $n) { + for ($i = 0; $i < $n; $i++) { + $t = $this->next($t); + } + return $t; + } + + /** + * Move hole to the previous element + * @param $t Element to fill hole with + * @return Original contents of new hole. + */ + public function prev($t) { + if ($t !== NULL) array_push($this->back, $t); + return empty($this->front) ? NULL : array_pop($this->front); + } + + /** + * Delete contents of current hole, shifting hole to + * next element. + * @return Original contents of new hole. + */ + public function delete() { + return empty($this->back) ? NULL : array_pop($this->back); + } + + /** + * Returns true if we are at the end of the list. + * @return bool + */ + public function done() { + return empty($this->back); + } + + /** + * Insert element before hole. + * @param Element to insert + */ + public function insertBefore($t) { + if ($t !== NULL) array_push($this->front, $t); + } + + /** + * Insert element after hole. + * @param Element to insert + */ + public function insertAfter($t) { + if ($t !== NULL) array_push($this->back, $t); + } + + /** + * Splice in multiple elements at hole. Functional specification + * in terms of array_splice: + * + * $arr1 = $arr; + * $old1 = array_splice($arr1, $i, $delete, $replacement); + * + * list($z, $t) = HTMLPurifier_Zipper::fromArray($arr); + * $t = $z->advance($t, $i); + * list($old2, $t) = $z->splice($t, $delete, $replacement); + * $arr2 = $z->toArray($t); + * + * assert($old1 === $old2); + * assert($arr1 === $arr2); + * + * NB: the absolute index location after this operation is + * *unchanged!* + * + * @param Current contents of hole. + */ + public function splice($t, $delete, $replacement) { + // delete + $old = array(); + $r = $t; + for ($i = $delete; $i > 0; $i--) { + $old[] = $r; + $r = $this->delete(); + } + // insert + for ($i = count($replacement)-1; $i >= 0; $i--) { + $this->insertAfter($r); + $r = $replacement[$i]; + } + return array($old, $r); + } +} From 54a64424059b2ec9a81295a7472b738684cc0619 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 17:58:48 +0700 Subject: [PATCH 13/94] Validator --- .../HTMLPurifier/ConfigSchema/Validator.php | 495 ++++++++++++++++++ 1 file changed, 495 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php new file mode 100644 index 00000000..d31a219a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php @@ -0,0 +1,495 @@ +parser = new HTMLPurifier_VarParser(); + + } + + + + /** + + * Validates a fully-formed interchange object. + + * @param HTMLPurifier_ConfigSchema_Interchange $interchange + + * @return bool + + */ + + public function validate($interchange) + + { + + $this->interchange = $interchange; + + $this->aliases = array(); + + // PHP is a bit lax with integer <=> string conversions in + + // arrays, so we don't use the identical !== comparison + + foreach ($interchange->directives as $i => $directive) { + + $id = $directive->id->toString(); + + if ($i != $id) { + + $this->error(false, "Integrity violation: key '$i' does not match internal id '$id'"); + + } + + $this->validateDirective($directive); + + } + + return true; + + } + + + + /** + + * Validates a HTMLPurifier_ConfigSchema_Interchange_Id object. + + * @param HTMLPurifier_ConfigSchema_Interchange_Id $id + + */ + + public function validateId($id) + + { + + $id_string = $id->toString(); + + $this->context[] = "id '$id_string'"; + + if (!$id instanceof HTMLPurifier_ConfigSchema_Interchange_Id) { + + // handled by InterchangeBuilder + + $this->error(false, 'is not an instance of HTMLPurifier_ConfigSchema_Interchange_Id'); + + } + + // keys are now unconstrained (we might want to narrow down to A-Za-z0-9.) + + // we probably should check that it has at least one namespace + + $this->with($id, 'key') + + ->assertNotEmpty() + + ->assertIsString(); // implicit assertIsString handled by InterchangeBuilder + + array_pop($this->context); + + } + + + + /** + + * Validates a HTMLPurifier_ConfigSchema_Interchange_Directive object. + + * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d + + */ + + public function validateDirective($d) + + { + + $id = $d->id->toString(); + + $this->context[] = "directive '$id'"; + + $this->validateId($d->id); + + + + $this->with($d, 'description') + + ->assertNotEmpty(); + + + + // BEGIN - handled by InterchangeBuilder + + $this->with($d, 'type') + + ->assertNotEmpty(); + + $this->with($d, 'typeAllowsNull') + + ->assertIsBool(); + + try { + + // This also tests validity of $d->type + + $this->parser->parse($d->default, $d->type, $d->typeAllowsNull); + + } catch (HTMLPurifier_VarParserException $e) { + + $this->error('default', 'had error: ' . $e->getMessage()); + + } + + // END - handled by InterchangeBuilder + + + + if (!is_null($d->allowed) || !empty($d->valueAliases)) { + + // allowed and valueAliases require that we be dealing with + + // strings, so check for that early. + + $d_int = HTMLPurifier_VarParser::$types[$d->type]; + + if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) { + + $this->error('type', 'must be a string type when used with allowed or value aliases'); + + } + + } + + + + $this->validateDirectiveAllowed($d); + + $this->validateDirectiveValueAliases($d); + + $this->validateDirectiveAliases($d); + + + + array_pop($this->context); + + } + + + + /** + + * Extra validation if $allowed member variable of + + * HTMLPurifier_ConfigSchema_Interchange_Directive is defined. + + * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d + + */ + + public function validateDirectiveAllowed($d) + + { + + if (is_null($d->allowed)) { + + return; + + } + + $this->with($d, 'allowed') + + ->assertNotEmpty() + + ->assertIsLookup(); // handled by InterchangeBuilder + + if (is_string($d->default) && !isset($d->allowed[$d->default])) { + + $this->error('default', 'must be an allowed value'); + + } + + $this->context[] = 'allowed'; + + foreach ($d->allowed as $val => $x) { + + if (!is_string($val)) { + + $this->error("value $val", 'must be a string'); + + } + + } + + array_pop($this->context); + + } + + + + /** + + * Extra validation if $valueAliases member variable of + + * HTMLPurifier_ConfigSchema_Interchange_Directive is defined. + + * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d + + */ + + public function validateDirectiveValueAliases($d) + + { + + if (is_null($d->valueAliases)) { + + return; + + } + + $this->with($d, 'valueAliases') + + ->assertIsArray(); // handled by InterchangeBuilder + + $this->context[] = 'valueAliases'; + + foreach ($d->valueAliases as $alias => $real) { + + if (!is_string($alias)) { + + $this->error("alias $alias", 'must be a string'); + + } + + if (!is_string($real)) { + + $this->error("alias target $real from alias '$alias'", 'must be a string'); + + } + + if ($alias === $real) { + + $this->error("alias '$alias'", "must not be an alias to itself"); + + } + + } + + if (!is_null($d->allowed)) { + + foreach ($d->valueAliases as $alias => $real) { + + if (isset($d->allowed[$alias])) { + + $this->error("alias '$alias'", 'must not be an allowed value'); + + } elseif (!isset($d->allowed[$real])) { + + $this->error("alias '$alias'", 'must be an alias to an allowed value'); + + } + + } + + } + + array_pop($this->context); + + } + + + + /** + + * Extra validation if $aliases member variable of + + * HTMLPurifier_ConfigSchema_Interchange_Directive is defined. + + * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d + + */ + + public function validateDirectiveAliases($d) + + { + + $this->with($d, 'aliases') + + ->assertIsArray(); // handled by InterchangeBuilder + + $this->context[] = 'aliases'; + + foreach ($d->aliases as $alias) { + + $this->validateId($alias); + + $s = $alias->toString(); + + if (isset($this->interchange->directives[$s])) { + + $this->error("alias '$s'", 'collides with another directive'); + + } + + if (isset($this->aliases[$s])) { + + $other_directive = $this->aliases[$s]; + + $this->error("alias '$s'", "collides with alias for directive '$other_directive'"); + + } + + $this->aliases[$s] = $d->id->toString(); + + } + + array_pop($this->context); + + } + + + + // protected helper functions + + + + /** + + * Convenience function for generating HTMLPurifier_ConfigSchema_ValidatorAtom + + * for validating simple member variables of objects. + + * @param $obj + + * @param $member + + * @return HTMLPurifier_ConfigSchema_ValidatorAtom + + */ + + protected function with($obj, $member) + + { + + return new HTMLPurifier_ConfigSchema_ValidatorAtom($this->getFormattedContext(), $obj, $member); + + } + + + + /** + + * Emits an error, providing helpful context. + + * @throws HTMLPurifier_ConfigSchema_Exception + + */ + + protected function error($target, $msg) + + { + + if ($target !== false) { + + $prefix = ucfirst($target) . ' in ' . $this->getFormattedContext(); + + } else { + + $prefix = ucfirst($this->getFormattedContext()); + + } + + throw new HTMLPurifier_ConfigSchema_Exception(trim($prefix . ' ' . $msg)); + + } + + + + /** + + * Returns a formatted context string. + + * @return string + + */ + + protected function getFormattedContext() + + { + + return implode(' in ', array_reverse($this->context)); + + } + +} + + + +// vim: et sw=4 sts=4 From 7e7a1be35e1d1055da8b2c9164550a94997c9899 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 18:05:50 +0700 Subject: [PATCH 14/94] Add files via upload --- .../HTMLPurifier/ConfigSchema/Exception.php | 11 + .../HTMLPurifier/ConfigSchema/Interchange.php | 47 ++++ .../ConfigSchema/InterchangeBuilder.php | 226 ++++++++++++++++++ .../ConfigSchema/ValidatorAtom.php | 130 ++++++++++ .../HTMLPurifier/ConfigSchema/schema.ser | Bin 0 -> 15923 bytes 5 files changed, 414 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php new file mode 100644 index 00000000..1abdcfc0 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php @@ -0,0 +1,11 @@ + array(directive info) + * @type HTMLPurifier_ConfigSchema_Interchange_Directive[] + */ + public $directives = array(); + + /** + * Adds a directive array to $directives + * @param HTMLPurifier_ConfigSchema_Interchange_Directive $directive + * @throws HTMLPurifier_ConfigSchema_Exception + */ + public function addDirective($directive) + { + if (isset($this->directives[$i = $directive->id->toString()])) { + throw new HTMLPurifier_ConfigSchema_Exception("Cannot redefine directive '$i'"); + } + $this->directives[$i] = $directive; + } + + /** + * Convenience function to perform standard validation. Throws exception + * on failed validation. + */ + public function validate() + { + $validator = new HTMLPurifier_ConfigSchema_Validator(); + return $validator->validate($this); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php new file mode 100644 index 00000000..fe9b3268 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php @@ -0,0 +1,226 @@ +varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native(); + } + + /** + * @param string $dir + * @return HTMLPurifier_ConfigSchema_Interchange + */ + public static function buildFromDirectory($dir = null) + { + $builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder(); + $interchange = new HTMLPurifier_ConfigSchema_Interchange(); + return $builder->buildDir($interchange, $dir); + } + + /** + * @param HTMLPurifier_ConfigSchema_Interchange $interchange + * @param string $dir + * @return HTMLPurifier_ConfigSchema_Interchange + */ + public function buildDir($interchange, $dir = null) + { + if (!$dir) { + $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema'; + } + if (file_exists($dir . '/info.ini')) { + $info = parse_ini_file($dir . '/info.ini'); + $interchange->name = $info['name']; + } + + $files = array(); + $dh = opendir($dir); + while (false !== ($file = readdir($dh))) { + if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') { + continue; + } + $files[] = $file; + } + closedir($dh); + + sort($files); + foreach ($files as $file) { + $this->buildFile($interchange, $dir . '/' . $file); + } + return $interchange; + } + + /** + * @param HTMLPurifier_ConfigSchema_Interchange $interchange + * @param string $file + */ + public function buildFile($interchange, $file) + { + $parser = new HTMLPurifier_StringHashParser(); + $this->build( + $interchange, + new HTMLPurifier_StringHash($parser->parseFile($file)) + ); + } + + /** + * Builds an interchange object based on a hash. + * @param HTMLPurifier_ConfigSchema_Interchange $interchange HTMLPurifier_ConfigSchema_Interchange object to build + * @param HTMLPurifier_StringHash $hash source data + * @throws HTMLPurifier_ConfigSchema_Exception + */ + public function build($interchange, $hash) + { + if (!$hash instanceof HTMLPurifier_StringHash) { + $hash = new HTMLPurifier_StringHash($hash); + } + if (!isset($hash['ID'])) { + throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID'); + } + if (strpos($hash['ID'], '.') === false) { + if (count($hash) == 2 && isset($hash['DESCRIPTION'])) { + $hash->offsetGet('DESCRIPTION'); // prevent complaining + } else { + throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace'); + } + } else { + $this->buildDirective($interchange, $hash); + } + $this->_findUnused($hash); + } + + /** + * @param HTMLPurifier_ConfigSchema_Interchange $interchange + * @param HTMLPurifier_StringHash $hash + * @throws HTMLPurifier_ConfigSchema_Exception + */ + public function buildDirective($interchange, $hash) + { + $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive(); + + // These are required elements: + $directive->id = $this->id($hash->offsetGet('ID')); + $id = $directive->id->toString(); // convenience + + if (isset($hash['TYPE'])) { + $type = explode('/', $hash->offsetGet('TYPE')); + if (isset($type[1])) { + $directive->typeAllowsNull = true; + } + $directive->type = $type[0]; + } else { + throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined"); + } + + if (isset($hash['DEFAULT'])) { + try { + $directive->default = $this->varParser->parse( + $hash->offsetGet('DEFAULT'), + $directive->type, + $directive->typeAllowsNull + ); + } catch (HTMLPurifier_VarParserException $e) { + throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'"); + } + } + + if (isset($hash['DESCRIPTION'])) { + $directive->description = $hash->offsetGet('DESCRIPTION'); + } + + if (isset($hash['ALLOWED'])) { + $directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED'))); + } + + if (isset($hash['VALUE-ALIASES'])) { + $directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES')); + } + + if (isset($hash['ALIASES'])) { + $raw_aliases = trim($hash->offsetGet('ALIASES')); + $aliases = preg_split('/\s*,\s*/', $raw_aliases); + foreach ($aliases as $alias) { + $directive->aliases[] = $this->id($alias); + } + } + + if (isset($hash['VERSION'])) { + $directive->version = $hash->offsetGet('VERSION'); + } + + if (isset($hash['DEPRECATED-USE'])) { + $directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE')); + } + + if (isset($hash['DEPRECATED-VERSION'])) { + $directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION'); + } + + if (isset($hash['EXTERNAL'])) { + $directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL'))); + } + + $interchange->addDirective($directive); + } + + /** + * Evaluates an array PHP code string without array() wrapper + * @param string $contents + */ + protected function evalArray($contents) + { + return eval('return array(' . $contents . ');'); + } + + /** + * Converts an array list into a lookup array. + * @param array $array + * @return array + */ + protected function lookup($array) + { + $ret = array(); + foreach ($array as $val) { + $ret[$val] = true; + } + return $ret; + } + + /** + * Convenience function that creates an HTMLPurifier_ConfigSchema_Interchange_Id + * object based on a string Id. + * @param string $id + * @return HTMLPurifier_ConfigSchema_Interchange_Id + */ + protected function id($id) + { + return HTMLPurifier_ConfigSchema_Interchange_Id::make($id); + } + + /** + * Triggers errors for any unused keys passed in the hash; such keys + * may indicate typos, missing values, etc. + * @param HTMLPurifier_StringHash $hash Hash to check. + */ + protected function _findUnused($hash) + { + $accessed = $hash->getAccessed(); + foreach ($hash as $k => $v) { + if (!isset($accessed[$k])) { + trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE); + } + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php new file mode 100644 index 00000000..a2e0b4a1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php @@ -0,0 +1,130 @@ +context = $context; + $this->obj = $obj; + $this->member = $member; + $this->contents =& $obj->$member; + } + + /** + * @return HTMLPurifier_ConfigSchema_ValidatorAtom + */ + public function assertIsString() + { + if (!is_string($this->contents)) { + $this->error('must be a string'); + } + return $this; + } + + /** + * @return HTMLPurifier_ConfigSchema_ValidatorAtom + */ + public function assertIsBool() + { + if (!is_bool($this->contents)) { + $this->error('must be a boolean'); + } + return $this; + } + + /** + * @return HTMLPurifier_ConfigSchema_ValidatorAtom + */ + public function assertIsArray() + { + if (!is_array($this->contents)) { + $this->error('must be an array'); + } + return $this; + } + + /** + * @return HTMLPurifier_ConfigSchema_ValidatorAtom + */ + public function assertNotNull() + { + if ($this->contents === null) { + $this->error('must not be null'); + } + return $this; + } + + /** + * @return HTMLPurifier_ConfigSchema_ValidatorAtom + */ + public function assertAlnum() + { + $this->assertIsString(); + if (!ctype_alnum($this->contents)) { + $this->error('must be alphanumeric'); + } + return $this; + } + + /** + * @return HTMLPurifier_ConfigSchema_ValidatorAtom + */ + public function assertNotEmpty() + { + if (empty($this->contents)) { + $this->error('must not be empty'); + } + return $this; + } + + /** + * @return HTMLPurifier_ConfigSchema_ValidatorAtom + */ + public function assertIsLookup() + { + $this->assertIsArray(); + foreach ($this->contents as $v) { + if ($v !== true) { + $this->error('must be a lookup array'); + } + } + return $this; + } + + /** + * @param string $msg + * @throws HTMLPurifier_ConfigSchema_Exception + */ + protected function error($msg) + { + throw new HTMLPurifier_ConfigSchema_Exception(ucfirst($this->member) . ' in ' . $this->context . ' ' . $msg); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser new file mode 100644 index 0000000000000000000000000000000000000000..371e948f1c76d99bacea65b4735454656858edbf GIT binary patch literal 15923 zcmeHOO>Y}V63tIB6zpXI6QX2q9Qve4B0{Vr8={P4Pr-<6QL`S-aOXpoV)(!Bd(~Cl zO=>7Qhusq$#3rYzyQ}M~t7{%VjE>%p4t~A4y!hDF`CabnKTfOiE?-P%_imXTjE+ZN zo6)<`!Q9+0xx) z^}_i%4o6?VVG1msPI2uDF0hUGkPso0jFeSBHSYB6`Zk}>T^Y0*)M8^NX9F7Ut>4!0A3Ab!_Dhk?J{Ng|4cnlj zqvzCXw{VXu9UUkASi8IYG10`(R6RNKw2Nw%!A?=|Mm^>hBGvp^xdvy|?9=sy zn&HR4!A+rU>TK(fFfnx(xvt%^dT{5Yhn3p^hQHvRuzl7>Y&-6{n0@S zO{8Dv@hgPL?-(9@G#q`+#S^fbrk)+V|AsJmv##J&0{{8ywpk6%A7^gW=2a;{dPHd; zd5e{9M?>z`OTjOgb3; zlOAW{1aa28Oj`k(IUOI6Q7MbP|2 zXNQuPSzT2nHI7~W`0kK@G~^Mf_Iy0H=NMAeS?M!3hm6N3Z~YLEo*c!Eqd1P=V85z> zI*jt}kSp;U2Cce!RV1WC5S8(+o832gX2Uq$c+78@@XLM9EaC+p%O8G2;1@YFgC}r6 zkO5Y4VXs`qQ!u2=9^g_o#3TUWw&;?%Y{6daSo>iJ>iWb+>e7dsCroSnv})gf4ds4GSlZ zR5-|mdqjSBSKac~)zhbPHYr|J~J`W-*>^zaPLEL%CP1WxbsVqViQdZJqxou^zk*&_J$k%f`xxT?yN z>FH#0dXF=7hV2AKNtl%ASE&rn3rE#R1W2}rJk46%LE5H$qBm;NXWbzpU%=@*tymzS z_aoM9p6V9a?CHF0^Y-b?VfQqrY9;bKy4oiptM_E=WtNvM{*QKnfWl#lxMG>WY<17Guw{uTtIA^>PUY_=_P) zugwUHPsLd}fAG-rU~Jau=4X`eiKRjE3@jH?QhST@bVQ{7etAI+A!OIe8_vmSeTgjD zqi-nhMK}m$hu$rb4_nCNEyyZGXt7M;{XrCK!y+lEV1h%eO=tJN!5G)Kd%4PuyQ07W zE~kse5_T_ZhUzEXuT?+P$vRiGyYU3+*GnYSSg4PvH8cNJb%!E=$FCY4#+Au&wU7e= z=>XT#90eLinZf&NDwBPh-Jxv1jb#-JF`1H-iI(8HT1xtG`)`~zK@d|iNBKHOGC|m( z2?{UElVK*JzXaosR^s^7)hr-9?W#h)D1FYgyeM)S88r!jzT90W1A=C z!l8ttx**CD7ncqfFzC*Wl{gwl2Y{mQRl}#^!XHb1v+TZFG5C1+@!y!ro`$S+xwL|-%o zWx#C7W1NewE?H}NUD5hI`rc* zs=y`FWKxMQJE`$4M+!F|JzJZu7pPN*B-rAj;l<#=N7@IJsC7O^M@iaV!6)=!KxB|B z=9G9aGP5I~=DscU(YI(mJa572)e`*=sKB@2V6Gqj{=+Qa@%*{*m^;!zVE>8J8=6B zoHWCb7WN&ueFv^uuC>fU4=c9W!nGRbtn@`9DZN))H)UnxJ+!5Gk=}RU zE(ZG!96?5*+p_P#@onb51DE>5cXi;<5=19$rEd{<%p+&x$&8=~cKXnzLpvoe@6fhI ztL^w5-x{%H&6cutf&(loAH9BuIbO!QoBDq#G9gi3_9O zC}iyeN3a_hj~uH@!KZ@rufYEZSQPy z2h5w3BG0txj#Xa(;HjldtO&nTORx_u0Eb2n)QX%PGP?Wvoqst!`~?` z>BZJx)L7CUw0GSq8oe?iw>F`7Is=_BGAXFeEV6+m+XlV!0w2@Y!c=TiE(aSUP#y_Z z?`4yI=c@f?rmcbyo9l;t(Q1*)Uy7a~|FA8-*7)lnJ?~H(+ejDjp9$_WiNue3B{Gh` z1jJM0BDV!tTnfaCwh!b4h^JJzPoNqQPf1X6AO#>E++7kT-Z3RaedQroJmp}VljB(_ z{gwfRFeEX&kY1la5~nV|`KDR2B6Bgvue~r(gkR@ zD>ZGOxZib=@Sg$r1m0(IP;W0I{9cO+;oZI`_#EJ;Tc%@hM=1o*JEecIYfi^ke=oNe zRkg;q0q}cHO#yxyVBdohQ@N27y*M*MVu@!!N)bpIGX0LMLiO(Gg!S6xuRzm8{kG6E zXqsw+9!f#%{3A3?NpyZsGH6;pI$~7N<%N)f%_1aC)nkV5fut#i8Gbt?O(ikLO-Nci zEJdD(H;bp1C-gzhbZ)aEP<{qAql;TnBjbDFX5f<2$oAQTIMaPH)TuA;)G6Z3GcY+P z49FI}h%=qdES82y#6GB0Jmd-gZGD)$4e`r_)4KoUX%rRmu<`izWwBhNtr$w}FY&ZQ{@umUT>|&$a;`$5fU~ zE>#k&ECV;7hAMlwY{jC6mo1~(;7HYWCr`Mb`q1v&a1;4)87!CH6NxO7i{c+8j%{`W z>5JH1a(k4YpPBt$y%`)1U)=!4-^gz^JRpgKY}=kA!tvw)f%OHu_G&md+&VgPtdEAh zj5PEj@@G0b8o7E%V85d8P`R!}+oh*G@-*-I8j#ugCe zhJW-`!zM5LunM2l$q<+_S%f-;a7;6e zqdz~xpbDt#`PLrZ&w+ln+*bwt?({%lB7rNVHVNK;FEu+cNHsg6Qu z_JB>5h;gES8WPcs-%IYgkT3)H%-6qN@b+L?<7SCW)blQM(!C!+6C`?ksqGTe@gcH1 zfBb6@Q=`J5N=?9}MvOz(e@iF%2{9=n4PP3SBTX{B5rJi=ayDn`R|`@^vR-VP`*n8% zSCtRpkW7<+M?GCt=z*&ndf33O`qo=Na@9|!A}ey$X456)>9h5>fme0#F8u2HCSy`x J>r;OF_FtxB?Uw)m literal 0 HcmV?d00001 From bee18a44558a6d104cc5f5a3d7916f2d1cc7b2df Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 18:07:52 +0700 Subject: [PATCH 15/94] Create ConfigSchema.php --- .../ConfigSchema/Builder/ConfigSchema.php | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php new file mode 100644 index 00000000..a25ab319 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php @@ -0,0 +1,95 @@ +directives as $d) { + + $schema->add( + + $d->id->key, + + $d->default, + + $d->type, + + $d->typeAllowsNull + + ); + + if ($d->allowed !== null) { + + $schema->addAllowedValues( + + $d->id->key, + + $d->allowed + + ); + + } + + foreach ($d->aliases as $alias) { + + $schema->addAlias( + + $alias->key, + + $d->id->key + + ); + + } + + if ($d->valueAliases !== null) { + + $schema->addValueAliases( + + $d->id->key, + + $d->valueAliases + + ); + + } + + } + + $schema->postProcess(); + + return $schema; + + } + +} + + + +// vim: et sw=4 sts=4 From 5157ae7290c489c1950a8cd66de258716c21b4b2 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 18:08:27 +0700 Subject: [PATCH 16/94] Add files via upload --- .../HTMLPurifier/ConfigSchema/Builder/Xml.php | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php new file mode 100644 index 00000000..0d00bf1d --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php @@ -0,0 +1,144 @@ +startElement('div'); + + $purifier = HTMLPurifier::getInstance(); + $html = $purifier->purify($html); + $this->writeAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); + $this->writeRaw($html); + + $this->endElement(); // div + } + + /** + * @param mixed $var + * @return string + */ + protected function export($var) + { + if ($var === array()) { + return 'array()'; + } + return var_export($var, true); + } + + /** + * @param HTMLPurifier_ConfigSchema_Interchange $interchange + */ + public function build($interchange) + { + // global access, only use as last resort + $this->interchange = $interchange; + + $this->setIndent(true); + $this->startDocument('1.0', 'UTF-8'); + $this->startElement('configdoc'); + $this->writeElement('title', $interchange->name); + + foreach ($interchange->directives as $directive) { + $this->buildDirective($directive); + } + + if ($this->namespace) { + $this->endElement(); + } // namespace + + $this->endElement(); // configdoc + $this->flush(); + } + + /** + * @param HTMLPurifier_ConfigSchema_Interchange_Directive $directive + */ + public function buildDirective($directive) + { + // Kludge, although I suppose having a notion of a "root namespace" + // certainly makes things look nicer when documentation is built. + // Depends on things being sorted. + if (!$this->namespace || $this->namespace !== $directive->id->getRootNamespace()) { + if ($this->namespace) { + $this->endElement(); + } // namespace + $this->namespace = $directive->id->getRootNamespace(); + $this->startElement('namespace'); + $this->writeAttribute('id', $this->namespace); + $this->writeElement('name', $this->namespace); + } + + $this->startElement('directive'); + $this->writeAttribute('id', $directive->id->toString()); + + $this->writeElement('name', $directive->id->getDirective()); + + $this->startElement('aliases'); + foreach ($directive->aliases as $alias) { + $this->writeElement('alias', $alias->toString()); + } + $this->endElement(); // aliases + + $this->startElement('constraints'); + if ($directive->version) { + $this->writeElement('version', $directive->version); + } + $this->startElement('type'); + if ($directive->typeAllowsNull) { + $this->writeAttribute('allow-null', 'yes'); + } + $this->text($directive->type); + $this->endElement(); // type + if ($directive->allowed) { + $this->startElement('allowed'); + foreach ($directive->allowed as $value => $x) { + $this->writeElement('value', $value); + } + $this->endElement(); // allowed + } + $this->writeElement('default', $this->export($directive->default)); + $this->writeAttribute('xml:space', 'preserve'); + if ($directive->external) { + $this->startElement('external'); + foreach ($directive->external as $project) { + $this->writeElement('project', $project); + } + $this->endElement(); + } + $this->endElement(); // constraints + + if ($directive->deprecatedVersion) { + $this->startElement('deprecated'); + $this->writeElement('version', $directive->deprecatedVersion); + $this->writeElement('use', $directive->deprecatedUse->toString()); + $this->endElement(); // deprecated + } + + $this->startElement('description'); + $this->writeHTMLDiv($directive->description); + $this->endElement(); // description + + $this->endElement(); // directive + } +} + +// vim: et sw=4 sts=4 From aef64c59cfc50f52d6303d86236bd712c1d61e36 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 18:14:57 +0700 Subject: [PATCH 17/94] Add files via upload --- protection/csrf/LICENSE | 22 ++++++++++ protection/csrf/README.md | 38 +++++++++++++++++ protection/csrf/form_demo.php | 79 +++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 protection/csrf/LICENSE create mode 100644 protection/csrf/README.md create mode 100644 protection/csrf/form_demo.php diff --git a/protection/csrf/LICENSE b/protection/csrf/LICENSE new file mode 100644 index 00000000..a26d079d --- /dev/null +++ b/protection/csrf/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Matt Kent + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/protection/csrf/README.md b/protection/csrf/README.md new file mode 100644 index 00000000..f1688998 --- /dev/null +++ b/protection/csrf/README.md @@ -0,0 +1,38 @@ +CSRF Class +=================== +This is a simple yet effective class to enable you to protect your forms from CSRF attacks. + +**What is CSRF?** +A CSRF attack or Cross Site Request Forgery as it's known is where a malicious user takes advantage of your logged in state. For example, say you used a get request to logout a user, like so: + + http://mysite.com/user/logout +This is a perfectly valid URL, however if this user was also logged in on another site, they could take advantage of this by placing this in an image tag: + + +This would cause the user to be logged out on your site. This is an annoying, but not too serious example. + +To protect from this we use what's called a **security token** which ensures that the request did come from our site. You could use it in a get request like so: + + http://mysite.com/user/logout?hash=6f792794d27d157fda64bc51f296e4f3 +This would prevent that image tag logging the user out as the security token wouldn't be present. +However, there can be problems doing it this way, so your better off logging a user out via a post request in a form. + +## Usage ## +If you look in the **form_demo.php** file, you will see an example of how the class can be used. + +**Step 1:** Echo `Token::display(); ` in your form. + +**Step 2:** Check for a post request and whether the security token is valid. If you want you can also check if it's recent: + ```php + if (!Token::isValid() OR !Token::isRecent()) + { + $errors[] = 'Invalid Security Token'; + // Stop further processing. + } + ``` + +**Step 3:** That's it! + +It's literally as easy as 1..2..3! + + diff --git a/protection/csrf/form_demo.php b/protection/csrf/form_demo.php new file mode 100644 index 00000000..4be35c28 --- /dev/null +++ b/protection/csrf/form_demo.php @@ -0,0 +1,79 @@ + + + + + CSRF Class Form Demo + + + +

CSRF Class Form Demo

+ ' . $error . '
'; + } + echo '
'; + } + + if (@$messages) + { + foreach ($messages as $message) + { + echo '' . $message . '
'; + } + echo '
'; + } + ?> + + + +
+ + + +

+ + + + \ No newline at end of file From 7697de1cb7848f78a10d06aac872e3e6ad682acc Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Wed, 12 Sep 2018 18:19:21 +0700 Subject: [PATCH 18/94] Add files via upload --- protection/xss/htmlpurifier/.gitattributes | 13 + protection/xss/htmlpurifier/.gitignore | 28 + protection/xss/htmlpurifier/.travis.yml | 13 + protection/xss/htmlpurifier/CREDITS | 9 + protection/xss/htmlpurifier/Doxyfile | 1317 +++++++++++++++++ protection/xss/htmlpurifier/INSTALL | 373 +++++ protection/xss/htmlpurifier/INSTALL.fr.utf8 | 60 + protection/xss/htmlpurifier/LICENSE | 504 +++++++ protection/xss/htmlpurifier/NEWS | 1190 +++++++++++++++ protection/xss/htmlpurifier/README.md | 29 + protection/xss/htmlpurifier/TODO | 150 ++ protection/xss/htmlpurifier/VERSION | 1 + protection/xss/htmlpurifier/WHATSNEW | 5 + protection/xss/htmlpurifier/WYSIWYG | 20 + protection/xss/htmlpurifier/composer.json | 25 + protection/xss/htmlpurifier/package.php | 61 + protection/xss/htmlpurifier/phpdoc.ini | 102 ++ .../xss/htmlpurifier/release1-update.php | 110 ++ protection/xss/htmlpurifier/release2-tag.php | 22 + .../xss/htmlpurifier/test-settings.sample.php | 74 + .../xss/htmlpurifier/test-settings.travis.php | 72 + 21 files changed, 4178 insertions(+) create mode 100644 protection/xss/htmlpurifier/.gitattributes create mode 100644 protection/xss/htmlpurifier/.gitignore create mode 100644 protection/xss/htmlpurifier/.travis.yml create mode 100644 protection/xss/htmlpurifier/CREDITS create mode 100644 protection/xss/htmlpurifier/Doxyfile create mode 100644 protection/xss/htmlpurifier/INSTALL create mode 100644 protection/xss/htmlpurifier/INSTALL.fr.utf8 create mode 100644 protection/xss/htmlpurifier/LICENSE create mode 100644 protection/xss/htmlpurifier/NEWS create mode 100644 protection/xss/htmlpurifier/README.md create mode 100644 protection/xss/htmlpurifier/TODO create mode 100644 protection/xss/htmlpurifier/VERSION create mode 100644 protection/xss/htmlpurifier/WHATSNEW create mode 100644 protection/xss/htmlpurifier/WYSIWYG create mode 100644 protection/xss/htmlpurifier/composer.json create mode 100644 protection/xss/htmlpurifier/package.php create mode 100644 protection/xss/htmlpurifier/phpdoc.ini create mode 100644 protection/xss/htmlpurifier/release1-update.php create mode 100644 protection/xss/htmlpurifier/release2-tag.php create mode 100644 protection/xss/htmlpurifier/test-settings.sample.php create mode 100644 protection/xss/htmlpurifier/test-settings.travis.php diff --git a/protection/xss/htmlpurifier/.gitattributes b/protection/xss/htmlpurifier/.gitattributes new file mode 100644 index 00000000..2e8728ed --- /dev/null +++ b/protection/xss/htmlpurifier/.gitattributes @@ -0,0 +1,13 @@ +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/Doxyfile export-ignore +/art/ export-ignore +/benchmarks/ export-ignore +/configdoc/ export-ignore +/configdoc/usage.xml -crlf +/docs/ export-ignore +/phpdoc.ini +/smoketests/ export-ignore +/tests/* export-ignore +/tests/path2class.func.php -export-ignore diff --git a/protection/xss/htmlpurifier/.gitignore b/protection/xss/htmlpurifier/.gitignore new file mode 100644 index 00000000..a099de25 --- /dev/null +++ b/protection/xss/htmlpurifier/.gitignore @@ -0,0 +1,28 @@ +tags +conf/ +test-settings.php +config-schema.php +library/HTMLPurifier/DefinitionCache/Serializer/*/ +library/standalone/ +library/HTMLPurifier.standalone.php +library/HTMLPurifier*.tgz +library/package*.xml +smoketests/test-schema.html +configdoc/*.html +configdoc/configdoc.xml +docs/doxygen* +*.phpt.diff +*.phpt.exp +*.phpt.log +*.phpt.out +*.phpt.php +*.phpt.skip.php +*.htmlt.ini +*.patch +/*.php +vendor +composer.lock +*.rej +*.orig +*.bak +core diff --git a/protection/xss/htmlpurifier/.travis.yml b/protection/xss/htmlpurifier/.travis.yml new file mode 100644 index 00000000..da2ad38f --- /dev/null +++ b/protection/xss/htmlpurifier/.travis.yml @@ -0,0 +1,13 @@ +language: php +php: + - '5.4' + - '5.5' + - '5.6' + - '7.0' + - '7.1' + - '7.2' +before_script: + - git clone --depth=50 https://github.com/ezyang/simpletest.git + - cp test-settings.travis.php test-settings.php +script: + - php tests/index.php diff --git a/protection/xss/htmlpurifier/CREDITS b/protection/xss/htmlpurifier/CREDITS new file mode 100644 index 00000000..d0cc45af --- /dev/null +++ b/protection/xss/htmlpurifier/CREDITS @@ -0,0 +1,9 @@ + +CREDITS + +Almost everything written by Edward Z. Yang (Ambush Commander). Lots of thanks +to the DevNetwork Community for their help (see docs/ref-devnetwork.html for +more details), Feyd especially (namely IPv6 and optimization). Thanks to RSnake +for letting me package his fantastic XSS cheatsheet for a smoketest. + + vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/Doxyfile b/protection/xss/htmlpurifier/Doxyfile new file mode 100644 index 00000000..c73d5d53 --- /dev/null +++ b/protection/xss/htmlpurifier/Doxyfile @@ -0,0 +1,1317 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = HTMLPurifier + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 4.10.0 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = "docs/doxygen " + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class " \ + "The $name widget " \ + "The $name file " \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = "C:/Users/Edward/Webs/htmlpurifier " \ + "C:/Documents and Settings/Edward/My Documents/My Webs/htmlpurifier " + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ". " + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = *.php + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = */tests/* \ + */benchmarks/* \ + */docs/* \ + */test-settings.php \ + */configdoc/* \ + */test-settings.php \ + */maintenance/* \ + */smoketests/* \ + */library/standalone/* \ + */.svn* \ + */conf/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/INSTALL b/protection/xss/htmlpurifier/INSTALL new file mode 100644 index 00000000..e77b5166 --- /dev/null +++ b/protection/xss/htmlpurifier/INSTALL @@ -0,0 +1,373 @@ + +Install + How to install HTML Purifier + +HTML Purifier is designed to run out of the box, so actually using the +library is extremely easy. (Although... if you were looking for a +step-by-step installation GUI, you've downloaded the wrong software!) + +While the impatient can get going immediately with some of the sample +code at the bottom of this library, it's well worth reading this entire +document--most of the other documentation assumes that you are familiar +with these contents. + + +--------------------------------------------------------------------------- +1. Compatibility + +HTML Purifier is PHP 5 and PHP 7, and is actively tested from PHP 5.0.5 +and up. It has no core dependencies with other libraries. + +These optional extensions can enhance the capabilities of HTML Purifier: + + * iconv : Converts text to and from non-UTF-8 encodings + * bcmath : Used for unit conversion and imagecrash protection + * tidy : Used for pretty-printing HTML + +These optional libraries can enhance the capabilities of HTML Purifier: + + * CSSTidy : Clean CSS stylesheets using %Core.ExtractStyleBlocks + Note: You should use the modernized fork of CSSTidy available + at https://github.com/Cerdic/CSSTidy + * Net_IDNA2 (PEAR) : IRI support using %Core.EnableIDNA + Note: This is not necessary for PHP 5.3 or later + +--------------------------------------------------------------------------- +2. Reconnaissance + +A big plus of HTML Purifier is its inerrant support of standards, so +your web-pages should be standards-compliant. (They should also use +semantic markup, but that's another issue altogether, one HTML Purifier +cannot fix without reading your mind.) + +HTML Purifier can process these doctypes: + +* XHTML 1.0 Transitional (default) +* XHTML 1.0 Strict +* HTML 4.01 Transitional +* HTML 4.01 Strict +* XHTML 1.1 + +...and these character encodings: + +* UTF-8 (default) +* Any encoding iconv supports (with crippled internationalization support) + +These defaults reflect what my choices would be if I were authoring an +HTML document, however, what you choose depends on the nature of your +codebase. If you don't know what doctype you are using, you can determine +the doctype from this identifier at the top of your source code: + + + +...and the character encoding from this code: + + + +If the character encoding declaration is missing, STOP NOW, and +read 'docs/enduser-utf8.html' (web accessible at +http://htmlpurifier.org/docs/enduser-utf8.html). In fact, even if it is +present, read this document anyway, as many websites specify their +document's character encoding incorrectly. + + +--------------------------------------------------------------------------- +3. Including the library + +The procedure is quite simple: + + require_once '/path/to/library/HTMLPurifier.auto.php'; + +This will setup an autoloader, so the library's files are only included +when you use them. + +Only the contents in the library/ folder are necessary, so you can remove +everything else when using HTML Purifier in a production environment. + +If you installed HTML Purifier via PEAR, all you need to do is: + + require_once 'HTMLPurifier.auto.php'; + +Please note that the usual PEAR practice of including just the classes you +want will not work with HTML Purifier's autoloading scheme. + +Advanced users, read on; other users can skip to section 4. + +Autoload compatibility +---------------------- + + HTML Purifier attempts to be as smart as possible when registering an + autoloader, but there are some cases where you will need to change + your own code to accomodate HTML Purifier. These are those cases: + + PHP VERSION IS LESS THAN 5.1.2, AND YOU'VE DEFINED __autoload + Because spl_autoload_register() doesn't exist in early versions + of PHP 5, HTML Purifier has no way of adding itself to the autoload + stack. Modify your __autoload function to test + HTMLPurifier_Bootstrap::autoload($class) + + For example, suppose your autoload function looks like this: + + function __autoload($class) { + require str_replace('_', '/', $class) . '.php'; + return true; + } + + A modified version with HTML Purifier would look like this: + + function __autoload($class) { + if (HTMLPurifier_Bootstrap::autoload($class)) return true; + require str_replace('_', '/', $class) . '.php'; + return true; + } + + Note that there *is* some custom behavior in our autoloader; the + original autoloader in our example would work for 99% of the time, + but would fail when including language files. + + AN __autoload FUNCTION IS DECLARED AFTER OUR AUTOLOADER IS REGISTERED + spl_autoload_register() has the curious behavior of disabling + the existing __autoload() handler. Users need to explicitly + spl_autoload_register('__autoload'). Because we use SPL when it + is available, __autoload() will ALWAYS be disabled. If __autoload() + is declared before HTML Purifier is loaded, this is not a problem: + HTML Purifier will register the function for you. But if it is + declared afterwards, it will mysteriously not work. This + snippet of code (after your autoloader is defined) will fix it: + + spl_autoload_register('__autoload') + + Users should also be on guard if they use a version of PHP previous + to 5.1.2 without an autoloader--HTML Purifier will define __autoload() + for you, which can collide with an autoloader that was added by *you* + later. + + +For better performance +---------------------- + + Opcode caches, which greatly speed up PHP initialization for scripts + with large amounts of code (HTML Purifier included), don't like + autoloaders. We offer an include file that includes all of HTML Purifier's + files in one go in an opcode cache friendly manner: + + // If /path/to/library isn't already in your include path, uncomment + // the below line: + // require '/path/to/library/HTMLPurifier.path.php'; + + require 'HTMLPurifier.includes.php'; + + Optional components still need to be included--you'll know if you try to + use a feature and you get a class doesn't exists error! The autoloader + can be used in conjunction with this approach to catch classes that are + missing. Simply add this afterwards: + + require 'HTMLPurifier.autoload.php'; + +Standalone version +------------------ + + HTML Purifier has a standalone distribution; you can also generate + a standalone file from the full version by running the script + maintenance/generate-standalone.php . The standalone version has the + benefit of having most of its code in one file, so parsing is much + faster and the library is easier to manage. + + If HTMLPurifier.standalone.php exists in the library directory, you + can use it like this: + + require '/path/to/HTMLPurifier.standalone.php'; + + This is equivalent to including HTMLPurifier.includes.php, except that + the contents of standalone/ will be added to your path. To override this + behavior, specify a new HTMLPURIFIER_PREFIX where standalone files can + be found (usually, this will be one directory up, the "true" library + directory in full distributions). Don't forget to set your path too! + + The autoloader can be added to the end to ensure the classes are + loaded when necessary; otherwise you can manually include them. + To use the autoloader, use this: + + require 'HTMLPurifier.autoload.php'; + +For advanced users +------------------ + + HTMLPurifier.auto.php performs a number of operations that can be done + individually. These are: + + HTMLPurifier.path.php + Puts /path/to/library in the include path. For high performance, + this should be done in php.ini. + + HTMLPurifier.autoload.php + Registers our autoload handler HTMLPurifier_Bootstrap::autoload($class). + + You can do these operations by yourself--in fact, you must modify your own + autoload handler if you are using a version of PHP earlier than PHP 5.1.2 + (See "Autoload compatibility" above). + + +--------------------------------------------------------------------------- +4. Configuration + +HTML Purifier is designed to run out-of-the-box, but occasionally HTML +Purifier needs to be told what to do. If you answer no to any of these +questions, read on; otherwise, you can skip to the next section (or, if you're +into configuring things just for the heck of it, skip to 4.3). + +* Am I using UTF-8? +* Am I using XHTML 1.0 Transitional? + +If you answered no to any of these questions, instantiate a configuration +object and read on: + + $config = HTMLPurifier_Config::createDefault(); + + +4.1. Setting a different character encoding + +You really shouldn't use any other encoding except UTF-8, especially if you +plan to support multilingual websites (read section three for more details). +However, switching to UTF-8 is not always immediately feasible, so we can +adapt. + +HTML Purifier uses iconv to support other character encodings, as such, +any encoding that iconv supports +HTML Purifier supports with this code: + + $config->set('Core.Encoding', /* put your encoding here */); + +An example usage for Latin-1 websites (the most common encoding for English +websites): + + $config->set('Core.Encoding', 'ISO-8859-1'); + +Note that HTML Purifier's support for non-Unicode encodings is crippled by the +fact that any character not supported by that encoding will be silently +dropped, EVEN if it is ampersand escaped. If you want to work around +this, you are welcome to read docs/enduser-utf8.html for a fix, +but please be cognizant of the issues the "solution" creates (for this +reason, I do not include the solution in this document). + + +4.2. Setting a different doctype + +For those of you using HTML 4.01 Transitional, you can disable +XHTML output like this: + + $config->set('HTML.Doctype', 'HTML 4.01 Transitional'); + +Other supported doctypes include: + + * HTML 4.01 Strict + * HTML 4.01 Transitional + * XHTML 1.0 Strict + * XHTML 1.0 Transitional + * XHTML 1.1 + + +4.3. Other settings + +There are more configuration directives which can be read about +here: They're a bit boring, +but they can help out for those of you who like to exert maximum control over +your code. Some of the more interesting ones are configurable at the +demo and are well worth looking into +for your own system. + +For example, you can fine tune allowed elements and attributes, convert +relative URLs to absolute ones, and even autoparagraph input text! These +are, respectively, %HTML.Allowed, %URI.MakeAbsolute and %URI.Base, and +%AutoFormat.AutoParagraph. The %Namespace.Directive naming convention +translates to: + + $config->set('Namespace.Directive', $value); + +E.g. + + $config->set('HTML.Allowed', 'p,b,a[href],i'); + $config->set('URI.Base', 'http://www.example.com'); + $config->set('URI.MakeAbsolute', true); + $config->set('AutoFormat.AutoParagraph', true); + + +--------------------------------------------------------------------------- +5. Caching + +HTML Purifier generates some cache files (generally one or two) to speed up +its execution. For maximum performance, make sure that +library/HTMLPurifier/DefinitionCache/Serializer is writeable by the webserver. + +If you are in the library/ folder of HTML Purifier, you can set the +appropriate permissions using: + + chmod -R 0755 HTMLPurifier/DefinitionCache/Serializer + +If the above command doesn't work, you may need to assign write permissions +to group: + + chmod -R 0775 HTMLPurifier/DefinitionCache/Serializer + +You can also chmod files via your FTP client; this option +is usually accessible by right clicking the corresponding directory and +then selecting "chmod" or "file permissions". + +Starting with 2.0.1, HTML Purifier will generate friendly error messages +that will tell you exactly what you have to chmod the directory to, if in doubt, +follow its advice. + +If you are unable or unwilling to give write permissions to the cache +directory, you can either disable the cache (and suffer a performance +hit): + + $config->set('Core.DefinitionCache', null); + +Or move the cache directory somewhere else (no trailing slash): + + $config->set('Cache.SerializerPath', '/home/user/absolute/path'); + + +--------------------------------------------------------------------------- +6. Using the code + +The interface is mind-numbingly simple: + + $purifier = new HTMLPurifier($config); + $clean_html = $purifier->purify( $dirty_html ); + +That's it! For more examples, check out docs/examples/ (they aren't very +different though). Also, docs/enduser-slow.html gives advice on what to +do if HTML Purifier is slowing down your application. + + +--------------------------------------------------------------------------- +7. Quick install + +First, make sure library/HTMLPurifier/DefinitionCache/Serializer is +writable by the webserver (see Section 5: Caching above for details). +If your website is in UTF-8 and XHTML Transitional, use this code: + +purify($dirty_html); +?> + +If your website is in a different encoding or doctype, use this code: + +set('Core.Encoding', 'ISO-8859-1'); // replace with your encoding + $config->set('HTML.Doctype', 'HTML 4.01 Transitional'); // replace with your doctype + $purifier = new HTMLPurifier($config); + + $clean_html = $purifier->purify($dirty_html); +?> + + vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/INSTALL.fr.utf8 b/protection/xss/htmlpurifier/INSTALL.fr.utf8 new file mode 100644 index 00000000..46631dca --- /dev/null +++ b/protection/xss/htmlpurifier/INSTALL.fr.utf8 @@ -0,0 +1,60 @@ + +Installation + Comment installer HTML Purifier + +Attention : Ce document est encodé en UTF-8, si les lettres avec des accents +ne s'affichent pas, prenez un meilleur éditeur de texte. + +L'installation de HTML Purifier est très simple, parce qu'il n'a pas besoin +de configuration. Pour les utilisateurs impatients, le code se trouve dans le +pied de page, mais je recommande de lire le document. + +1. Compatibilité + +HTML Purifier fonctionne avec PHP 5. PHP 5.0.5 est la dernière version testée. +Il ne dépend pas d'autres librairies. + +Les extensions optionnelles sont iconv (généralement déjà installée) et tidy +(répendue aussi). Si vous utilisez UTF-8 et que vous ne voulez pas l'indentation, +vous pouvez utiliser HTML Purifier sans ces extensions. + + +2. Inclure la librairie + +Quand vous devez l'utilisez, incluez le : + + require_once('/path/to/library/HTMLPurifier.auto.php'); + +Ne pas l'inclure si ce n'est pas nécessaire, car HTML Purifier est lourd. + +HTML Purifier utilise "autoload". Si vous avez défini la fonction __autoload, +vous devez ajouter cette fonction : + + spl_autoload_register('__autoload') + +Plus d'informations dans le document "INSTALL". + +3. Installation rapide + +Si votre site Web est en UTF-8 et XHTML Transitional, utilisez : + +purify($html_a_purifier); +?> + +Sinon, utilisez : + +set('Core', 'Encoding', 'ISO-8859-1'); //Remplacez par votre + encodage + $config->set('Core', 'XHTML', true); //Remplacer par false si HTML 4.01 + $purificateur = new HTMLPurifier($config); + $html_propre = $purificateur->purify($html_a_purifier); +?> + + + vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/LICENSE b/protection/xss/htmlpurifier/LICENSE new file mode 100644 index 00000000..21ee8faa --- /dev/null +++ b/protection/xss/htmlpurifier/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/NEWS b/protection/xss/htmlpurifier/NEWS new file mode 100644 index 00000000..647e4f7e --- /dev/null +++ b/protection/xss/htmlpurifier/NEWS @@ -0,0 +1,1190 @@ +NEWS ( CHANGELOG and HISTORY ) HTMLPurifier +||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + += KEY ==================== + # Breaks back-compat + ! Feature + - Bugfix + + Sub-comment + . Internal change +========================== + +4.10.0, released 2018-02-22 +# PHP 5.3 is no longer officially supported by HTML Purifier + (we did not specifically break support, but we are no longer + testing on PHP 5.3) +! Relative CSS length units are now supported +- A few PHP 7.2 compatibility fixes, thanks John Flatness + +- Improve portability with old versions of libxml which don't + support accessing the data of a node +- IDNA2008 is now used for converting domains to ASCII, fixing + some rather strange bugs with international domains +- Fix race condition resulting in E_WARNING when creating + directories with Serializer + +4.9.3, released 2017-06-02 +- Workaround PHP 7.1 infinite loop when opcode cache is enabled. + Thanks @Xiphin (#134, #135) +- Don't use autoloader when testing for DOMDocument. Hypothetically, + this could cause your install to start using DirectLex if you had + previously been monkeypatching in a custom, autoloaded implementation + of DOMDocument. Don't do that. Thanks @Izumi-kun (#130) + +4.9.2, released 2017-03-12 +- Fixes PHP 5.3 compatibility +- Fix breakage when decoding decimal entities. Thanks @rybakit (#129) + +4.9.1, released 2017-03-08 +! %URI.DefaultScheme can now be set to null, in which case + all relative paths are removed. +! New CSS properties: min-width, max-width, min-height, max-height (#94) +! Transparency (rgba) and hsl/hsla supported where color CSS is present. + Thanks @fxbt for contributing the patch. (#118) +- When idn_to_ascii is defined, we might accept malformed + hostnames. Apply validation to the result in such cases. +- Close directory when done in Serializer DefinitionCache (#100) +- Deleted some asserts to avoid linters from choking (#97) +- Rework Serializer cache behavior to avoid chmod'ing if possible (#32) +- Embedded semicolons in strings in CSS are now handled correctly! +- We accidentally dropped certain Unicode characters if there was + one or more invalid characters. This has been fixed, thanks + to mpyw +- Fix for "Don't truncate upon encountering when using DOMLex" + caused a regression with HTML 4.01 Strict parsing with libxml 2.9.1 + (and maybe later versions, but known OK with libxml 2.9.4). The + fix is to go about handling truncation a bit more cleverly so that + we can wrap with divs (sidestepping the bug) but slurping out the + rest of the text in case it ran off the end. (#78) +- Fix PREG_BACKTRACK_LIMIT_ERROR in HTMLPurifier_Filter_ExtractStyle. + Thanks @breathbath for contributing the report and fix (#120) +- Fix entity decoding algorithm to be more conservative about + decoding entities that are missing trailing semicolon. + To get old behavior, set %Core.LegacyEntityDecoder to true. + (#119) +- Workaround libxml bug when HTML tags are embedded inside + script tags. To disable workaround set %Core.AggressivelyRemoveScript + to false. (#83) +# By default, when a link has a target attribute associated + with it, we now also add rel="noopener" in order to + prevent the new window from being able to overwrite + the original frame. To disable this protection, + set %HTML.TargetNoopener to FALSE. + +4.9.0 was cut on Git but never properly released; when we did the +real release we decided to skip this version number. + +4.8.0, released 2016-07-16 +# By default, when a link has a target attribute associated + with it, we now also add rel="noreferrer" in order to + prevent the new window from being able to overwrite + the original frame. To disable this protection, + set %HTML.TargetNoreferrer to FALSE. +! Full PHP 7 compatibility, the test suite is ALL GO. +! %CSS.AllowDuplicates permits duplicate CSS properties. +! Support for 'tel' URIs. +! Partial support for 'border-radius' properties when %CSS.AllowProprietary is true. + The slash syntax, i.e., 'border-radius: 2em 1em 4em / 0.5em 3em' is not + yet supported. +! %Attr.ID.HTML5 turns on HTML5-style ID handling. +- alt truncation could result in malformed UTF-8 sequence. Don't + truncate. Thanks Brandon Farber for reporting. +- Linkify regex is smarter, based off of Gruber's regex. +- IDNA supported natively on PHP 5.3 and later. +- Non all-numeric top-level names (e.g., foo.1f, 1f) are now + allowed. +- Minor bounds error fix to squash a PHP 7 notice. +- Support non-/tmp temporary directories for data:// validation +- Give a better error message when a user attempts to allow + ul/ol without allowing li. +- On some versions of PHP, the Serializer DefinitionCache could + infinite loop when the directory exists but is not listable. (#49) +- Don't match for inside comments with + %Core.ConvertDocumentToFragment. (#67) +- SafeObject is now less case sensitive. (#57) +- AutoFormat.RemoveEmpty.Predicate now correctly renders in + web form. (#85) + +4.7.0, released 2015-08-04 +# opacity is now considered a "tricky" CSS property rather than a + proprietary one. +! %AutoFormat.RemoveEmpty.Predicate for specifying exactly when + an element should be considered "empty" (maybe preserve if it + has attributes), and modify iframe support so that the iframe + is removed if it is missing a src attribute. Thanks meeva for + reporting. +- Don't truncate upon encountering when using DOMLex. Thanks + Myrto Christina for finally convincing me to fix this. +- Update YouTube filter for new code. +- Fix parsing of rgb() values with spaces in them for 'border' + attribute. +- Don't remove foo="" attributes if foo is a boolean attribute. Thanks + valME for reporting. + +4.6.0, released 2013-11-30 +# Secure URI munge hashing algorithm has changed to hash_hmac("sha256", $url, $secret). + Please update any verification scripts you may have. +# URI parsing algorithm was made more strict, so only prefixes which + looks like schemes will actually be schemes. Thanks + Michael Gusev for fixing. +# %Core.EscapeInvalidChildren is no longer supported, and no longer does + anything. +! New directive %Core.AllowHostnameUnderscore which allows underscores + in hostnames. +- Eliminate quadratic behavior in DOMLex by using a proper queue. + Thanks Ole Laursen for noticing this. +- Rewritten MakeWellFormed/FixNesting implementation eliminates quadratic + behavior in the rest of the purificaiton pipeline. Thanks Chedburn + Networks for sponsoring this work. +- Made Linkify URL parser a bit less permissive, so that non-breaking + spaces and commas are not included as part of URL. Thanks nAS for fixing. +- Fix some bad interactions with %HTML.Allowed and injectors. Thanks + David Hirtz for reporting. +- Fix infinite loop in DirectLex. Thanks Ashar Javed (@soaj1664ashar) + for reporting. + +4.5.0, released 2013-02-17 +# Fix bug where stacked attribute transforms clobber each other; + this also means it's no longer possible to override attribute + transforms in later modules. No internal code was using this + but this may break some clients. +# We now use SHA-1 to identify cached definitions, instead of MD5. +! Support display:inline-block +! Support for more white-space CSS values. +! Permit underscores in font families +! Support for page-break-* CSS3 properties when proprietary properties + are enabled. +! New directive %Core.DisableExcludes; can be set to 'true' to turn off + SGML excludes checking. If HTML Purifier is removing too much text + and you don't care about full standards compliance, try setting this to + 'true'. +- Use prepend for SPL autoloading on PHP 5.3 and later. +- Fix bug with nofollow transform when pre-existing rel exists. +- Fix bug where background:url() always gets lower-cased + (but not background-image:url()) +- Fix bug with non lower-case color names in HTML +- Fix bug where data URI validation doesn't remove temporary files. + Thanks Javier Marín Ros for reporting. +- Don't remove certain empty tags on RemoveEmpty. + +4.4.0, released 2012-01-18 +# Removed PEARSax3 handler. +# URI.Munge now munges URIs inside the same host that go from https + to http. Reported by Neike Taika-Tessaro. +# Core.EscapeNonASCIICharacters now always transforms entities to + entities, even if target encoding is UTF-8. +# Tighten up selector validation in ExtractStyleBlocks. + Non-syntactically valid selectors are now rejected, along with + some of the more obscure ones such as attribute selectors, the + :lang pseudoselector, and anything not in CSS2.1. Furthermore, + ID and class selectors now work properly with the relevant + configuration attributes. Also, mute errors when parsing CSS + with CSS Tidy. Reported by Mario Heiderich and Norman Hippert. +! Added support for 'scope' attribute on tables. +! Added %HTML.TargetBlank, which adds target="blank" to all outgoing links. +! Properly handle sub-lists directly nested inside of lists in + a standards compliant way, by moving them into the preceding
  • +! Added %HTML.AllowedComments and %HTML.AllowedCommentsRegexp for + limited allowed comments in untrusted situations. +! Implement iframes, and allow them to be used in untrusted mode with + %HTML.SafeIframe and %URI.SafeIframeRegexp. Thanks Bradley M. Froehle + for submitting an initial version of the patch. +! The Forms module now works properly for transitional doctypes. +! Added support for internationalized domain names. You need the PEAR + Net_IDNA2 module to be in your path; if it is installed, ensure the + class can be loaded and then set %Core.EnableIDNA to true. +- Color keywords are now case insensitive. Thanks Yzmir Ramirez + for reporting. +- Explicitly initialize anonModule variable to null. +- Do not duplicate nofollow if already present. Thanks 178 + for reporting. +- Do not add nofollow if hostname matches our current host. Thanks 178 + for reporting, and Neike Taika-Tessaro for helping diagnose. +- Do not unset parser variable; this fixes intermittent serialization + problems. Thanks Neike Taika-Tessaro for reporting, bill + <10010tiger@gmail.com> for diagnosing. +- Fix iconv truncation bug, where non-UTF-8 target encodings see + output truncated after around 8000 characters. Thanks Jörg Ludwig + for reporting. +- Fix broken table content model for XHTML1.1 (and also earlier + versions, although the W3C validator doesn't catch those violations). + Thanks GlitchMr for reporting. + +4.3.0, released 2011-03-27 +# Fixed broken caching of customized raw definitions, but requires an + API change. The old API still works but will emit a warning, + see http://htmlpurifier.org/docs/enduser-customize.html#optimized + for how to upgrade your code. +# Protect against Internet Explorer innerHTML behavior by specially + treating attributes with backticks but no angled brackets, quotes or + spaces. This constitutes a slight semantic change, which can be + reverted using %Output.FixInnerHTML. Reported by Neike Taika-Tessaro + and Mario Heiderich. +# Protect against cssText/innerHTML by restricting allowed characters + used in fonts further than mandated by the specification and encoding + some extra special characters in URLs. Reported by Neike + Taika-Tessaro and Mario Heiderich. +! Added %HTML.Nofollow to add rel="nofollow" to external links. +! More types of SPL autoloaders allowed on later versions of PHP. +! Implementations for position, top, left, right, bottom, z-index + when %CSS.Trusted is on. +! Add %Cache.SerializerPermissions option for custom serializer + directory/file permissions +! Fix longstanding bug in Flash support for non-IE browsers, and + allow more wmode attributes. +! Add %CSS.AllowedFonts to restrict permissible font names. +- Switch to an iterative traversal of the DOM, which prevents us + from running out of stack space for deeply nested documents. + Thanks Maxim Krizhanovsky for contributing a patch. +- Make removal of conditional IE comments ungreedy; thanks Bernd + for reporting. +- Escape CDATA before removing Internet Explorer comments. +- Fix removal of id attributes under certain conditions by ensuring + armor attributes are preserved when recreating tags. +- Check if schema.ser was corrupted. +- Check if zend.ze1_compatibility_mode is on, and error out if it is. + This safety check is only done for HTMLPurifier.auto.php; if you + are using standalone or the specialized includes files, you're + expected to know what you're doing. +- Stop repeatedly writing the cache file after I'm done customizing a + raw definition. Reported by ajh. +- Switch to using require_once in the Bootstrap to work around bad + interaction with Zend Debugger and APC. Reported by Antonio Parraga. +- Fix URI handling when hostname is missing but scheme is present. + Reported by Neike Taika-Tessaro. +- Fix missing numeric entities on DirectLex; thanks Neike Taika-Tessaro + for reporting. +- Fix harmless notice from indexing into empty string. Thanks Matthijs + Kooijman for reporting. +- Don't autoclose no parent elements are able to support the element + that triggered the autoclose. In particular fixes strange behavior + of stray
  • tags. Thanks pkuliga@gmail.com for reporting and + Neike Taika-Tessaro for debugging assistance. + +4.2.0, released 2010-09-15 +! Added %Core.RemoveProcessingInstructions, which lets you remove + statements. +! Added %URI.DisableResources functionality; the directive originally + did nothing. Thanks David Rothstein for reporting. +! Add documentation about configuration directive types. +! Add %CSS.ForbiddenProperties configuration directive. +! Add %HTML.FlashAllowFullScreen to permit embedded Flash objects + to utilize full-screen mode. +! Add optional support for the file URI scheme, enable + by explicitly setting %URI.AllowedSchemes. +! Add %Core.NormalizeNewlines options to allow turning off newline + normalization. +- Fix improper handling of Internet Explorer conditional comments + by parser. Thanks zmonteca for reporting. +- Fix missing attributes bug when running on Mac Snow Leopard and APC. + Thanks sidepodcast for the fix. +- Warn if an element is allowed, but an attribute it requires is + not allowed. + +4.1.1, released 2010-05-31 +- Fix undefined index warnings in maintenance scripts. +- Fix bug in DirectLex for parsing elements with a single attribute + with entities. +- Rewrite CSS output logic for font-family and url(). Thanks Mario + Heiderich for reporting and Takeshi + Terada for suggesting the fix. +- Emit an error for CollectErrors if a body is extracted +- Fix bug where in background-position for center keyword handling. +- Fix infinite loop when a wrapper element is inserted in a context + where it's not allowed. Thanks Lars for reporting. +- Remove +x bit and shebang from index.php; only supported mode is to + explicitly call it with php. +- Make test script less chatty when log_errors is on. + +4.1.0, released 2010-04-26 +! Support proprietary height attribute on table element +! Support YouTube slideshows that contain /cp/ in their URL. +! Support for data: URI scheme; not enabled by default, add it using + %URI.AllowedSchemes +! Support flashvars when using %HTML.SafeObject and %HTML.SafeEmbed. +! Support for Internet Explorer compatibility with %HTML.SafeObject + using %Output.FlashCompat. +! Handle
        properly, by inserting the necessary
      1. tag. +- Always quote the insides of url(...) in CSS. + +4.0.0, released 2009-07-07 +# APIs for ConfigSchema subsystem have substantially changed. See + docs/dev-config-bcbreaks.txt for details; in essence, anything that + had both namespace and directive now have a single unified key. +# Some configuration directives were renamed, specifically: + %AutoFormatParam.PurifierLinkifyDocURL -> %AutoFormat.PurifierLinkify.DocURL + %FilterParam.ExtractStyleBlocksEscaping -> %Filter.ExtractStyleBlocks.Escaping + %FilterParam.ExtractStyleBlocksScope -> %Filter.ExtractStyleBlocks.Scope + %FilterParam.ExtractStyleBlocksTidyImpl -> %Filter.ExtractStyleBlocks.TidyImpl + As usual, the old directive names will still work, but will throw E_NOTICE + errors. +# The allowed values for class have been relaxed to allow all of CDATA for + doctypes that are not XHTML 1.1 or XHTML 2.0. For old behavior, set + %Attr.ClassUseCDATA to false. +# Instead of appending the content model to an old content model, a blank + element will replace the old content model. You can use #SUPER to get + the old content model. +! More robust support for name="" and id="" +! HTMLPurifier_Config::inherit($config) allows you to inherit one + configuration, and have changes to that configuration be propagated + to all of its children. +! Implement %HTML.Attr.Name.UseCDATA, which relaxes validation rules on + the name attribute when set. Use with care. Thanks Ian Cook for + sponsoring. +! Implement %AutoFormat.RemoveEmpty.RemoveNbsp, which removes empty + tags that contain non-breaking spaces as well other whitespace. You + can also modify which tags should have   maintained with + %AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions. +! Implement %Attr.AllowedClasses, which allows administrators to restrict + classes users can use to a specified finite set of classes, and + %Attr.ForbiddenClasses, which is the logical inverse. +! You can now maintain your own configuration schema directories by + creating a config-schema.php file or passing an extra argument. Check + docs/dev-config-schema.html for more details. +! Added HTMLPurifier_Config->serialize() method, which lets you save away + your configuration in a compact serial file, which you can unserialize + and use directly without having to go through the overhead of setup. +- Fix bug where URIDefinition would not get cleared if it's directives got + changed. +- Fix fatal error in HTMLPurifier_Encoder on certain platforms (probably NetBSD 5.0) +- Fix bug in Linkify autoformatter involving http://foo +- Make %URI.Munge not apply to links that have the same host as your host. +- Prevent stray tag from truncating output, if a second + is present. +. Created script maintenance/rename-config.php for renaming a configuration + directive while maintaining its alias. This script does not change source code. +. Implement namespace locking for definition construction, to prevent + bugs where a directive is used for definition construction but is not + used to construct the cache hash. + +3.3.0, released 2009-02-16 +! Implement CSS property 'overflow' when %CSS.AllowTricky is true. +! Implement generic property list classess +- Fix bug with testEncodingSupportsASCII() algorithm when iconv() implementation + does not do the "right thing" with characters not supported in the output + set. +- Spellcheck UTF-8: The Secret To Character Encoding +- Fix improper removal of the contents of elements with only whitespace. Thanks + Eric Wald for reporting. +- Fix broken test suite in versions of PHP without spl_autoload_register() +- Fix degenerate case with YouTube filter involving double hyphens. + Thanks Pierre Attar for reporting. +- Fix YouTube rendering problem on certain versions of Firefox. +- Fix CSSDefinition Printer problems with decorators +- Add text parameter to unit tests, forces text output +. Add verbose mode to command line test runner, use (--verbose) +. Turn on unit tests for UnitConverter +. Fix missing version number in configuration %Attr.DefaultImageAlt (added 3.2.0) +. Fix newline errors that caused spurious failures when CRLF HTML Purifier was + tested on Linux. +. Removed trailing whitespace from all text files, see + remote-trailing-whitespace.php maintenance script. +. Convert configuration to use property list backend. + +3.2.0, released 2008-10-31 +# Using %Core.CollectErrors forces line number/column tracking on, whereas + previously you could theoretically turn it off. +# HTMLPurifier_Injector->notifyEnd() is formally deprecated. Please + use handleEnd() instead. +! %Output.AttrSort for when you need your attributes in alphabetical order to + deal with a bug in FCKEditor. Requested by frank farmer. +! Enable HTML comments when %HTML.Trusted is on. Requested by Waldo Jaquith. +! Proper support for name attribute. It is now allowed and equivalent to the id + attribute in a and img tags, and is only converted to id when %HTML.TidyLevel + is heavy (for all doctypes). +! %AutoFormat.RemoveEmpty to remove some empty tags from documents. Please don't + use on hand-written HTML. +! Add error-cases for unsupported elements in MakeWellFormed. This enables + the strategy to be used, standalone, on untrusted input. +! %Core.AggressivelyFixLt is on by default. This causes more sensible + processing of left angled brackets in smileys and other whatnot. +! Test scripts now have a 'type' parameter, which lets you say 'htmlpurifier', + 'phpt', 'vtest', etc. in order to only execute those tests. This supercedes + the --only-phpt parameter, although for backwards-compatibility the flag + will still work. +! AutoParagraph auto-formatter will now preserve double-newlines upon output. + Users who are not performing inbound filtering, this may seem a little + useless, but as a bonus, the test suite and handling of edge cases is also + improved. +! Experimental implementation of forms for %HTML.Trusted +! Track column numbers when maintain line numbers is on +! Proprietary 'background' attribute on table-related elements converted into + corresponding CSS. Thanks Fusemail for sponsoring this feature! +! Add forward(), forwardUntilEndToken(), backward() and current() to Injector + supertype. +! HTMLPurifier_Injector->handleEnd() permits modification to end tokens. The + time of operation varies slightly from notifyEnd() as *all* end tokens are + processed by the injector before they are subject to the well-formedness rules. +! %Attr.DefaultImageAlt allows overriding default behavior of setting alt to + basename of image when not present. +! %AutoFormat.DisplayLinkURI neuters tags into plain text URLs. +- Fix two bugs in %URI.MakeAbsolute; one involving empty paths in base URLs, + the other involving an undefined $is_folder error. +- Throw error when %Core.Encoding is set to a spurious value. Previously, + this errored silently and returned false. +- Redirected stderr to stdout for flush error output. +- %URI.DisableExternal will now use the host in %URI.Base if %URI.Host is not + available. +- Do not re-munge URL if the output URL has the same host as the input URL. + Requested by Chris. +- Fix error in documentation regarding %Filter.ExtractStyleBlocks +- Prevent ]]> from triggering %Core.ConvertDocumentToFragment +- Fix bug with inline elements in blockquotes conflicting with strict doctype +- Detect if HTML support is disabled for DOM by checking for loadHTML() method. +- Fix bug where dots and double-dots in absolute URLs without hostname were + not collapsed by URIFilter_MakeAbsolute. +- Fix bug with anonymous modules operating on SafeEmbed or SafeObject elements + by reordering their addition. +- Will now throw exception on many error conditions during lexer creation; also + throw an exception when MaintainLineNumbers is true, but a non-tracksLineNumbers + is being used. +- Detect if domxml extension is loaded, and use DirectLEx accordingly. +- Improve handling of big numbers with floating point arithmetic in UnitConverter. + Reported by David Morton. +. Strategy_MakeWellFormed now operates in-place, saving memory and allowing + for more interesting filter-backtracking +. New HTMLPurifier_Injector->rewind() functionality, allows injectors to rewind + index to reprocess tokens. +. StringHashParser now allows for multiline sections with "empty" content; + previously the section would remain undefined. +. Added --quick option to multitest.php, which tests only the most recent + release for each series. +. Added --distro option to multitest.php, which accepts either 'normal' or + 'standalone'. This supercedes --exclude-normal and --exclude-standalone + +3.1.1, released 2008-06-19 +# %URI.Munge now, by default, does not munge resources (for example, ) + In order to enable this again, please set %URI.MungeResources to true. +! More robust imagecrash protection with height/width CSS with %CSS.MaxImgLength, + and height/width HTML with %HTML.MaxImgLength. +! %URI.MungeSecretKey for secure URI munging. Thanks Chris + for sponsoring this feature. Check out the corresponding documentation + for details. (Att Nightly testers: The API for this feature changed before + the general release. Namely, rename your directives %URI.SecureMungeSecretKey => + %URI.MungeSecretKey and and %URI.SecureMunge => %URI.Munge) +! Implemented post URI filtering. Set member variable $post to true to set + a URIFilter as such. +! Allow modules to define injectors via $info_injector. Injectors are + automatically disabled if injector's needed elements are not found. +! Support for "safe" objects added, use %HTML.SafeObject and %HTML.SafeEmbed. + Thanks Chris for sponsoring. If you've been using ad hoc code from the + forums, PLEASE use this instead. +! Added substitutions for %e, %n, %a and %p in %URI.Munge (in order, + embedded, tag name, attribute name, CSS property name). See %URI.Munge + for more details. Requested by Jochem Blok. +- Disable percent height/width attributes for img. +- AttrValidator operations are now atomic; updates to attributes are not + manifest in token until end of operations. This prevents naughty internal + code from directly modifying CurrentToken when they're not supposed to. + This semantics change was requested by frank farmer. +- Percent encoding checks enabled for URI query and fragment +- Fix stray backslashes in font-family; CSS Unicode character escapes are + now properly resolved (although *only* in font-family). Thanks Takeshi Terada + for reporting. +- Improve parseCDATA algorithm to take into account newline normalization +- Account for browser confusion between Yen character and backslash in + Shift_JIS encoding. This fix generalizes to any other encoding which is not + a strict superset of printable ASCII. Thanks Takeshi Terada for reporting. +- Fix missing configuration parameter in Generator calls. Thanks vs for the + partial patch. +- Improved adherence to Unicode by checking for non-character codepoints. + Thanks Geoffrey Sneddon for reporting. This may result in degraded + performance for extremely large inputs. +- Allow CSS property-value pair ''text-decoration: none''. Thanks Jochem Blok + for reporting. +. Added HTMLPurifier_UnitConverter and HTMLPurifier_Length for convenient + handling of CSS-style lengths. HTMLPurifier_AttrDef_CSS_Length now uses + this class. +. API of HTMLPurifier_AttrDef_CSS_Length changed from __construct($disable_negative) + to __construct($min, $max). __construct(true) is equivalent to + __construct('0'). +. Added HTMLPurifier_AttrDef_Switch class +. Rename HTMLPurifier_HTMLModule_Tidy->construct() to setup() and bubble method + up inheritance hierarchy to HTMLPurifier_HTMLModule. All HTMLModules + get this called with the configuration object. All modules now + use this rather than __construct(), although legacy code using constructors + will still work--the new format, however, lets modules access the + configuration object for HTML namespace dependant tweaks. +. AttrDef_HTML_Pixels now takes a single construction parameter, pixels. +. ConfigSchema data-structure heavily optimized; on average it uses a third + the memory it did previously. The interface has changed accordingly, + consult changes to HTMLPurifier_Config for details. +. Variable parsing types now are magic integers instead of strings +. Added benchmark for ConfigSchema +. HTMLPurifier_Generator requires $config and $context parameters. If you + don't know what they should be, use HTMLPurifier_Config::createDefault() + and new HTMLPurifier_Context(). +. Printers now properly distinguish between output configuration, and + target configuration. This is not applicable to scripts using + the Printers for HTML Purifier related tasks. +. HTML/CSS Printers must be primed with prepareGenerator($gen_config), otherwise + fatal errors will ensue. +. URIFilter->prepare can return false in order to abort loading of the filter +. Factory for AttrDef_URI implemented, URI#embedded to indicate URI that embeds + an external resource. +. %URI.Munge functionality factored out into a post-filter class. +. Added CurrentCSSProperty context variable during CSS validation + +3.1.0, released 2008-05-18 +# Unnecessary references to objects (vestiges of PHP4) removed from method + signatures. The following methods do not need references when assigning from + them and will result in E_STRICT errors if you try: + + HTMLPurifier_Config->get*Definition() [* = HTML, CSS] + + HTMLPurifier_ConfigSchema::instance() + + HTMLPurifier_DefinitionCacheFactory::instance() + + HTMLPurifier_DefinitionCacheFactory->create() + + HTMLPurifier_DoctypeRegistry->register() + + HTMLPurifier_DoctypeRegistry->get() + + HTMLPurifier_HTMLModule->addElement() + + HTMLPurifier_HTMLModule->addBlankElement() + + HTMLPurifier_LanguageFactory::instance() +# Printer_ConfigForm's get*() functions were static-ified +# %HTML.ForbiddenAttributes requires attribute declarations to be in the + form of tag@attr, NOT tag.attr (which will throw an error and won't do + anything). This is for forwards compatibility with XML; you'd do best + to migrate an %HTML.AllowedAttributes directives to this syntax too. +! Allow index to be false for config from form creation +! Added HTMLPurifier::VERSION constant +! Commas, not dashes, used for serializer IDs. This change is forwards-compatible + and allows for version numbers like "3.1.0-dev". +! %HTML.Allowed deals gracefully with whitespace anywhere, anytime! +! HTML Purifier's URI handling is a lot more robust, with much stricter + validation checks and better percent encoding handling. Thanks Gareth Heyes + for indicating security vulnerabilities from lax percent encoding. +! Bootstrap autoloader deals more robustly with classes that don't exist, + preventing class_exists($class, true) from barfing. +- InterchangeBuilder now alphabetizes its lists +- Validation error in configdoc output fixed +- Iconv and other encoding errors muted even with custom error handlers that + do not honor error_reporting +- Add protection against imagecrash attack with CSS height/width +- HTMLPurifier::instance() created for consistency, is equivalent to getInstance() +- Fixed and revamped broken ConfigForm smoketest +- Bug with bool/null fields in Printer_ConfigForm fixed +- Bug with global forbidden attributes fixed +- Improved error messages for allowed and forbidden HTML elements and attributes +- Missing (or null) in configdoc documentation restored +- If DOM throws and exception during parsing with PH5P (occurs in newer versions + of DOM), HTML Purifier punts to DirectLex +- Fatal error with unserialization of ScriptRequired +- Created directories are now chmod'ed properly +- Fixed bug with fallback languages in LanguageFactory +- Standalone testing setup properly with autoload +. Out-of-date documentation revised +. UTF-8 encoding check optimization as suggested by Diego +. HTMLPurifier_Error removed in favor of exceptions +. More copy() function removed; should use clone instead +. More extensive unit tests for HTMLDefinition +. assertPurification moved to central harness +. HTMLPurifier_Generator accepts $config and $context parameters during + instantiation, not runtime +. Double-quotes outside of attribute values are now unescaped + +3.1.0rc1, released 2008-04-22 +# Autoload support added. Internal require_once's removed in favor of an + explicit require list or autoloading. To use HTML Purifier, + you must now either use HTMLPurifier.auto.php + or HTMLPurifier.includes.php; setting the include path and including + HTMLPurifier.php is insufficient--in such cases include HTMLPurifier.autoload.php + as well to register our autoload handler (or modify your autoload function + to check HTMLPurifier_Bootstrap::getPath($class)). You can also use + HTMLPurifier.safe-includes.php for a less performance friendly but more + user-friendly library load. +# HTMLPurifier_ConfigSchema static functions are officially deprecated. Schema + information is stored in the ConfigSchema directory, and the + maintenance/generate-schema-cache.php generates the schema.ser file, which + is now instantiated. Support for userland schema changes coming soon! +# HTMLPurifier_Config will now throw E_USER_NOTICE when you use a directive + alias; to get rid of these errors just modify your configuration to use + the new directive name. +# HTMLPurifier->addFilter is deprecated; built-in filters can now be + enabled using %Filter.$filter_name or by setting your own filters using + %Filter.Custom +# Directive-level safety properties superceded in favor of module-level + safety. Internal method HTMLModule->addElement() has changed, although + the externally visible HTMLDefinition->addElement has *not* changed. +! Extra utility classes for testing and non-library operations can + be found in extras/. Specifically, these are FSTools and ConfigDoc. + You may find a use for these in your own project, but right now they + are highly experimental and volatile. +! Integration with PHPT allows for automated smoketests +! Limited support for proprietary HTML elements, namely , sponsored + by Chris. You can enable them with %HTML.Proprietary if your client + demands them. +! Support for !important CSS cascade modifier. By default, this will be stripped + from CSS, but you can enable it using %CSS.AllowImportant +! Support for display and visibility CSS properties added, set %CSS.AllowTricky + to true to use them. +! HTML Purifier now has its own Exception hierarchy under HTMLPurifier_Exception. + Developer error (not enduser error) can cause these to be triggered. +! Experimental kses() wrapper introduced with HTMLPurifier.kses.php +! Finally %CSS.AllowedProperties for tweaking allowed CSS properties without + mucking around with HTMLPurifier_CSSDefinition +! ConfigDoc output has been enhanced with version and deprecation info. +! %HTML.ForbiddenAttributes and %HTML.ForbiddenElements implemented. +- Autoclose now operates iteratively, i.e.
        now has + both span tags closed. +- Various HTMLPurifier_Config convenience functions now accept another parameter + $schema which defines what HTMLPurifier_ConfigSchema to use besides the + global default. +- Fix bug with trusted script handling in libxml versions later than 2.6.28. +- Fix bug in ExtractStyleBlocks with comments in style tags +- Fix bug in comment parsing for DirectLex +- Flush output now displayed when in command line mode for unit tester +- Fix bug with rgb(0, 1, 2) color syntax with spaces inside shorthand syntax +- HTMLPurifier_HTMLDefinition->addAttribute can now be called multiple times + on the same element without emitting errors. +- Fixed fatal error in PH5P lexer with invalid tag names +. Plugins now get their own changelogs according to project conventions. +. Convert tokens to use instanceof, reducing memory footprint and + improving comparison speed. +. Dry runs now supported in SimpleTest; testing facilities improved +. Bootstrap class added for handling autoloading functionality +. Implemented recursive glob at FSTools->globr +. ConfigSchema now has instance methods for all corresponding define* + static methods. +. A couple of new historical maintenance scripts were added. +. HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php split into two files +. tests/index.php can now be run from any directory. +. HTMLPurifier_Token subclasses split into seperate files +. HTMLPURIFIER_PREFIX now is defined in Bootstrap.php, NOT HTMLPurifier.php +. HTMLPURIFIER_PREFIX can now be defined outside of HTML Purifier +. New --php=php flag added, allows PHP executable to be specified (command + line only!) +. htmlpurifier_add_test() preferred method to translate test files in to + classes, because it handles PHPT files too. +. Debugger class is deprecated and will be removed soon. +. Command line argument parsing for testing scripts revamped, now --opt value + format is supported. +. Smoketests now cleanup after magic quotes +. Generator now can output comments (however, comments are still stripped + from HTML Purifier output) +. HTMLPurifier_ConfigSchema->validate() deprecated in favor of + HTMLPurifier_VarParser->parse() +. Integers auto-cast into float type by VarParser. +. HTMLPURIFIER_STRICT removed; no validation is performed on runtime, only + during cache generation +. Reordered script calls in maintenance/flush.php +. Command line scripts now honor exit codes +. When --flush fails in unit testers, abort tests and print message +. Improved documentation in docs/dev-flush.html about the maintenance scripts +. copy() methods removed in favor of clone keyword + +3.0.0, released 2008-01-06 +# HTML Purifier is PHP 5 only! The 2.1.x branch will be maintained + until PHP 4 is completely deprecated, but no new features will be added + to it. + + Visibility declarations added + + Constructor methods renamed to __construct() + + PHP4 reference cruft removed (in progress) +! CSS properties are now case-insensitive +! DefinitionCacheFactory now can register new implementations +! New HTMLPurifier_Filter_ExtractStyleBlocks for extracting + // we must not grab foo in a font-family prop). + if ($config->get('Filter.ExtractStyleBlocks.Escaping')) { + $css = str_replace( + array('<', '>', '&'), + array('\3C ', '\3E ', '\26 '), + $css + ); + } + return $css; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php new file mode 100644 index 00000000..b90ddf75 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php @@ -0,0 +1,65 @@ +]+>.+?' . + '(?:http:)?//www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?#s'; + $pre_replace = '\1'; + return preg_replace($pre_regex, $pre_replace, $html); + } + + /** + * @param string $html + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return string + */ + public function postFilter($html, $config, $context) + { + $post_regex = '#((?:v|cp)/[A-Za-z0-9\-_=]+)#'; + return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html); + } + + /** + * @param $url + * @return string + */ + protected function armorUrl($url) + { + return str_replace('--', '--', $url); + } + + /** + * @param array $matches + * @return string + */ + protected function postFilterCallback($matches) + { + $url = $this->armorUrl($matches[1]); + return '' . + '' . + '' . + ''; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php new file mode 100644 index 00000000..191a78d1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php @@ -0,0 +1,44 @@ + array('dir' => false) + ); + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) + { + $bdo = $this->addElement( + 'bdo', + 'Inline', + 'Inline', + array('Core', 'Lang'), + array( + 'dir' => 'Enum#ltr,rtl', // required + // The Abstract Module specification has the attribute + // inclusions wrong for bdo: bdo allows Lang + ) + ); + $bdo->attr_transform_post[] = new HTMLPurifier_AttrTransform_BdoDir(); + + $this->attr_collections['I18N']['dir'] = 'Enum#ltr,rtl'; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php new file mode 100644 index 00000000..e2fe53fc --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php @@ -0,0 +1,31 @@ + array( + 0 => array('Style'), + // 'xml:space' => false, + 'class' => 'Class', + 'id' => 'ID', + 'title' => 'CDATA', + ), + 'Lang' => array(), + 'I18N' => array( + 0 => array('Lang'), // proprietary, for xml:lang/lang + ), + 'Common' => array( + 0 => array('Core', 'I18N') + ) + ); +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php new file mode 100644 index 00000000..b8288368 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php @@ -0,0 +1,55 @@ + 'URI', + // 'datetime' => 'Datetime', // not implemented + ); + $this->addElement('del', 'Inline', $contents, 'Common', $attr); + $this->addElement('ins', 'Inline', $contents, 'Common', $attr); + } + + // HTML 4.01 specifies that ins/del must not contain block + // elements when used in an inline context, chameleon is + // a complicated workaround to acheive this effect + + // Inline context ! Block context (exclamation mark is + // separator, see getChildDef for parsing) + + /** + * @type bool + */ + public $defines_child_def = true; + + /** + * @param HTMLPurifier_ElementDef $def + * @return HTMLPurifier_ChildDef_Chameleon + */ + public function getChildDef($def) + { + if ($def->content_model_type != 'chameleon') { + return false; + } + $value = explode('!', $def->content_model); + return new HTMLPurifier_ChildDef_Chameleon($value[0], $value[1]); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php new file mode 100644 index 00000000..13ce6ad5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php @@ -0,0 +1,190 @@ + 'Form', + 'Inline' => 'Formctrl', + ); + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) + { + $form = $this->addElement( + 'form', + 'Form', + 'Required: Heading | List | Block | fieldset', + 'Common', + array( + 'accept' => 'ContentTypes', + 'accept-charset' => 'Charsets', + 'action*' => 'URI', + 'method' => 'Enum#get,post', + // really ContentType, but these two are the only ones used today + 'enctype' => 'Enum#application/x-www-form-urlencoded,multipart/form-data', + ) + ); + $form->excludes = array('form' => true); + + $input = $this->addElement( + 'input', + 'Formctrl', + 'Empty', + 'Common', + array( + 'accept' => 'ContentTypes', + 'accesskey' => 'Character', + 'alt' => 'Text', + 'checked' => 'Bool#checked', + 'disabled' => 'Bool#disabled', + 'maxlength' => 'Number', + 'name' => 'CDATA', + 'readonly' => 'Bool#readonly', + 'size' => 'Number', + 'src' => 'URI#embedded', + 'tabindex' => 'Number', + 'type' => 'Enum#text,password,checkbox,button,radio,submit,reset,file,hidden,image', + 'value' => 'CDATA', + ) + ); + $input->attr_transform_post[] = new HTMLPurifier_AttrTransform_Input(); + + $this->addElement( + 'select', + 'Formctrl', + 'Required: optgroup | option', + 'Common', + array( + 'disabled' => 'Bool#disabled', + 'multiple' => 'Bool#multiple', + 'name' => 'CDATA', + 'size' => 'Number', + 'tabindex' => 'Number', + ) + ); + + $this->addElement( + 'option', + false, + 'Optional: #PCDATA', + 'Common', + array( + 'disabled' => 'Bool#disabled', + 'label' => 'Text', + 'selected' => 'Bool#selected', + 'value' => 'CDATA', + ) + ); + // It's illegal for there to be more than one selected, but not + // be multiple. Also, no selected means undefined behavior. This might + // be difficult to implement; perhaps an injector, or a context variable. + + $textarea = $this->addElement( + 'textarea', + 'Formctrl', + 'Optional: #PCDATA', + 'Common', + array( + 'accesskey' => 'Character', + 'cols*' => 'Number', + 'disabled' => 'Bool#disabled', + 'name' => 'CDATA', + 'readonly' => 'Bool#readonly', + 'rows*' => 'Number', + 'tabindex' => 'Number', + ) + ); + $textarea->attr_transform_pre[] = new HTMLPurifier_AttrTransform_Textarea(); + + $button = $this->addElement( + 'button', + 'Formctrl', + 'Optional: #PCDATA | Heading | List | Block | Inline', + 'Common', + array( + 'accesskey' => 'Character', + 'disabled' => 'Bool#disabled', + 'name' => 'CDATA', + 'tabindex' => 'Number', + 'type' => 'Enum#button,submit,reset', + 'value' => 'CDATA', + ) + ); + + // For exclusions, ideally we'd specify content sets, not literal elements + $button->excludes = $this->makeLookup( + 'form', + 'fieldset', // Form + 'input', + 'select', + 'textarea', + 'label', + 'button', // Formctrl + 'a', // as per HTML 4.01 spec, this is omitted by modularization + 'isindex', + 'iframe' // legacy items + ); + + // Extra exclusion: img usemap="" is not permitted within this element. + // We'll omit this for now, since we don't have any good way of + // indicating it yet. + + // This is HIGHLY user-unfriendly; we need a custom child-def for this + $this->addElement('fieldset', 'Form', 'Custom: (#WS?,legend,(Flow|#PCDATA)*)', 'Common'); + + $label = $this->addElement( + 'label', + 'Formctrl', + 'Optional: #PCDATA | Inline', + 'Common', + array( + 'accesskey' => 'Character', + // 'for' => 'IDREF', // IDREF not implemented, cannot allow + ) + ); + $label->excludes = array('label' => true); + + $this->addElement( + 'legend', + false, + 'Optional: #PCDATA | Inline', + 'Common', + array( + 'accesskey' => 'Character', + ) + ); + + $this->addElement( + 'optgroup', + false, + 'Required: option', + 'Common', + array( + 'disabled' => 'Bool#disabled', + 'label*' => 'Text', + ) + ); + // Don't forget an injector for . This one's a little complex + // because it maps to multiple elements. + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php new file mode 100644 index 00000000..968c07e9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php @@ -0,0 +1,40 @@ +addElement( + 'a', + 'Inline', + 'Inline', + 'Common', + array( + // 'accesskey' => 'Character', + // 'charset' => 'Charset', + 'href' => 'URI', + // 'hreflang' => 'LanguageCode', + 'rel' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rel'), + 'rev' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rev'), + // 'tabindex' => 'Number', + // 'type' => 'ContentType', + ) + ); + $a->formatting = true; + $a->excludes = array('a' => true); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php new file mode 100644 index 00000000..2c9bdc58 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php @@ -0,0 +1,51 @@ +get('HTML.SafeIframe')) { + $this->safe = true; + } + $this->addElement( + 'iframe', + 'Inline', + 'Flow', + 'Common', + array( + 'src' => 'URI#embedded', + 'width' => 'Length', + 'height' => 'Length', + 'name' => 'ID', + 'scrolling' => 'Enum#yes,no,auto', + 'frameborder' => 'Enum#0,1', + 'longdesc' => 'URI', + 'marginheight' => 'Pixels', + 'marginwidth' => 'Pixels', + ) + ); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php new file mode 100644 index 00000000..0ed7411e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php @@ -0,0 +1,49 @@ +get('HTML.MaxImgLength'); + $img = $this->addElement( + 'img', + 'Inline', + 'Empty', + 'Common', + array( + 'alt*' => 'Text', + // According to the spec, it's Length, but percents can + // be abused, so we allow only Pixels. + 'height' => 'Pixels#' . $max, + 'width' => 'Pixels#' . $max, + 'longdesc' => 'URI', + 'src*' => new HTMLPurifier_AttrDef_URI(true), // embedded + ) + ); + if ($max === null || $config->get('HTML.Trusted')) { + $img->attr['height'] = + $img->attr['width'] = 'Length'; + } + + // kind of strange, but splitting things up would be inefficient + $img->attr_transform_pre[] = + $img->attr_transform_post[] = + new HTMLPurifier_AttrTransform_ImgRequired(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php new file mode 100644 index 00000000..9ca1cb37 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php @@ -0,0 +1,186 @@ +addElement( + 'basefont', + 'Inline', + 'Empty', + null, + array( + 'color' => 'Color', + 'face' => 'Text', // extremely broad, we should + 'size' => 'Text', // tighten it + 'id' => 'ID' + ) + ); + $this->addElement('center', 'Block', 'Flow', 'Common'); + $this->addElement( + 'dir', + 'Block', + 'Required: li', + 'Common', + array( + 'compact' => 'Bool#compact' + ) + ); + $this->addElement( + 'font', + 'Inline', + 'Inline', + array('Core', 'I18N'), + array( + 'color' => 'Color', + 'face' => 'Text', // extremely broad, we should + 'size' => 'Text', // tighten it + ) + ); + $this->addElement( + 'menu', + 'Block', + 'Required: li', + 'Common', + array( + 'compact' => 'Bool#compact' + ) + ); + + $s = $this->addElement('s', 'Inline', 'Inline', 'Common'); + $s->formatting = true; + + $strike = $this->addElement('strike', 'Inline', 'Inline', 'Common'); + $strike->formatting = true; + + $u = $this->addElement('u', 'Inline', 'Inline', 'Common'); + $u->formatting = true; + + // setup modifications to old elements + + $align = 'Enum#left,right,center,justify'; + + $address = $this->addBlankElement('address'); + $address->content_model = 'Inline | #PCDATA | p'; + $address->content_model_type = 'optional'; + $address->child = false; + + $blockquote = $this->addBlankElement('blockquote'); + $blockquote->content_model = 'Flow | #PCDATA'; + $blockquote->content_model_type = 'optional'; + $blockquote->child = false; + + $br = $this->addBlankElement('br'); + $br->attr['clear'] = 'Enum#left,all,right,none'; + + $caption = $this->addBlankElement('caption'); + $caption->attr['align'] = 'Enum#top,bottom,left,right'; + + $div = $this->addBlankElement('div'); + $div->attr['align'] = $align; + + $dl = $this->addBlankElement('dl'); + $dl->attr['compact'] = 'Bool#compact'; + + for ($i = 1; $i <= 6; $i++) { + $h = $this->addBlankElement("h$i"); + $h->attr['align'] = $align; + } + + $hr = $this->addBlankElement('hr'); + $hr->attr['align'] = $align; + $hr->attr['noshade'] = 'Bool#noshade'; + $hr->attr['size'] = 'Pixels'; + $hr->attr['width'] = 'Length'; + + $img = $this->addBlankElement('img'); + $img->attr['align'] = 'IAlign'; + $img->attr['border'] = 'Pixels'; + $img->attr['hspace'] = 'Pixels'; + $img->attr['vspace'] = 'Pixels'; + + // figure out this integer business + + $li = $this->addBlankElement('li'); + $li->attr['value'] = new HTMLPurifier_AttrDef_Integer(); + $li->attr['type'] = 'Enum#s:1,i,I,a,A,disc,square,circle'; + + $ol = $this->addBlankElement('ol'); + $ol->attr['compact'] = 'Bool#compact'; + $ol->attr['start'] = new HTMLPurifier_AttrDef_Integer(); + $ol->attr['type'] = 'Enum#s:1,i,I,a,A'; + + $p = $this->addBlankElement('p'); + $p->attr['align'] = $align; + + $pre = $this->addBlankElement('pre'); + $pre->attr['width'] = 'Number'; + + // script omitted + + $table = $this->addBlankElement('table'); + $table->attr['align'] = 'Enum#left,center,right'; + $table->attr['bgcolor'] = 'Color'; + + $tr = $this->addBlankElement('tr'); + $tr->attr['bgcolor'] = 'Color'; + + $th = $this->addBlankElement('th'); + $th->attr['bgcolor'] = 'Color'; + $th->attr['height'] = 'Length'; + $th->attr['nowrap'] = 'Bool#nowrap'; + $th->attr['width'] = 'Length'; + + $td = $this->addBlankElement('td'); + $td->attr['bgcolor'] = 'Color'; + $td->attr['height'] = 'Length'; + $td->attr['nowrap'] = 'Bool#nowrap'; + $td->attr['width'] = 'Length'; + + $ul = $this->addBlankElement('ul'); + $ul->attr['compact'] = 'Bool#compact'; + $ul->attr['type'] = 'Enum#square,disc,circle'; + + // "safe" modifications to "unsafe" elements + // WARNING: If you want to add support for an unsafe, legacy + // attribute, make a new TrustedLegacy module with the trusted + // bit set appropriately + + $form = $this->addBlankElement('form'); + $form->content_model = 'Flow | #PCDATA'; + $form->content_model_type = 'optional'; + $form->attr['target'] = 'FrameTarget'; + + $input = $this->addBlankElement('input'); + $input->attr['align'] = 'IAlign'; + + $legend = $this->addBlankElement('legend'); + $legend->attr['align'] = 'LAlign'; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php new file mode 100644 index 00000000..605e37c9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php @@ -0,0 +1,51 @@ + 'List'); + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) + { + $ol = $this->addElement('ol', 'List', new HTMLPurifier_ChildDef_List(), 'Common'); + $ul = $this->addElement('ul', 'List', new HTMLPurifier_ChildDef_List(), 'Common'); + // XXX The wrap attribute is handled by MakeWellFormed. This is all + // quite unsatisfactory, because we generated this + // *specifically* for lists, and now a big chunk of the handling + // is done properly by the List ChildDef. So actually, we just + // want enough information to make autoclosing work properly, + // and then hand off the tricky stuff to the ChildDef. + $ol->wrap = 'li'; + $ul->wrap = 'li'; + $this->addElement('dl', 'List', 'Required: dt | dd', 'Common'); + + $this->addElement('li', false, 'Flow', 'Common'); + + $this->addElement('dd', false, 'Flow', 'Common'); + $this->addElement('dt', false, 'Inline', 'Common'); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php new file mode 100644 index 00000000..315e22a8 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php @@ -0,0 +1,26 @@ +addBlankElement($name); + $element->attr['name'] = 'CDATA'; + if (!$config->get('HTML.Attr.Name.UseCDATA')) { + $element->attr_transform_post[] = new HTMLPurifier_AttrTransform_NameSync(); + } + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php new file mode 100644 index 00000000..c145e8e9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php @@ -0,0 +1,25 @@ +addBlankElement('a'); + $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_Nofollow(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php new file mode 100644 index 00000000..7d66e114 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php @@ -0,0 +1,20 @@ + array( + 'lang' => 'LanguageCode', + ) + ); +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php new file mode 100644 index 00000000..d388b24c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php @@ -0,0 +1,62 @@ + to cater to legacy browsers: this + * module does not allow this sort of behavior + */ +class HTMLPurifier_HTMLModule_Object extends HTMLPurifier_HTMLModule +{ + /** + * @type string + */ + public $name = 'Object'; + + /** + * @type bool + */ + public $safe = false; + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) + { + $this->addElement( + 'object', + 'Inline', + 'Optional: #PCDATA | Flow | param', + 'Common', + array( + 'archive' => 'URI', + 'classid' => 'URI', + 'codebase' => 'URI', + 'codetype' => 'Text', + 'data' => 'URI', + 'declare' => 'Bool#declare', + 'height' => 'Length', + 'name' => 'CDATA', + 'standby' => 'Text', + 'tabindex' => 'Number', + 'type' => 'ContentType', + 'width' => 'Length' + ) + ); + + $this->addElement( + 'param', + false, + 'Empty', + null, + array( + 'id' => 'ID', + 'name*' => 'Text', + 'type' => 'Text', + 'value' => 'Text', + 'valuetype' => 'Enum#data,ref,object' + ) + ); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php new file mode 100644 index 00000000..831db4cf --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php @@ -0,0 +1,42 @@ +addElement('hr', 'Block', 'Empty', 'Common'); + $this->addElement('sub', 'Inline', 'Inline', 'Common'); + $this->addElement('sup', 'Inline', 'Inline', 'Common'); + $b = $this->addElement('b', 'Inline', 'Inline', 'Common'); + $b->formatting = true; + $big = $this->addElement('big', 'Inline', 'Inline', 'Common'); + $big->formatting = true; + $i = $this->addElement('i', 'Inline', 'Inline', 'Common'); + $i->formatting = true; + $small = $this->addElement('small', 'Inline', 'Inline', 'Common'); + $small->formatting = true; + $tt = $this->addElement('tt', 'Inline', 'Inline', 'Common'); + $tt->formatting = true; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php new file mode 100644 index 00000000..4593fc40 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php @@ -0,0 +1,40 @@ +addElement( + 'marquee', + 'Inline', + 'Flow', + 'Common', + array( + 'direction' => 'Enum#left,right,up,down', + 'behavior' => 'Enum#alternate', + 'width' => 'Length', + 'height' => 'Length', + 'scrolldelay' => 'Number', + 'scrollamount' => 'Number', + 'loop' => 'Number', + 'bgcolor' => 'Color', + 'hspace' => 'Pixels', + 'vspace' => 'Pixels', + ) + ); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php new file mode 100644 index 00000000..9a261729 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php @@ -0,0 +1,36 @@ +addElement( + 'ruby', + 'Inline', + 'Custom: ((rb, (rt | (rp, rt, rp))) | (rbc, rtc, rtc?))', + 'Common' + ); + $this->addElement('rbc', false, 'Required: rb', 'Common'); + $this->addElement('rtc', false, 'Required: rt', 'Common'); + $rb = $this->addElement('rb', false, 'Inline', 'Common'); + $rb->excludes = array('ruby' => true); + $rt = $this->addElement('rt', false, 'Inline', 'Common', array('rbspan' => 'Number')); + $rt->excludes = array('ruby' => true); + $this->addElement('rp', false, 'Optional: #PCDATA', 'Common'); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php new file mode 100644 index 00000000..11572887 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php @@ -0,0 +1,40 @@ +get('HTML.MaxImgLength'); + $embed = $this->addElement( + 'embed', + 'Inline', + 'Empty', + 'Common', + array( + 'src*' => 'URI#embedded', + 'type' => 'Enum#application/x-shockwave-flash', + 'width' => 'Pixels#' . $max, + 'height' => 'Pixels#' . $max, + 'allowscriptaccess' => 'Enum#never', + 'allownetworking' => 'Enum#internal', + 'flashvars' => 'Text', + 'wmode' => 'Enum#window,transparent,opaque', + 'name' => 'ID', + ) + ); + $embed->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeEmbed(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php new file mode 100644 index 00000000..a061cec1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php @@ -0,0 +1,62 @@ +get('HTML.MaxImgLength'); + $object = $this->addElement( + 'object', + 'Inline', + 'Optional: param | Flow | #PCDATA', + 'Common', + array( + // While technically not required by the spec, we're forcing + // it to this value. + 'type' => 'Enum#application/x-shockwave-flash', + 'width' => 'Pixels#' . $max, + 'height' => 'Pixels#' . $max, + 'data' => 'URI#embedded', + 'codebase' => new HTMLPurifier_AttrDef_Enum( + array( + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0' + ) + ), + ) + ); + $object->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeObject(); + + $param = $this->addElement( + 'param', + false, + 'Empty', + false, + array( + 'id' => 'ID', + 'name*' => 'Text', + 'value' => 'Text' + ) + ); + $param->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeParam(); + $this->info_injector[] = 'SafeObject'; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php new file mode 100644 index 00000000..6e9113cb --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php @@ -0,0 +1,40 @@ +get('HTML.SafeScripting'); + $script = $this->addElement( + 'script', + 'Inline', + 'Empty', + null, + array( + // While technically not required by the spec, we're forcing + // it to this value. + 'type' => 'Enum#text/javascript', + 'src*' => new HTMLPurifier_AttrDef_Enum(array_keys($allowed)) + ) + ); + $script->attr_transform_pre[] = + $script->attr_transform_post[] = new HTMLPurifier_AttrTransform_ScriptRequired(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php new file mode 100644 index 00000000..18785372 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php @@ -0,0 +1,73 @@ + 'script | noscript', 'Inline' => 'script | noscript'); + + /** + * @type bool + */ + public $safe = false; + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) + { + // TODO: create custom child-definition for noscript that + // auto-wraps stray #PCDATA in a similar manner to + // blockquote's custom definition (we would use it but + // blockquote's contents are optional while noscript's contents + // are required) + + // TODO: convert this to new syntax, main problem is getting + // both content sets working + + // In theory, this could be safe, but I don't see any reason to + // allow it. + $this->info['noscript'] = new HTMLPurifier_ElementDef(); + $this->info['noscript']->attr = array(0 => array('Common')); + $this->info['noscript']->content_model = 'Heading | List | Block'; + $this->info['noscript']->content_model_type = 'required'; + + $this->info['script'] = new HTMLPurifier_ElementDef(); + $this->info['script']->attr = array( + 'defer' => new HTMLPurifier_AttrDef_Enum(array('defer')), + 'src' => new HTMLPurifier_AttrDef_URI(true), + 'type' => new HTMLPurifier_AttrDef_Enum(array('text/javascript')) + ); + $this->info['script']->content_model = '#PCDATA'; + $this->info['script']->content_model_type = 'optional'; + $this->info['script']->attr_transform_pre[] = + $this->info['script']->attr_transform_post[] = + new HTMLPurifier_AttrTransform_ScriptRequired(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php new file mode 100644 index 00000000..f192780a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php @@ -0,0 +1,33 @@ + array('style' => false), // see constructor + 'Core' => array(0 => array('Style')) + ); + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) + { + $this->attr_collections['Style']['style'] = new HTMLPurifier_AttrDef_CSS(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php new file mode 100644 index 00000000..f993e3ca --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php @@ -0,0 +1,75 @@ +addElement('caption', false, 'Inline', 'Common'); + + $this->addElement( + 'table', + 'Block', + new HTMLPurifier_ChildDef_Table(), + 'Common', + array( + 'border' => 'Pixels', + 'cellpadding' => 'Length', + 'cellspacing' => 'Length', + 'frame' => 'Enum#void,above,below,hsides,lhs,rhs,vsides,box,border', + 'rules' => 'Enum#none,groups,rows,cols,all', + 'summary' => 'Text', + 'width' => 'Length' + ) + ); + + // common attributes + $cell_align = array( + 'align' => 'Enum#left,center,right,justify,char', + 'charoff' => 'Length', + 'valign' => 'Enum#top,middle,bottom,baseline', + ); + + $cell_t = array_merge( + array( + 'abbr' => 'Text', + 'colspan' => 'Number', + 'rowspan' => 'Number', + // Apparently, as of HTML5 this attribute only applies + // to 'th' elements. + 'scope' => 'Enum#row,col,rowgroup,colgroup', + ), + $cell_align + ); + $this->addElement('td', false, 'Flow', 'Common', $cell_t); + $this->addElement('th', false, 'Flow', 'Common', $cell_t); + + $this->addElement('tr', false, 'Required: td | th', 'Common', $cell_align); + + $cell_col = array_merge( + array( + 'span' => 'Number', + 'width' => 'MultiLength', + ), + $cell_align + ); + $this->addElement('col', false, 'Empty', 'Common', $cell_col); + $this->addElement('colgroup', false, 'Optional: col', 'Common', $cell_col); + + $this->addElement('tbody', false, 'Required: tr', 'Common', $cell_align); + $this->addElement('thead', false, 'Required: tr', 'Common', $cell_align); + $this->addElement('tfoot', false, 'Required: tr', 'Common', $cell_align); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php new file mode 100644 index 00000000..f3af0486 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php @@ -0,0 +1,28 @@ +addBlankElement($name); + $e->attr = array( + 'target' => new HTMLPurifier_AttrDef_HTML_FrameTarget() + ); + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php new file mode 100644 index 00000000..757cddcd --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php @@ -0,0 +1,24 @@ +addBlankElement('a'); + $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetBlank(); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoopener.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoopener.php new file mode 100644 index 00000000..bc8e88d6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoopener.php @@ -0,0 +1,21 @@ +addBlankElement('a'); + $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetNoopener(); + } +} diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php new file mode 100644 index 00000000..9fa558c2 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php @@ -0,0 +1,21 @@ +addBlankElement('a'); + $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetNoreferrer(); + } +} diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php new file mode 100644 index 00000000..11fdd8bd --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php @@ -0,0 +1,87 @@ + 'Heading | Block | Inline' + ); + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) + { + // Inline Phrasal ------------------------------------------------- + $this->addElement('abbr', 'Inline', 'Inline', 'Common'); + $this->addElement('acronym', 'Inline', 'Inline', 'Common'); + $this->addElement('cite', 'Inline', 'Inline', 'Common'); + $this->addElement('dfn', 'Inline', 'Inline', 'Common'); + $this->addElement('kbd', 'Inline', 'Inline', 'Common'); + $this->addElement('q', 'Inline', 'Inline', 'Common', array('cite' => 'URI')); + $this->addElement('samp', 'Inline', 'Inline', 'Common'); + $this->addElement('var', 'Inline', 'Inline', 'Common'); + + $em = $this->addElement('em', 'Inline', 'Inline', 'Common'); + $em->formatting = true; + + $strong = $this->addElement('strong', 'Inline', 'Inline', 'Common'); + $strong->formatting = true; + + $code = $this->addElement('code', 'Inline', 'Inline', 'Common'); + $code->formatting = true; + + // Inline Structural ---------------------------------------------- + $this->addElement('span', 'Inline', 'Inline', 'Common'); + $this->addElement('br', 'Inline', 'Empty', 'Core'); + + // Block Phrasal -------------------------------------------------- + $this->addElement('address', 'Block', 'Inline', 'Common'); + $this->addElement('blockquote', 'Block', 'Optional: Heading | Block | List', 'Common', array('cite' => 'URI')); + $pre = $this->addElement('pre', 'Block', 'Inline', 'Common'); + $pre->excludes = $this->makeLookup( + 'img', + 'big', + 'small', + 'object', + 'applet', + 'font', + 'basefont' + ); + $this->addElement('h1', 'Heading', 'Inline', 'Common'); + $this->addElement('h2', 'Heading', 'Inline', 'Common'); + $this->addElement('h3', 'Heading', 'Inline', 'Common'); + $this->addElement('h4', 'Heading', 'Inline', 'Common'); + $this->addElement('h5', 'Heading', 'Inline', 'Common'); + $this->addElement('h6', 'Heading', 'Inline', 'Common'); + + // Block Structural ----------------------------------------------- + $p = $this->addElement('p', 'Block', 'Inline', 'Common'); + $p->autoclose = array_flip( + array("address", "blockquote", "center", "dir", "div", "dl", "fieldset", "ol", "p", "ul") + ); + + $this->addElement('div', 'Block', 'Flow', 'Common'); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php new file mode 100644 index 00000000..f482a374 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php @@ -0,0 +1,230 @@ + 'none', 'light', 'medium', 'heavy'); + + /** + * Default level to place all fixes in. + * Disabled by default. + * @type string + */ + public $defaultLevel = null; + + /** + * Lists of fixes used by getFixesForLevel(). + * Format is: + * HTMLModule_Tidy->fixesForLevel[$level] = array('fix-1', 'fix-2'); + * @type array + */ + public $fixesForLevel = array( + 'light' => array(), + 'medium' => array(), + 'heavy' => array() + ); + + /** + * Lazy load constructs the module by determining the necessary + * fixes to create and then delegating to the populate() function. + * @param HTMLPurifier_Config $config + * @todo Wildcard matching and error reporting when an added or + * subtracted fix has no effect. + */ + public function setup($config) + { + // create fixes, initialize fixesForLevel + $fixes = $this->makeFixes(); + $this->makeFixesForLevel($fixes); + + // figure out which fixes to use + $level = $config->get('HTML.TidyLevel'); + $fixes_lookup = $this->getFixesForLevel($level); + + // get custom fix declarations: these need namespace processing + $add_fixes = $config->get('HTML.TidyAdd'); + $remove_fixes = $config->get('HTML.TidyRemove'); + + foreach ($fixes as $name => $fix) { + // needs to be refactored a little to implement globbing + if (isset($remove_fixes[$name]) || + (!isset($add_fixes[$name]) && !isset($fixes_lookup[$name]))) { + unset($fixes[$name]); + } + } + + // populate this module with necessary fixes + $this->populate($fixes); + } + + /** + * Retrieves all fixes per a level, returning fixes for that specific + * level as well as all levels below it. + * @param string $level level identifier, see $levels for valid values + * @return array Lookup up table of fixes + */ + public function getFixesForLevel($level) + { + if ($level == $this->levels[0]) { + return array(); + } + $activated_levels = array(); + for ($i = 1, $c = count($this->levels); $i < $c; $i++) { + $activated_levels[] = $this->levels[$i]; + if ($this->levels[$i] == $level) { + break; + } + } + if ($i == $c) { + trigger_error( + 'Tidy level ' . htmlspecialchars($level) . ' not recognized', + E_USER_WARNING + ); + return array(); + } + $ret = array(); + foreach ($activated_levels as $level) { + foreach ($this->fixesForLevel[$level] as $fix) { + $ret[$fix] = true; + } + } + return $ret; + } + + /** + * Dynamically populates the $fixesForLevel member variable using + * the fixes array. It may be custom overloaded, used in conjunction + * with $defaultLevel, or not used at all. + * @param array $fixes + */ + public function makeFixesForLevel($fixes) + { + if (!isset($this->defaultLevel)) { + return; + } + if (!isset($this->fixesForLevel[$this->defaultLevel])) { + trigger_error( + 'Default level ' . $this->defaultLevel . ' does not exist', + E_USER_ERROR + ); + return; + } + $this->fixesForLevel[$this->defaultLevel] = array_keys($fixes); + } + + /** + * Populates the module with transforms and other special-case code + * based on a list of fixes passed to it + * @param array $fixes Lookup table of fixes to activate + */ + public function populate($fixes) + { + foreach ($fixes as $name => $fix) { + // determine what the fix is for + list($type, $params) = $this->getFixType($name); + switch ($type) { + case 'attr_transform_pre': + case 'attr_transform_post': + $attr = $params['attr']; + if (isset($params['element'])) { + $element = $params['element']; + if (empty($this->info[$element])) { + $e = $this->addBlankElement($element); + } else { + $e = $this->info[$element]; + } + } else { + $type = "info_$type"; + $e = $this; + } + // PHP does some weird parsing when I do + // $e->$type[$attr], so I have to assign a ref. + $f =& $e->$type; + $f[$attr] = $fix; + break; + case 'tag_transform': + $this->info_tag_transform[$params['element']] = $fix; + break; + case 'child': + case 'content_model_type': + $element = $params['element']; + if (empty($this->info[$element])) { + $e = $this->addBlankElement($element); + } else { + $e = $this->info[$element]; + } + $e->$type = $fix; + break; + default: + trigger_error("Fix type $type not supported", E_USER_ERROR); + break; + } + } + } + + /** + * Parses a fix name and determines what kind of fix it is, as well + * as other information defined by the fix + * @param $name String name of fix + * @return array(string $fix_type, array $fix_parameters) + * @note $fix_parameters is type dependant, see populate() for usage + * of these parameters + */ + public function getFixType($name) + { + // parse it + $property = $attr = null; + if (strpos($name, '#') !== false) { + list($name, $property) = explode('#', $name); + } + if (strpos($name, '@') !== false) { + list($name, $attr) = explode('@', $name); + } + + // figure out the parameters + $params = array(); + if ($name !== '') { + $params['element'] = $name; + } + if (!is_null($attr)) { + $params['attr'] = $attr; + } + + // special case: attribute transform + if (!is_null($attr)) { + if (is_null($property)) { + $property = 'pre'; + } + $type = 'attr_transform_' . $property; + return array($type, $params); + } + + // special case: tag transform + if (is_null($property)) { + return array('tag_transform', $params); + } + + return array($property, $params); + + } + + /** + * Defines all fixes the module will perform in a compact + * associative array of fix name to fix implementation. + * @return array + */ + public function makeFixes() + { + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php new file mode 100644 index 00000000..bb47bafd --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php @@ -0,0 +1,33 @@ +content_model_type != 'strictblockquote') { + return parent::getChildDef($def); + } + return new HTMLPurifier_ChildDef_StrictBlockquote($def->content_model); + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php new file mode 100644 index 00000000..79411d25 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php @@ -0,0 +1,16 @@ + 'text-align:left;', + 'right' => 'text-align:right;', + 'top' => 'caption-side:top;', + 'bottom' => 'caption-side:bottom;' // not supported by IE + ) + ); + + // @align for img ------------------------------------------------- + $r['img@align'] = + new HTMLPurifier_AttrTransform_EnumToCSS( + 'align', + array( + 'left' => 'float:left;', + 'right' => 'float:right;', + 'top' => 'vertical-align:top;', + 'middle' => 'vertical-align:middle;', + 'bottom' => 'vertical-align:baseline;', + ) + ); + + // @align for table ----------------------------------------------- + $r['table@align'] = + new HTMLPurifier_AttrTransform_EnumToCSS( + 'align', + array( + 'left' => 'float:left;', + 'center' => 'margin-left:auto;margin-right:auto;', + 'right' => 'float:right;' + ) + ); + + // @align for hr ----------------------------------------------- + $r['hr@align'] = + new HTMLPurifier_AttrTransform_EnumToCSS( + 'align', + array( + // we use both text-align and margin because these work + // for different browsers (IE and Firefox, respectively) + // and the melange makes for a pretty cross-compatible + // solution + 'left' => 'margin-left:0;margin-right:auto;text-align:left;', + 'center' => 'margin-left:auto;margin-right:auto;text-align:center;', + 'right' => 'margin-left:auto;margin-right:0;text-align:right;' + ) + ); + + // @align for h1, h2, h3, h4, h5, h6, p, div ---------------------- + // {{{ + $align_lookup = array(); + $align_values = array('left', 'right', 'center', 'justify'); + foreach ($align_values as $v) { + $align_lookup[$v] = "text-align:$v;"; + } + // }}} + $r['h1@align'] = + $r['h2@align'] = + $r['h3@align'] = + $r['h4@align'] = + $r['h5@align'] = + $r['h6@align'] = + $r['p@align'] = + $r['div@align'] = + new HTMLPurifier_AttrTransform_EnumToCSS('align', $align_lookup); + + // @bgcolor for table, tr, td, th --------------------------------- + $r['table@bgcolor'] = + $r['td@bgcolor'] = + $r['th@bgcolor'] = + new HTMLPurifier_AttrTransform_BgColor(); + + // @border for img ------------------------------------------------ + $r['img@border'] = new HTMLPurifier_AttrTransform_Border(); + + // @clear for br -------------------------------------------------- + $r['br@clear'] = + new HTMLPurifier_AttrTransform_EnumToCSS( + 'clear', + array( + 'left' => 'clear:left;', + 'right' => 'clear:right;', + 'all' => 'clear:both;', + 'none' => 'clear:none;', + ) + ); + + // @height for td, th --------------------------------------------- + $r['td@height'] = + $r['th@height'] = + new HTMLPurifier_AttrTransform_Length('height'); + + // @hspace for img ------------------------------------------------ + $r['img@hspace'] = new HTMLPurifier_AttrTransform_ImgSpace('hspace'); + + // @noshade for hr ------------------------------------------------ + // this transformation is not precise but often good enough. + // different browsers use different styles to designate noshade + $r['hr@noshade'] = + new HTMLPurifier_AttrTransform_BoolToCSS( + 'noshade', + 'color:#808080;background-color:#808080;border:0;' + ); + + // @nowrap for td, th --------------------------------------------- + $r['td@nowrap'] = + $r['th@nowrap'] = + new HTMLPurifier_AttrTransform_BoolToCSS( + 'nowrap', + 'white-space:nowrap;' + ); + + // @size for hr -------------------------------------------------- + $r['hr@size'] = new HTMLPurifier_AttrTransform_Length('size', 'height'); + + // @type for li, ol, ul ------------------------------------------- + // {{{ + $ul_types = array( + 'disc' => 'list-style-type:disc;', + 'square' => 'list-style-type:square;', + 'circle' => 'list-style-type:circle;' + ); + $ol_types = array( + '1' => 'list-style-type:decimal;', + 'i' => 'list-style-type:lower-roman;', + 'I' => 'list-style-type:upper-roman;', + 'a' => 'list-style-type:lower-alpha;', + 'A' => 'list-style-type:upper-alpha;' + ); + $li_types = $ul_types + $ol_types; + // }}} + + $r['ul@type'] = new HTMLPurifier_AttrTransform_EnumToCSS('type', $ul_types); + $r['ol@type'] = new HTMLPurifier_AttrTransform_EnumToCSS('type', $ol_types, true); + $r['li@type'] = new HTMLPurifier_AttrTransform_EnumToCSS('type', $li_types, true); + + // @vspace for img ------------------------------------------------ + $r['img@vspace'] = new HTMLPurifier_AttrTransform_ImgSpace('vspace'); + + // @width for hr, td, th ------------------------------------------ + $r['td@width'] = + $r['th@width'] = + $r['hr@width'] = new HTMLPurifier_AttrTransform_Length('width'); + + return $r; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php new file mode 100644 index 00000000..27a353db --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php @@ -0,0 +1,20 @@ + array( + 'xml:lang' => 'LanguageCode', + ) + ); +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php new file mode 100644 index 00000000..d3ec44f1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php @@ -0,0 +1,356 @@ +armor['MakeWellFormed_TagClosedError'] = true; + return $par; + } + + /** + * @param HTMLPurifier_Token_Text $token + */ + public function handleText(&$token) + { + $text = $token->data; + // Does the current parent allow

        tags? + if ($this->allowsElement('p')) { + if (empty($this->currentNesting) || strpos($text, "\n\n") !== false) { + // Note that we have differing behavior when dealing with text + // in the anonymous root node, or a node inside the document. + // If the text as a double-newline, the treatment is the same; + // if it doesn't, see the next if-block if you're in the document. + + $i = $nesting = null; + if (!$this->forwardUntilEndToken($i, $current, $nesting) && $token->is_whitespace) { + // State 1.1: ... ^ (whitespace, then document end) + // ---- + // This is a degenerate case + } else { + if (!$token->is_whitespace || $this->_isInline($current)) { + // State 1.2: PAR1 + // ---- + + // State 1.3: PAR1\n\nPAR2 + // ------------ + + // State 1.4:

        PAR1\n\nPAR2 (see State 2) + // ------------ + $token = array($this->_pStart()); + $this->_splitText($text, $token); + } else { + // State 1.5: \n
        + // -- + } + } + } else { + // State 2:
        PAR1... (similar to 1.4) + // ---- + + // We're in an element that allows paragraph tags, but we're not + // sure if we're going to need them. + if ($this->_pLookAhead()) { + // State 2.1:
        PAR1PAR1\n\nPAR2 + // ---- + // Note: This will always be the first child, since any + // previous inline element would have triggered this very + // same routine, and found the double newline. One possible + // exception would be a comment. + $token = array($this->_pStart(), $token); + } else { + // State 2.2.1:
        PAR1
        + // ---- + + // State 2.2.2:
        PAR1PAR1
        + // ---- + } + } + // Is the current parent a

        tag? + } elseif (!empty($this->currentNesting) && + $this->currentNesting[count($this->currentNesting) - 1]->name == 'p') { + // State 3.1: ...

        PAR1 + // ---- + + // State 3.2: ...

        PAR1\n\nPAR2 + // ------------ + $token = array(); + $this->_splitText($text, $token); + // Abort! + } else { + // State 4.1: ...PAR1 + // ---- + + // State 4.2: ...PAR1\n\nPAR2 + // ------------ + } + } + + /** + * @param HTMLPurifier_Token $token + */ + public function handleElement(&$token) + { + // We don't have to check if we're already in a

        tag for block + // tokens, because the tag would have been autoclosed by MakeWellFormed. + if ($this->allowsElement('p')) { + if (!empty($this->currentNesting)) { + if ($this->_isInline($token)) { + // State 1:

        ... + // --- + // Check if this token is adjacent to the parent token + // (seek backwards until token isn't whitespace) + $i = null; + $this->backward($i, $prev); + + if (!$prev instanceof HTMLPurifier_Token_Start) { + // Token wasn't adjacent + if ($prev instanceof HTMLPurifier_Token_Text && + substr($prev->data, -2) === "\n\n" + ) { + // State 1.1.4:

        PAR1

        \n\n + // --- + // Quite frankly, this should be handled by splitText + $token = array($this->_pStart(), $token); + } else { + // State 1.1.1:

        PAR1

        + // --- + // State 1.1.2:

        + // --- + // State 1.1.3:
        PAR + // --- + } + } else { + // State 1.2.1:
        + // --- + // Lookahead to see if

        is needed. + if ($this->_pLookAhead()) { + // State 1.3.1:

        PAR1\n\nPAR2 + // --- + $token = array($this->_pStart(), $token); + } else { + // State 1.3.2:
        PAR1
        + // --- + + // State 1.3.3:
        PAR1
        \n\n
        + // --- + } + } + } else { + // State 2.3: ...
        + // ----- + } + } else { + if ($this->_isInline($token)) { + // State 3.1: + // --- + // This is where the {p} tag is inserted, not reflected in + // inputTokens yet, however. + $token = array($this->_pStart(), $token); + } else { + // State 3.2:
        + // ----- + } + + $i = null; + if ($this->backward($i, $prev)) { + if (!$prev instanceof HTMLPurifier_Token_Text) { + // State 3.1.1: ...

        {p} + // --- + // State 3.2.1: ...

        + // ----- + if (!is_array($token)) { + $token = array($token); + } + array_unshift($token, new HTMLPurifier_Token_Text("\n\n")); + } else { + // State 3.1.2: ...

        \n\n{p} + // --- + // State 3.2.2: ...

        \n\n
        + // ----- + // Note: PAR cannot occur because PAR would have been + // wrapped in

        tags. + } + } + } + } else { + // State 2.2:

        • + // ---- + // State 2.4:

          + // --- + } + } + + /** + * Splits up a text in paragraph tokens and appends them + * to the result stream that will replace the original + * @param string $data String text data that will be processed + * into paragraphs + * @param HTMLPurifier_Token[] $result Reference to array of tokens that the + * tags will be appended onto + */ + private function _splitText($data, &$result) + { + $raw_paragraphs = explode("\n\n", $data); + $paragraphs = array(); // without empty paragraphs + $needs_start = false; + $needs_end = false; + + $c = count($raw_paragraphs); + if ($c == 1) { + // There were no double-newlines, abort quickly. In theory this + // should never happen. + $result[] = new HTMLPurifier_Token_Text($data); + return; + } + for ($i = 0; $i < $c; $i++) { + $par = $raw_paragraphs[$i]; + if (trim($par) !== '') { + $paragraphs[] = $par; + } else { + if ($i == 0) { + // Double newline at the front + if (empty($result)) { + // The empty result indicates that the AutoParagraph + // injector did not add any start paragraph tokens. + // This means that we have been in a paragraph for + // a while, and the newline means we should start a new one. + $result[] = new HTMLPurifier_Token_End('p'); + $result[] = new HTMLPurifier_Token_Text("\n\n"); + // However, the start token should only be added if + // there is more processing to be done (i.e. there are + // real paragraphs in here). If there are none, the + // next start paragraph tag will be handled by the + // next call to the injector + $needs_start = true; + } else { + // We just started a new paragraph! + // Reinstate a double-newline for presentation's sake, since + // it was in the source code. + array_unshift($result, new HTMLPurifier_Token_Text("\n\n")); + } + } elseif ($i + 1 == $c) { + // Double newline at the end + // There should be a trailing

          when we're finally done. + $needs_end = true; + } + } + } + + // Check if this was just a giant blob of whitespace. Move this earlier, + // perhaps? + if (empty($paragraphs)) { + return; + } + + // Add the start tag indicated by \n\n at the beginning of $data + if ($needs_start) { + $result[] = $this->_pStart(); + } + + // Append the paragraphs onto the result + foreach ($paragraphs as $par) { + $result[] = new HTMLPurifier_Token_Text($par); + $result[] = new HTMLPurifier_Token_End('p'); + $result[] = new HTMLPurifier_Token_Text("\n\n"); + $result[] = $this->_pStart(); + } + + // Remove trailing start token; Injector will handle this later if + // it was indeed needed. This prevents from needing to do a lookahead, + // at the cost of a lookbehind later. + array_pop($result); + + // If there is no need for an end tag, remove all of it and let + // MakeWellFormed close it later. + if (!$needs_end) { + array_pop($result); // removes \n\n + array_pop($result); // removes

          + } + } + + /** + * Returns true if passed token is inline (and, ergo, allowed in + * paragraph tags) + * @param HTMLPurifier_Token $token + * @return bool + */ + private function _isInline($token) + { + return isset($this->htmlDefinition->info['p']->child->elements[$token->name]); + } + + /** + * Looks ahead in the token list and determines whether or not we need + * to insert a

          tag. + * @return bool + */ + private function _pLookAhead() + { + if ($this->currentToken instanceof HTMLPurifier_Token_Start) { + $nesting = 1; + } else { + $nesting = 0; + } + $ok = false; + $i = null; + while ($this->forwardUntilEndToken($i, $current, $nesting)) { + $result = $this->_checkNeedsP($current); + if ($result !== null) { + $ok = $result; + break; + } + } + return $ok; + } + + /** + * Determines if a particular token requires an earlier inline token + * to get a paragraph. This should be used with _forwardUntilEndToken + * @param HTMLPurifier_Token $current + * @return bool + */ + private function _checkNeedsP($current) + { + if ($current instanceof HTMLPurifier_Token_Start) { + if (!$this->_isInline($current)) { + //

          PAR1
          + // ---- + // Terminate early, since we hit a block element + return false; + } + } elseif ($current instanceof HTMLPurifier_Token_Text) { + if (strpos($current->data, "\n\n") !== false) { + //
          PAR1PAR1\n\nPAR2 + // ---- + return true; + } else { + //
          PAR1PAR1... + // ---- + } + } + return null; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php new file mode 100644 index 00000000..9f904482 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php @@ -0,0 +1,40 @@ +start->attr['href'])) { + $url = $token->start->attr['href']; + unset($token->start->attr['href']); + $token = array($token, new HTMLPurifier_Token_Text(" ($url)")); + } else { + // nothing to display + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php new file mode 100644 index 00000000..531dde4a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php @@ -0,0 +1,64 @@ + array('href')); + + /** + * @param HTMLPurifier_Token $token + */ + public function handleText(&$token) + { + if (!$this->allowsElement('a')) { + return; + } + + if (strpos($token->data, '://') === false) { + // our really quick heuristic failed, abort + // this may not work so well if we want to match things like + // "google.com", but then again, most people don't + return; + } + + // there is/are URL(s). Let's split the string. + // We use this regex: + // https://gist.github.com/gruber/249502 + // but with @cscott's backtracking fix and also + // the Unicode characters un-Unicodified. + $bits = preg_split( + '/\\b((?:[a-z][\\w\\-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]|\\((?:[^\\s()<>]|(?:\\([^\\s()<>]+\\)))*\\))+(?:\\((?:[^\\s()<>]|(?:\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'".,<>?\x{00ab}\x{00bb}\x{201c}\x{201d}\x{2018}\x{2019}]))/iu', + $token->data, -1, PREG_SPLIT_DELIM_CAPTURE); + + + $token = array(); + + // $i = index + // $c = count + // $l = is link + for ($i = 0, $c = count($bits), $l = false; $i < $c; $i++, $l = !$l) { + if (!$l) { + if ($bits[$i] === '') { + continue; + } + $token[] = new HTMLPurifier_Token_Text($bits[$i]); + } else { + $token[] = new HTMLPurifier_Token_Start('a', array('href' => $bits[$i])); + $token[] = new HTMLPurifier_Token_Text($bits[$i]); + $token[] = new HTMLPurifier_Token_End('a'); + } + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php new file mode 100644 index 00000000..d7dd7d97 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php @@ -0,0 +1,71 @@ + array('href')); + + /** + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return string + */ + public function prepare($config, $context) + { + $this->docURL = $config->get('AutoFormat.PurifierLinkify.DocURL'); + return parent::prepare($config, $context); + } + + /** + * @param HTMLPurifier_Token $token + */ + public function handleText(&$token) + { + if (!$this->allowsElement('a')) { + return; + } + if (strpos($token->data, '%') === false) { + return; + } + + $bits = preg_split('#%([a-z0-9]+\.[a-z0-9]+)#Si', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE); + $token = array(); + + // $i = index + // $c = count + // $l = is link + for ($i = 0, $c = count($bits), $l = false; $i < $c; $i++, $l = !$l) { + if (!$l) { + if ($bits[$i] === '') { + continue; + } + $token[] = new HTMLPurifier_Token_Text($bits[$i]); + } else { + $token[] = new HTMLPurifier_Token_Start( + 'a', + array('href' => str_replace('%s', $bits[$i], $this->docURL)) + ); + $token[] = new HTMLPurifier_Token_Text('%' . $bits[$i]); + $token[] = new HTMLPurifier_Token_End('a'); + } + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php new file mode 100644 index 00000000..aae2dca1 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php @@ -0,0 +1,112 @@ +config = $config; + $this->context = $context; + $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp'); + $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions'); + $this->exclude = $config->get('AutoFormat.RemoveEmpty.Predicate'); + foreach ($this->exclude as $key => $attrs) { + if (!is_array($attrs)) { + // HACK, see HTMLPurifier/Printer/ConfigForm.php + $this->exclude[$key] = explode(';', $attrs); + } + } + $this->attrValidator = new HTMLPurifier_AttrValidator(); + } + + /** + * @param HTMLPurifier_Token $token + */ + public function handleElement(&$token) + { + if (!$token instanceof HTMLPurifier_Token_Start) { + return; + } + $next = false; + $deleted = 1; // the current tag + for ($i = count($this->inputZipper->back) - 1; $i >= 0; $i--, $deleted++) { + $next = $this->inputZipper->back[$i]; + if ($next instanceof HTMLPurifier_Token_Text) { + if ($next->is_whitespace) { + continue; + } + if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) { + $plain = str_replace("\xC2\xA0", "", $next->data); + $isWsOrNbsp = $plain === '' || ctype_space($plain); + if ($isWsOrNbsp) { + continue; + } + } + } + break; + } + if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) { + $this->attrValidator->validateToken($token, $this->config, $this->context); + $token->armor['ValidateAttributes'] = true; + if (isset($this->exclude[$token->name])) { + $r = true; + foreach ($this->exclude[$token->name] as $elem) { + if (!isset($token->attr[$elem])) $r = false; + } + if ($r) return; + } + if (isset($token->attr['id']) || isset($token->attr['name'])) { + return; + } + $token = $deleted + 1; + for ($b = 0, $c = count($this->inputZipper->front); $b < $c; $b++) { + $prev = $this->inputZipper->front[$b]; + if ($prev instanceof HTMLPurifier_Token_Text && $prev->is_whitespace) { + continue; + } + break; + } + // This is safe because we removed the token that triggered this. + $this->rewindOffset($b+$deleted); + return; + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php new file mode 100644 index 00000000..270b7f82 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php @@ -0,0 +1,84 @@ +attrValidator = new HTMLPurifier_AttrValidator(); + $this->config = $config; + $this->context = $context; + return parent::prepare($config, $context); + } + + /** + * @param HTMLPurifier_Token $token + */ + public function handleElement(&$token) + { + if ($token->name !== 'span' || !$token instanceof HTMLPurifier_Token_Start) { + return; + } + + // We need to validate the attributes now since this doesn't normally + // happen until after MakeWellFormed. If all the attributes are removed + // the span needs to be removed too. + $this->attrValidator->validateToken($token, $this->config, $this->context); + $token->armor['ValidateAttributes'] = true; + + if (!empty($token->attr)) { + return; + } + + $nesting = 0; + while ($this->forwardUntilEndToken($i, $current, $nesting)) { + } + + if ($current instanceof HTMLPurifier_Token_End && $current->name === 'span') { + // Mark closing span tag for deletion + $current->markForDeletion = true; + // Delete open span tag + $token = false; + } + } + + /** + * @param HTMLPurifier_Token $token + */ + public function handleEnd(&$token) + { + if ($token->markForDeletion) { + $token = false; + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php new file mode 100644 index 00000000..0b051101 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php @@ -0,0 +1,124 @@ + 'never', + 'allowNetworking' => 'internal', + ); + + /** + * These are all lower-case keys. + * @type array + */ + protected $allowedParam = array( + 'wmode' => true, + 'movie' => true, + 'flashvars' => true, + 'src' => true, + 'allowfullscreen' => true, // if omitted, assume to be 'false' + ); + + /** + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return void + */ + public function prepare($config, $context) + { + parent::prepare($config, $context); + } + + /** + * @param HTMLPurifier_Token $token + */ + public function handleElement(&$token) + { + if ($token->name == 'object') { + $this->objectStack[] = $token; + $this->paramStack[] = array(); + $new = array($token); + foreach ($this->addParam as $name => $value) { + $new[] = new HTMLPurifier_Token_Empty('param', array('name' => $name, 'value' => $value)); + } + $token = $new; + } elseif ($token->name == 'param') { + $nest = count($this->currentNesting) - 1; + if ($nest >= 0 && $this->currentNesting[$nest]->name === 'object') { + $i = count($this->objectStack) - 1; + if (!isset($token->attr['name'])) { + $token = false; + return; + } + $n = $token->attr['name']; + // We need this fix because YouTube doesn't supply a data + // attribute, which we need if a type is specified. This is + // *very* Flash specific. + if (!isset($this->objectStack[$i]->attr['data']) && + ($token->attr['name'] == 'movie' || $token->attr['name'] == 'src') + ) { + $this->objectStack[$i]->attr['data'] = $token->attr['value']; + } + // Check if the parameter is the correct value but has not + // already been added + if (!isset($this->paramStack[$i][$n]) && + isset($this->addParam[$n]) && + $token->attr['name'] === $this->addParam[$n]) { + // keep token, and add to param stack + $this->paramStack[$i][$n] = true; + } elseif (isset($this->allowedParam[strtolower($n)])) { + // keep token, don't do anything to it + // (could possibly check for duplicates here) + // Note: In principle, parameters should be case sensitive. + // But it seems they are not really; so accept any case. + } else { + $token = false; + } + } else { + // not directly inside an object, DENY! + $token = false; + } + } + } + + public function handleEnd(&$token) + { + // This is the WRONG way of handling the object and param stacks; + // we should be inserting them directly on the relevant object tokens + // so that the global stack handling handles it. + if ($token->name == 'object') { + array_pop($this->objectStack); + array_pop($this->paramStack); + } + } +} + +// vim: et sw=4 sts=4 From 1caba3cfd8f1a36f43f8bd22fe4f30a379cbf738 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:35:48 +0700 Subject: [PATCH 23/94] Add files via upload --- .../HTMLPurifier/ChildDef/Chameleon.php | 67 ++++++ .../library/HTMLPurifier/ChildDef/Custom.php | 102 ++++++++ .../library/HTMLPurifier/ChildDef/Empty.php | 38 +++ .../library/HTMLPurifier/ChildDef/List.php | 92 +++++++ .../HTMLPurifier/ChildDef/Optional.php | 45 ++++ .../HTMLPurifier/ChildDef/Required.php | 118 +++++++++ .../ChildDef/StrictBlockquote.php | 110 +++++++++ .../library/HTMLPurifier/ChildDef/Table.php | 224 ++++++++++++++++++ 8 files changed, 796 insertions(+) create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/List.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php create mode 100644 protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php new file mode 100644 index 00000000..f6b2f22e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php @@ -0,0 +1,67 @@ +inline = new HTMLPurifier_ChildDef_Optional($inline); + $this->block = new HTMLPurifier_ChildDef_Optional($block); + $this->elements = $this->block->elements; + } + + /** + * @param HTMLPurifier_Node[] $children + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool + */ + public function validateChildren($children, $config, $context) + { + if ($context->get('IsInline') === false) { + return $this->block->validateChildren( + $children, + $config, + $context + ); + } else { + return $this->inline->validateChildren( + $children, + $config, + $context + ); + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php new file mode 100644 index 00000000..1047cd8e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php @@ -0,0 +1,102 @@ +dtd_regex = $dtd_regex; + $this->_compileRegex(); + } + + /** + * Compiles the PCRE regex from a DTD regex ($dtd_regex to $_pcre_regex) + */ + protected function _compileRegex() + { + $raw = str_replace(' ', '', $this->dtd_regex); + if ($raw{0} != '(') { + $raw = "($raw)"; + } + $el = '[#a-zA-Z0-9_.-]+'; + $reg = $raw; + + // COMPLICATED! AND MIGHT BE BUGGY! I HAVE NO CLUE WHAT I'M + // DOING! Seriously: if there's problems, please report them. + + // collect all elements into the $elements array + preg_match_all("/$el/", $reg, $matches); + foreach ($matches[0] as $match) { + $this->elements[$match] = true; + } + + // setup all elements as parentheticals with leading commas + $reg = preg_replace("/$el/", '(,\\0)', $reg); + + // remove commas when they were not solicited + $reg = preg_replace("/([^,(|]\(+),/", '\\1', $reg); + + // remove all non-paranthetical commas: they are handled by first regex + $reg = preg_replace("/,\(/", '(', $reg); + + $this->_pcre_regex = $reg; + } + + /** + * @param HTMLPurifier_Node[] $children + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool + */ + public function validateChildren($children, $config, $context) + { + $list_of_children = ''; + $nesting = 0; // depth into the nest + foreach ($children as $node) { + if (!empty($node->is_whitespace)) { + continue; + } + $list_of_children .= $node->name . ','; + } + // add leading comma to deal with stray comma declarations + $list_of_children = ',' . rtrim($list_of_children, ','); + $okay = + preg_match( + '/^,?' . $this->_pcre_regex . '$/', + $list_of_children + ); + return (bool)$okay; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php new file mode 100644 index 00000000..bbcde56e --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php @@ -0,0 +1,38 @@ + true, 'ul' => true, 'ol' => true); + + /** + * @param array $children + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function validateChildren($children, $config, $context) + { + // Flag for subclasses + $this->whitespace = false; + + // if there are no tokens, delete parent node + if (empty($children)) { + return false; + } + + // if li is not allowed, delete parent node + if (!isset($config->getHTMLDefinition()->info['li'])) { + trigger_error("Cannot allow ul/ol without allowing li", E_USER_WARNING); + return false; + } + + // the new set of children + $result = array(); + + // a little sanity check to make sure it's not ALL whitespace + $all_whitespace = true; + + $current_li = null; + + foreach ($children as $node) { + if (!empty($node->is_whitespace)) { + $result[] = $node; + continue; + } + $all_whitespace = false; // phew, we're not talking about whitespace + + if ($node->name === 'li') { + // good + $current_li = $node; + $result[] = $node; + } else { + // we want to tuck this into the previous li + // Invariant: we expect the node to be ol/ul + // ToDo: Make this more robust in the case of not ol/ul + // by distinguishing between existing li and li created + // to handle non-list elements; non-list elements should + // not be appended to an existing li; only li created + // for non-list. This distinction is not currently made. + if ($current_li === null) { + $current_li = new HTMLPurifier_Node_Element('li'); + $result[] = $current_li; + } + $current_li->children[] = $node; + $current_li->empty = false; // XXX fascinating! Check for this error elsewhere ToDo + } + } + if (empty($result)) { + return false; + } + if ($all_whitespace) { + return false; + } + return $result; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php new file mode 100644 index 00000000..1db864d9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php @@ -0,0 +1,45 @@ +whitespace) { + return $children; + } else { + return array(); + } + } + return $result; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php new file mode 100644 index 00000000..f6b8e8a2 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php @@ -0,0 +1,118 @@ + $x) { + $elements[$i] = true; + if (empty($i)) { + unset($elements[$i]); + } // remove blank + } + } + $this->elements = $elements; + } + + /** + * @type bool + */ + public $allow_empty = false; + + /** + * @type string + */ + public $type = 'required'; + + /** + * @param array $children + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function validateChildren($children, $config, $context) + { + // Flag for subclasses + $this->whitespace = false; + + // if there are no tokens, delete parent node + if (empty($children)) { + return false; + } + + // the new set of children + $result = array(); + + // whether or not parsed character data is allowed + // this controls whether or not we silently drop a tag + // or generate escaped HTML from it + $pcdata_allowed = isset($this->elements['#PCDATA']); + + // a little sanity check to make sure it's not ALL whitespace + $all_whitespace = true; + + $stack = array_reverse($children); + while (!empty($stack)) { + $node = array_pop($stack); + if (!empty($node->is_whitespace)) { + $result[] = $node; + continue; + } + $all_whitespace = false; // phew, we're not talking about whitespace + + if (!isset($this->elements[$node->name])) { + // special case text + // XXX One of these ought to be redundant or something + if ($pcdata_allowed && $node instanceof HTMLPurifier_Node_Text) { + $result[] = $node; + continue; + } + // spill the child contents in + // ToDo: Make configurable + if ($node instanceof HTMLPurifier_Node_Element) { + for ($i = count($node->children) - 1; $i >= 0; $i--) { + $stack[] = $node->children[$i]; + } + continue; + } + continue; + } + $result[] = $node; + } + if (empty($result)) { + return false; + } + if ($all_whitespace) { + $this->whitespace = true; + return false; + } + return $result; + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php new file mode 100644 index 00000000..38bf9533 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php @@ -0,0 +1,110 @@ +init($config); + return $this->fake_elements; + } + + /** + * @param array $children + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function validateChildren($children, $config, $context) + { + $this->init($config); + + // trick the parent class into thinking it allows more + $this->elements = $this->fake_elements; + $result = parent::validateChildren($children, $config, $context); + $this->elements = $this->real_elements; + + if ($result === false) { + return array(); + } + if ($result === true) { + $result = $children; + } + + $def = $config->getHTMLDefinition(); + $block_wrap_name = $def->info_block_wrapper; + $block_wrap = false; + $ret = array(); + + foreach ($result as $node) { + if ($block_wrap === false) { + if (($node instanceof HTMLPurifier_Node_Text && !$node->is_whitespace) || + ($node instanceof HTMLPurifier_Node_Element && !isset($this->elements[$node->name]))) { + $block_wrap = new HTMLPurifier_Node_Element($def->info_block_wrapper); + $ret[] = $block_wrap; + } + } else { + if ($node instanceof HTMLPurifier_Node_Element && isset($this->elements[$node->name])) { + $block_wrap = false; + + } + } + if ($block_wrap) { + $block_wrap->children[] = $node; + } else { + $ret[] = $node; + } + } + return $ret; + } + + /** + * @param HTMLPurifier_Config $config + */ + private function init($config) + { + if (!$this->init) { + $def = $config->getHTMLDefinition(); + // allow all inline elements + $this->real_elements = $this->elements; + $this->fake_elements = $def->info_content_sets['Flow']; + $this->fake_elements['#PCDATA'] = true; + $this->init = true; + } + } +} + +// vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php new file mode 100644 index 00000000..9b12c928 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php @@ -0,0 +1,224 @@ + true, + 'tbody' => true, + 'thead' => true, + 'tfoot' => true, + 'caption' => true, + 'colgroup' => true, + 'col' => true + ); + + public function __construct() + { + } + + /** + * @param array $children + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function validateChildren($children, $config, $context) + { + if (empty($children)) { + return false; + } + + // only one of these elements is allowed in a table + $caption = false; + $thead = false; + $tfoot = false; + + // whitespace + $initial_ws = array(); + $after_caption_ws = array(); + $after_thead_ws = array(); + $after_tfoot_ws = array(); + + // as many of these as you want + $cols = array(); + $content = array(); + + $tbody_mode = false; // if true, then we need to wrap any stray + //
  • + + + + + +
    OriginalTextAttribute
    &yen;¥¥
    &yen¥¥
    &yena&yena&yena
    &yen=¥=¥=
    +

    + In HTML Purifier 4.9.0, we changed the behavior of entity parsing + to match entities that had missing trailing semicolons in less + cases, to more closely match HTML5 parsing behavior: +

    + + + + + + +
    OriginalTextAttribute
    &yen;¥¥
    &yen¥¥
    &yena¥a&yena
    &yen=¥=&yen=
    +

    + This flag reverts back to pre-HTML Purifier 4.9.0 behavior. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt new file mode 100644 index 00000000..e11c0152 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt @@ -0,0 +1,34 @@ +Core.LexerImpl +TYPE: mixed/null +VERSION: 2.0.0 +DEFAULT: NULL +--DESCRIPTION-- + +

    + This parameter determines what lexer implementation can be used. The + valid values are: +

    +
    +
    null
    +
    + Recommended, the lexer implementation will be auto-detected based on + your PHP-version and configuration. +
    +
    string lexer identifier
    +
    + This is a slim way of manually overridding the implementation. + Currently recognized values are: DOMLex (the default PHP5 +implementation) + and DirectLex (the default PHP4 implementation). Only use this if + you know what you are doing: usually, the auto-detection will + manage things for cases you aren't even aware of. +
    +
    object lexer instance
    +
    + Super-advanced: you can specify your own, custom, implementation that + implements the interface defined by HTMLPurifier_Lexer. + I may remove this option simply because I don't expect anyone + to use it. +
    +
    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt new file mode 100644 index 00000000..838f10f6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt @@ -0,0 +1,16 @@ +Core.MaintainLineNumbers +TYPE: bool/null +VERSION: 2.0.0 +DEFAULT: NULL +--DESCRIPTION-- + +

    + If true, HTML Purifier will add line number information to all tokens. + This is useful when error reporting is turned on, but can result in + significant performance degradation and should not be used when + unnecessary. This directive must be used with the DirectLex lexer, + as the DOMLex lexer does not (yet) support this functionality. + If the value is null, an appropriate value will be selected based + on other configuration. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt new file mode 100644 index 00000000..94a88600 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt @@ -0,0 +1,11 @@ +Core.NormalizeNewlines +TYPE: bool +VERSION: 4.2.0 +DEFAULT: true +--DESCRIPTION-- +

    + Whether or not to normalize newlines to the operating + system default. When false, HTML Purifier + will attempt to preserve mixed newline files. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt new file mode 100644 index 00000000..704ac56c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt @@ -0,0 +1,12 @@ +Core.RemoveInvalidImg +TYPE: bool +DEFAULT: true +VERSION: 1.3.0 +--DESCRIPTION-- + +

    + This directive enables pre-emptive URI checking in img + tags, as the attribute validation strategy is not authorized to + remove elements from the document. Revert to pre-1.3.0 behavior by setting to false. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt new file mode 100644 index 00000000..ed6f1342 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt @@ -0,0 +1,11 @@ +Core.RemoveProcessingInstructions +TYPE: bool +VERSION: 4.2.0 +DEFAULT: false +--DESCRIPTION-- +Instead of escaping processing instructions in the form <? ... +?>, remove it out-right. This may be useful if the HTML +you are validating contains XML processing instruction gunk, however, +it can also be user-unfriendly for people attempting to post PHP +snippets. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt new file mode 100644 index 00000000..efbe994c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt @@ -0,0 +1,12 @@ +Core.RemoveScriptContents +TYPE: bool/null +DEFAULT: NULL +VERSION: 2.0.0 +DEPRECATED-VERSION: 2.1.0 +DEPRECATED-USE: Core.HiddenElements +--DESCRIPTION-- +

    + This directive enables HTML Purifier to remove not only script tags + but all of their contents. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt new file mode 100644 index 00000000..861ae66c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt @@ -0,0 +1,11 @@ +Filter.Custom +TYPE: list +VERSION: 3.1.0 +DEFAULT: array() +--DESCRIPTION-- +

    + This directive can be used to add custom filters; it is nearly the + equivalent of the now deprecated HTMLPurifier->addFilter() + method. Specify an array of concrete implementations. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt new file mode 100644 index 00000000..69602635 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt @@ -0,0 +1,14 @@ +Filter.ExtractStyleBlocks.Escaping +TYPE: bool +VERSION: 3.0.0 +DEFAULT: true +ALIASES: Filter.ExtractStyleBlocksEscaping, FilterParam.ExtractStyleBlocksEscaping +--DESCRIPTION-- + +

    + Whether or not to escape the dangerous characters <, > and & + as \3C, \3E and \26, respectively. This is can be safely set to false + if the contents of StyleBlocks will be placed in an external stylesheet, + where there is no risk of it being interpreted as HTML. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt new file mode 100644 index 00000000..baa81ae0 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt @@ -0,0 +1,29 @@ +Filter.ExtractStyleBlocks.Scope +TYPE: string/null +VERSION: 3.0.0 +DEFAULT: NULL +ALIASES: Filter.ExtractStyleBlocksScope, FilterParam.ExtractStyleBlocksScope +--DESCRIPTION-- + +

    + If you would like users to be able to define external stylesheets, but + only allow them to specify CSS declarations for a specific node and + prevent them from fiddling with other elements, use this directive. + It accepts any valid CSS selector, and will prepend this to any + CSS declaration extracted from the document. For example, if this + directive is set to #user-content and a user uses the + selector a:hover, the final selector will be + #user-content a:hover. +

    +

    + The comma shorthand may be used; consider the above example, with + #user-content, #user-content2, the final selector will + be #user-content a:hover, #user-content2 a:hover. +

    +

    + Warning: It is possible for users to bypass this measure + using a naughty + selector. This is a bug in CSS Tidy 1.3, not HTML + Purifier, and I am working to get it fixed. Until then, HTML Purifier + performs a basic check to prevent this. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt new file mode 100644 index 00000000..3b701891 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt @@ -0,0 +1,16 @@ +Filter.ExtractStyleBlocks.TidyImpl +TYPE: mixed/null +VERSION: 3.1.0 +DEFAULT: NULL +ALIASES: FilterParam.ExtractStyleBlocksTidyImpl +--DESCRIPTION-- +

    + If left NULL, HTML Purifier will attempt to instantiate a csstidy + class to use for internal cleaning. This will usually be good enough. +

    +

    + However, for trusted user input, you can set this to false to + disable cleaning. In addition, you can supply your own concrete implementation + of Tidy's interface to use, although I don't know why you'd want to do that. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt new file mode 100644 index 00000000..be0177d4 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt @@ -0,0 +1,74 @@ +Filter.ExtractStyleBlocks +TYPE: bool +VERSION: 3.1.0 +DEFAULT: false +EXTERNAL: CSSTidy +--DESCRIPTION-- +

    + This directive turns on the style block extraction filter, which removes + style blocks from input HTML, cleans them up with CSSTidy, + and places them in the StyleBlocks context variable, for further + use by you, usually to be placed in an external stylesheet, or a + style block in the head of your document. +

    +

    + Sample usage: +

    +
    ';
    +?>
    +
    +
    +
    +  Filter.ExtractStyleBlocks
    +body {color:#F00;} Some text';
    +
    +    $config = HTMLPurifier_Config::createDefault();
    +    $config->set('Filter', 'ExtractStyleBlocks', true);
    +    $purifier = new HTMLPurifier($config);
    +
    +    $html = $purifier->purify($dirty);
    +
    +    // This implementation writes the stylesheets to the styles/ directory.
    +    // You can also echo the styles inside the document, but it's a bit
    +    // more difficult to make sure they get interpreted properly by
    +    // browsers; try the usual CSS armoring techniques.
    +    $styles = $purifier->context->get('StyleBlocks');
    +    $dir = 'styles/';
    +    if (!is_dir($dir)) mkdir($dir);
    +    $hash = sha1($_GET['html']);
    +    foreach ($styles as $i => $style) {
    +        file_put_contents($name = $dir . $hash . "_$i");
    +        echo '';
    +    }
    +?>
    +
    +
    +  
    + +
    + + +]]>
    +

    + Warning: It is possible for a user to mount an + imagecrash attack using this CSS. Counter-measures are difficult; + it is not simply enough to limit the range of CSS lengths (using + relative lengths with many nesting levels allows for large values + to be attained without actually specifying them in the stylesheet), + and the flexible nature of selectors makes it difficult to selectively + disable lengths on image tags (HTML Purifier, however, does disable + CSS width and height in inline styling). There are probably two effective + counter measures: an explicit width and height set to auto in all + images in your document (unlikely) or the disabling of width and + height (somewhat reasonable). Whether or not these measures should be + used is left to the reader. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt new file mode 100644 index 00000000..88221866 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt @@ -0,0 +1,16 @@ +Filter.YouTube +TYPE: bool +VERSION: 3.1.0 +DEFAULT: false +--DESCRIPTION-- +

    + Warning: Deprecated in favor of %HTML.SafeObject and + %Output.FlashCompat (turn both on to allow YouTube videos and other + Flash content). +

    +

    + This directive enables YouTube video embedding in HTML Purifier. Check + this document + on embedding videos for more information on what this filter does. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt new file mode 100644 index 00000000..afd48a0d --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt @@ -0,0 +1,25 @@ +HTML.Allowed +TYPE: itext/null +VERSION: 2.0.0 +DEFAULT: NULL +--DESCRIPTION-- + +

    + This is a preferred convenience directive that combines + %HTML.AllowedElements and %HTML.AllowedAttributes. + Specify elements and attributes that are allowed using: + element1[attr1|attr2],element2.... For example, + if you would like to only allow paragraphs and links, specify + a[href],p. You can specify attributes that apply + to all elements using an asterisk, e.g. *[lang]. + You can also use newlines instead of commas to separate elements. +

    +

    + Warning: + All of the constraints on the component directives are still enforced. + The syntax is a subset of TinyMCE's valid_elements + whitelist: directly copy-pasting it here will probably result in + broken whitelists. If %HTML.AllowedElements or %HTML.AllowedAttributes + are set, this directive has no effect. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt new file mode 100644 index 00000000..0e6ec54f --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt @@ -0,0 +1,19 @@ +HTML.AllowedAttributes +TYPE: lookup/null +VERSION: 1.3.0 +DEFAULT: NULL +--DESCRIPTION-- + +

    + If HTML Purifier's attribute set is unsatisfactory, overload it! + The syntax is "tag.attr" or "*.attr" for the global attributes + (style, id, class, dir, lang, xml:lang). +

    +

    + Warning: If another directive conflicts with the + elements here, that directive will win and override. For + example, %HTML.EnableAttrID will take precedence over *.id in this + directive. You must set that directive to true before you can use + IDs at all. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt new file mode 100644 index 00000000..8440bc39 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt @@ -0,0 +1,10 @@ +HTML.AllowedComments +TYPE: lookup +VERSION: 4.4.0 +DEFAULT: array() +--DESCRIPTION-- +A whitelist which indicates what explicit comment bodies should be +allowed, modulo leading and trailing whitespace. See also %HTML.AllowedCommentsRegexp +(these directives are union'ed together, so a comment is considered +valid if any directive deems it valid.) +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt new file mode 100644 index 00000000..b1e65beb --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt @@ -0,0 +1,15 @@ +HTML.AllowedCommentsRegexp +TYPE: string/null +VERSION: 4.4.0 +DEFAULT: NULL +--DESCRIPTION-- +A regexp, which if it matches the body of a comment, indicates that +it should be allowed. Trailing and leading spaces are removed prior +to running this regular expression. +Warning: Make sure you specify +correct anchor metacharacters ^regex$, otherwise you may accept +comments that you did not mean to! In particular, the regex /foo|bar/ +is probably not sufficiently strict, since it also allows foobar. +See also %HTML.AllowedComments (these directives are union'ed together, +so a comment is considered valid if any directive deems it valid.) +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt new file mode 100644 index 00000000..ca3c13dd --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt @@ -0,0 +1,23 @@ +HTML.AllowedElements +TYPE: lookup/null +VERSION: 1.3.0 +DEFAULT: NULL +--DESCRIPTION-- +

    + If HTML Purifier's tag set is unsatisfactory for your needs, you can + overload it with your own list of tags to allow. If you change + this, you probably also want to change %HTML.AllowedAttributes; see + also %HTML.Allowed which lets you set allowed elements and + attributes at the same time. +

    +

    + If you attempt to allow an element that HTML Purifier does not know + about, HTML Purifier will raise an error. You will need to manually + tell HTML Purifier about this element by using the + advanced customization features. +

    +

    + Warning: If another directive conflicts with the + elements here, that directive will win and override. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt new file mode 100644 index 00000000..e373791a --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt @@ -0,0 +1,20 @@ +HTML.AllowedModules +TYPE: lookup/null +VERSION: 2.0.0 +DEFAULT: NULL +--DESCRIPTION-- + +

    + A doctype comes with a set of usual modules to use. Without having + to mucking about with the doctypes, you can quickly activate or + disable these modules by specifying which modules you wish to allow + with this directive. This is most useful for unit testing specific + modules, although end users may find it useful for their own ends. +

    +

    + If you specify a module that does not exist, the manager will silently + fail to use it, so be careful! User-defined modules are not affected + by this directive. Modules defined in %HTML.CoreModules are not + affected by this directive. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt new file mode 100644 index 00000000..75d680ee --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt @@ -0,0 +1,11 @@ +HTML.Attr.Name.UseCDATA +TYPE: bool +DEFAULT: false +VERSION: 4.0.0 +--DESCRIPTION-- +The W3C specification DTD defines the name attribute to be CDATA, not ID, due +to limitations of DTD. In certain documents, this relaxed behavior is desired, +whether it is to specify duplicate names, or to specify names that would be +illegal IDs (for example, names that begin with a digit.) Set this configuration +directive to true to use the relaxed parsing rules. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt new file mode 100644 index 00000000..f32b802c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt @@ -0,0 +1,18 @@ +HTML.BlockWrapper +TYPE: string +VERSION: 1.3.0 +DEFAULT: 'p' +--DESCRIPTION-- + +

    + String name of element to wrap inline elements that are inside a block + context. This only occurs in the children of blockquote in strict mode. +

    +

    + Example: by default value, + <blockquote>Foo</blockquote> would become + <blockquote><p>Foo</p></blockquote>. + The <p> tags can be replaced with whatever you desire, + as long as it is a block level element. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt new file mode 100644 index 00000000..fc8e4020 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt @@ -0,0 +1,23 @@ +HTML.CoreModules +TYPE: lookup +VERSION: 2.0.0 +--DEFAULT-- +array ( + 'Structure' => true, + 'Text' => true, + 'Hypertext' => true, + 'List' => true, + 'NonXMLCommonAttributes' => true, + 'XMLCommonAttributes' => true, + 'CommonAttributes' => true, +) +--DESCRIPTION-- + +

    + Certain modularized doctypes (XHTML, namely), have certain modules + that must be included for the doctype to be an conforming document + type: put those modules here. By default, XHTML's core modules + are used. You can set this to a blank array to disable core module + protection, but this is not recommended. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt new file mode 100644 index 00000000..187c0a0d --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt @@ -0,0 +1,9 @@ +HTML.CustomDoctype +TYPE: string/null +VERSION: 2.0.1 +DEFAULT: NULL +--DESCRIPTION-- + +A custom doctype for power-users who defined their own document +type. This directive only applies when %HTML.Doctype is blank. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt new file mode 100644 index 00000000..f5433e3f --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt @@ -0,0 +1,33 @@ +HTML.DefinitionID +TYPE: string/null +DEFAULT: NULL +VERSION: 2.0.0 +--DESCRIPTION-- + +

    + Unique identifier for a custom-built HTML definition. If you edit + the raw version of the HTMLDefinition, introducing changes that the + configuration object does not reflect, you must specify this variable. + If you change your custom edits, you should change this directive, or + clear your cache. Example: +

    +
    +$config = HTMLPurifier_Config::createDefault();
    +$config->set('HTML', 'DefinitionID', '1');
    +$def = $config->getHTMLDefinition();
    +$def->addAttribute('a', 'tabindex', 'Number');
    +
    +

    + In the above example, the configuration is still at the defaults, but + using the advanced API, an extra attribute has been added. The + configuration object normally has no way of knowing that this change + has taken place, so it needs an extra directive: %HTML.DefinitionID. + If someone else attempts to use the default configuration, these two + pieces of code will not clobber each other in the cache, since one has + an extra directive attached to it. +

    +

    + You must specify a value to this directive to use the + advanced API features. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt new file mode 100644 index 00000000..0bb5a718 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt @@ -0,0 +1,16 @@ +HTML.DefinitionRev +TYPE: int +VERSION: 2.0.0 +DEFAULT: 1 +--DESCRIPTION-- + +

    + Revision identifier for your custom definition specified in + %HTML.DefinitionID. This serves the same purpose: uniquely identifying + your custom definition, but this one does so in a chronological + context: revision 3 is more up-to-date then revision 2. Thus, when + this gets incremented, the cache handling is smart enough to clean + up any older revisions of your definition as well as flush the + cache. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt new file mode 100644 index 00000000..a6969b99 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt @@ -0,0 +1,11 @@ +HTML.Doctype +TYPE: string/null +DEFAULT: NULL +--DESCRIPTION-- +Doctype to use during filtering. Technically speaking this is not actually +a doctype (as it does not identify a corresponding DTD), but we are using +this name for sake of simplicity. When non-blank, this will override any +older directives like %HTML.XHTML or %HTML.Strict. +--ALLOWED-- +'HTML 4.01 Transitional', 'HTML 4.01 Strict', 'XHTML 1.0 Transitional', 'XHTML 1.0 Strict', 'XHTML 1.1' +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt new file mode 100644 index 00000000..08d641f9 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt @@ -0,0 +1,11 @@ +HTML.FlashAllowFullScreen +TYPE: bool +VERSION: 4.2.0 +DEFAULT: false +--DESCRIPTION-- +

    + Whether or not to permit embedded Flash content from + %HTML.SafeObject to expand to the full screen. Corresponds to + the allowFullScreen parameter. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt new file mode 100644 index 00000000..2b8df97c --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt @@ -0,0 +1,21 @@ +HTML.ForbiddenAttributes +TYPE: lookup +VERSION: 3.1.0 +DEFAULT: array() +--DESCRIPTION-- +

    + While this directive is similar to %HTML.AllowedAttributes, for + forwards-compatibility with XML, this attribute has a different syntax. Instead of + tag.attr, use tag@attr. To disallow href + attributes in a tags, set this directive to + a@href. You can also disallow an attribute globally with + attr or *@attr (either syntax is fine; the latter + is provided for consistency with %HTML.AllowedAttributes). +

    +

    + Warning: This directive complements %HTML.ForbiddenElements, + accordingly, check + out that directive for a discussion of why you + should think twice before using this directive. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt new file mode 100644 index 00000000..40466c46 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt @@ -0,0 +1,20 @@ +HTML.ForbiddenElements +TYPE: lookup +VERSION: 3.1.0 +DEFAULT: array() +--DESCRIPTION-- +

    + This was, perhaps, the most requested feature ever in HTML + Purifier. Please don't abuse it! This is the logical inverse of + %HTML.AllowedElements, and it will override that directive, or any + other directive. +

    +

    + If possible, %HTML.Allowed is recommended over this directive, because it + can sometimes be difficult to tell whether or not you've forbidden all of + the behavior you would like to disallow. If you forbid img + with the expectation of preventing images on your site, you'll be in for + a nasty surprise when people start using the background-image + CSS property. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt new file mode 100644 index 00000000..31974795 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt @@ -0,0 +1,14 @@ +HTML.MaxImgLength +TYPE: int/null +DEFAULT: 1200 +VERSION: 3.1.1 +--DESCRIPTION-- +

    + This directive controls the maximum number of pixels in the width and + height attributes in img tags. This is + in place to prevent imagecrash attacks, disable with null at your own risk. + This directive is similar to %CSS.MaxImgLength, and both should be + concurrently edited, although there are + subtle differences in the input format (the HTML max is an integer). +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt new file mode 100644 index 00000000..7aa35635 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt @@ -0,0 +1,7 @@ +HTML.Nofollow +TYPE: bool +VERSION: 4.3.0 +DEFAULT: FALSE +--DESCRIPTION-- +If enabled, nofollow rel attributes are added to all outgoing links. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt new file mode 100644 index 00000000..2d2fbd11 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt @@ -0,0 +1,12 @@ +HTML.Parent +TYPE: string +VERSION: 1.3.0 +DEFAULT: 'div' +--DESCRIPTION-- + +

    + String name of element that HTML fragment passed to library will be + inserted in. An interesting variation would be using span as the + parent element, meaning that only inline tags would be allowed. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt new file mode 100644 index 00000000..b3c45e19 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt @@ -0,0 +1,12 @@ +HTML.Proprietary +TYPE: bool +VERSION: 3.1.0 +DEFAULT: false +--DESCRIPTION-- +

    + Whether or not to allow proprietary elements and attributes in your + documents, as per HTMLPurifier_HTMLModule_Proprietary. + Warning: This can cause your documents to stop + validating! +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt new file mode 100644 index 00000000..556fa674 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt @@ -0,0 +1,13 @@ +HTML.SafeEmbed +TYPE: bool +VERSION: 3.1.1 +DEFAULT: false +--DESCRIPTION-- +

    + Whether or not to permit embed tags in documents, with a number of extra + security features added to prevent script execution. This is similar to + what websites like MySpace do to embed tags. Embed is a proprietary + element and will cause your website to stop validating; you should + see if you can use %Output.FlashCompat with %HTML.SafeObject instead + first.

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt new file mode 100644 index 00000000..295a8cf6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt @@ -0,0 +1,13 @@ +HTML.SafeIframe +TYPE: bool +VERSION: 4.4.0 +DEFAULT: false +--DESCRIPTION-- +

    + Whether or not to permit iframe tags in untrusted documents. This + directive must be accompanied by a whitelist of permitted iframes, + such as %URI.SafeIframeRegexp, otherwise it will fatally error. + This directive has no effect on strict doctypes, as iframes are not + valid. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt new file mode 100644 index 00000000..07f6e536 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt @@ -0,0 +1,13 @@ +HTML.SafeObject +TYPE: bool +VERSION: 3.1.1 +DEFAULT: false +--DESCRIPTION-- +

    + Whether or not to permit object tags in documents, with a number of extra + security features added to prevent script execution. This is similar to + what websites like MySpace do to object tags. You should also enable + %Output.FlashCompat in order to generate Internet Explorer + compatibility code for your object tags. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt new file mode 100644 index 00000000..641b4a8d --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt @@ -0,0 +1,10 @@ +HTML.SafeScripting +TYPE: lookup +VERSION: 4.5.0 +DEFAULT: array() +--DESCRIPTION-- +

    + Whether or not to permit script tags to external scripts in documents. + Inline scripting is not allowed, and the script must match an explicit whitelist. +

    +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt new file mode 100644 index 00000000..d99663a5 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt @@ -0,0 +1,9 @@ +HTML.Strict +TYPE: bool +VERSION: 1.3.0 +DEFAULT: false +DEPRECATED-VERSION: 1.7.0 +DEPRECATED-USE: HTML.Doctype +--DESCRIPTION-- +Determines whether or not to use Transitional (loose) or Strict rulesets. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt new file mode 100644 index 00000000..d65f0d04 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt @@ -0,0 +1,8 @@ +HTML.TargetBlank +TYPE: bool +VERSION: 4.4.0 +DEFAULT: FALSE +--DESCRIPTION-- +If enabled, target=blank attributes are added to all outgoing links. +(This includes links from an HTTPS version of a page to an HTTP version.) +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoopener.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoopener.txt new file mode 100644 index 00000000..05cb3424 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoopener.txt @@ -0,0 +1,10 @@ +--# vim: et sw=4 sts=4 +HTML.TargetNoopener +TYPE: bool +VERSION: 4.8.0 +DEFAULT: TRUE +--DESCRIPTION-- +If enabled, noopener rel attributes are added to links which have +a target attribute associated with them. This prevents malicious +destinations from overwriting the original window. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt new file mode 100644 index 00000000..993a8170 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt @@ -0,0 +1,9 @@ +HTML.TargetNoreferrer +TYPE: bool +VERSION: 4.8.0 +DEFAULT: TRUE +--DESCRIPTION-- +If enabled, noreferrer rel attributes are added to links which have +a target attribute associated with them. This prevents malicious +destinations from overwriting the original window. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt new file mode 100644 index 00000000..602453f6 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt @@ -0,0 +1,8 @@ +HTML.TidyAdd +TYPE: lookup +VERSION: 2.0.0 +DEFAULT: array() +--DESCRIPTION-- + +Fixes to add to the default set of Tidy fixes as per your level. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt new file mode 100644 index 00000000..bf943e8f --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt @@ -0,0 +1,24 @@ +HTML.TidyLevel +TYPE: string +VERSION: 2.0.0 +DEFAULT: 'medium' +--DESCRIPTION-- + +

    General level of cleanliness the Tidy module should enforce. +There are four allowed values:

    +
    +
    none
    +
    No extra tidying should be done
    +
    light
    +
    Only fix elements that would be discarded otherwise due to + lack of support in doctype
    +
    medium
    +
    Enforce best practices
    +
    heavy
    +
    Transform all deprecated elements and attributes to standards + compliant equivalents
    +
    + +--ALLOWED-- +'none', 'light', 'medium', 'heavy' +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt new file mode 100644 index 00000000..92cca2a4 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt @@ -0,0 +1,8 @@ +HTML.TidyRemove +TYPE: lookup +VERSION: 2.0.0 +DEFAULT: array() +--DESCRIPTION-- + +Fixes to remove from the default set of Tidy fixes as per your level. +--# vim: et sw=4 sts=4 diff --git a/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt new file mode 100644 index 00000000..bc8e6549 --- /dev/null +++ b/protection/xss/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt @@ -0,0 +1,9 @@ +HTML.Trusted +TYPE: bool +VERSION: 2.0.0 +DEFAULT: false +--DESCRIPTION-- +Indicates whether or not the user input is trusted or not. If the input is +trusted, a more expansive set of allowed tags and attributes will be used. +See also %CSS.Trusted. +--# vim: et sw=4 sts=4 From 82a14e28aa40eb8a069da4e57f2245890026809f Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:47:57 +0700 Subject: [PATCH 27/94] change name from Token to CSRF_Token --- protection/csrf/class_csrf.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protection/csrf/class_csrf.php b/protection/csrf/class_csrf.php index 90ef70f3..521c0d35 100644 --- a/protection/csrf/class_csrf.php +++ b/protection/csrf/class_csrf.php @@ -6,7 +6,7 @@ * * session_start(); must be called before this is utilised. */ -class Token +class CSRF_Token { // Empty constructor to avoid "Constructor cannot be static" error. public function __construct() {} From c4f06025a65b7a861e5019b31a1534b4e1380fa9 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:50:53 +0700 Subject: [PATCH 28/94] Add files via upload --- profile/change_email.php | 2 +- profile/change_password.php | 2 +- profile/index.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/profile/change_email.php b/profile/change_email.php index 8a355512..20d7f3d9 100644 --- a/profile/change_email.php +++ b/profile/change_email.php @@ -36,7 +36,7 @@ if (isset($_POST['submit'])) { - if (Token::isValid() AND Token::isRecent()) + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) { $this_password = $_POST['form_password_hidden']; diff --git a/profile/change_password.php b/profile/change_password.php index 6a78a600..bf65ecd5 100644 --- a/profile/change_password.php +++ b/profile/change_password.php @@ -33,7 +33,7 @@ } if (isset($_POST['submit'])) { - if (Token::isValid() AND Token::isRecent()) + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) { if (!empty($_POST['form_old_password_hidden'])) { diff --git a/profile/index.php b/profile/index.php index 0a252408..e65481fb 100644 --- a/profile/index.php +++ b/profile/index.php @@ -35,7 +35,7 @@ } if (isset($_POST['submit'])) { - if (Token::isValid() AND Token::isRecent()) + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) { if (isset($_POST['is_author'])) $is_author = 1; else $is_author = 0; From f18b09b87b383479d2c3fd876eee2be49aa8f771 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:51:56 +0700 Subject: [PATCH 29/94] Add files via upload --- themes/default/profile/change_email.php | 135 +++++++++++++++++++++ themes/default/profile/change_password.php | 96 +++++++++++++++ themes/default/profile/index.php | 84 +++++++++++++ 3 files changed, 315 insertions(+) create mode 100644 themes/default/profile/change_email.php create mode 100644 themes/default/profile/change_password.php create mode 100644 themes/default/profile/index.php diff --git a/themes/default/profile/change_email.php b/themes/default/profile/change_email.php new file mode 100644 index 00000000..20d7f3d9 --- /dev/null +++ b/themes/default/profile/change_email.php @@ -0,0 +1,135 @@ +printInfos('INVALID_USER'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +if (isset($_POST['cancel'])) +{ + $msg->addFeedback('CANCELLED'); + Header('Location: ../index.php'); + exit; +} + +if (isset($_POST['submit'])) +{ + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $this_password = $_POST['form_password_hidden']; + + // password check + if (!empty($this_password)) + { + //check if old password entered is correct + if ($row = $_current_user->getInfo()) + { + if ($row['password'] != $this_password) + { + $msg->addError('WRONG_PASSWORD'); + Header('Location: change_email.php'); + exit; + } + } + } + else + { + $msg->addError(array('EMPTY_FIELDS', _AT('password'))); + header('Location: change_email.php'); + exit; + } + + // email check + if ($_POST['email'] == '') + { + $msg->addError(array('EMPTY_FIELDS', _AT('email'))); + } + else + { + if(!preg_match("/^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$/i", $_POST['email'])) + { + $msg->addError('EMAIL_INVALID'); + } + + $usersDAO = new UsersDAO(); + $row = $usersDAO->getUserByEmail($_POST['email']); + if ($row['user_id'] > 0 && $row['user_id'] <> $_SESSION['user_id']) + { + $msg->addError('EMAIL_EXISTS'); + } + } + + if (!$msg->containsErrors()) + { + + if (defined('TR_EMAIL_CONFIRMATION') && TR_EMAIL_CONFIRMATION) + { + //send confirmation email + $row = $_current_user->getInfo(); + + if ($row['email'] != $_POST['email']) { + $code = substr(md5($_POST['email'] . $row['creation_date'] . $_SESSION['user_id']), 0, 10); + $confirmation_link = TR_BASE_HREF . 'confirm.php?id='.$_SESSION['user_id'].SEP .'e='.urlencode($_POST['email']).SEP.'m='.$code; + + /* send the email confirmation message: */ + require(TR_INCLUDE_PATH . 'classes/phpmailer/transformablemailer.class.php'); + $mail = new TransformableMailer(); + + $mail->From = $_config['contact_email']; + $mail->AddAddress($_POST['email']); + $mail->Subject = SITE_NAME . ' - ' . _AT('email_confirmation_subject'); + $mail->Body = _AT('email_confirmation_message2', $_config['site_name'], $confirmation_link); + + $mail->Send(); + + $msg->addFeedback('CONFIRM_EMAIL'); + } else { + $msg->addFeedback('CHANGE_TO_SAME_EMAIL'); + } + } else { + + //insert into database + $_current_user->setEmail($_POST[email]); + + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + } + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +$row = $_current_user->getInfo(); + +if (!isset($_POST['submit'])) { + $_POST = $row; +} + +/* template starts here */ +$savant->assign('row', $row); +$savant->display('profile/change_email.tmpl.php'); + +?> diff --git a/themes/default/profile/change_password.php b/themes/default/profile/change_password.php new file mode 100644 index 00000000..bf65ecd5 --- /dev/null +++ b/themes/default/profile/change_password.php @@ -0,0 +1,96 @@ +printInfos('INVALID_USER'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + Header('Location: ../index.php'); + exit; +} + +if (isset($_POST['submit'])) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + if (!empty($_POST['form_old_password_hidden'])) + { + //check if old password entered is correct + if ($row = $_current_user->getInfo()) + { + if ($row['password'] != $purifier->purify($_POST['form_old_password_hidden'])) + { + $msg->addError('WRONG_PASSWORD'); + Header('Location: change_password.php'); + exit; + } + } + } + else + { + $msg->addError(array('EMPTY_FIELDS', _AT('password'))); + header('Location: change_password.php'); + exit; + } + + /* password check: password is verified front end by javascript. here is to handle the errors from javascript */ + if ($_POST['password_error'] <> "") + { + $pwd_errors = explode(",", $_POST['password_error']); + + foreach ($pwd_errors as $pwd_error) + { + if ($pwd_error == "missing_password") + $missing_fields[] = _AT('password'); + else + $msg->addError($pwd_error); + } + } + + if (!$msg->containsErrors()) { + + // insert into the db. + $password = $purifier->purify($_POST['form_password_hidden']); + + if (!$_current_user->setPassword($password)) + { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('DB_NOT_UPDATED'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + + $msg->addFeedback('PASSWORD_CHANGED'); + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +/* template starts here */ +$savant->display('profile/change_password.tmpl.php'); + +?> diff --git a/themes/default/profile/index.php b/themes/default/profile/index.php new file mode 100644 index 00000000..e65481fb --- /dev/null +++ b/themes/default/profile/index.php @@ -0,0 +1,84 @@ +printInfos('INVALID_USER'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + Header('Location: ../index.php'); + exit; +} + +if (isset($_POST['submit'])) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + if (isset($_POST['is_author'])) $is_author = 1; + else $is_author = 0; + + $usersDAO = new UsersDAO(); + $user_row = $usersDAO->getUserByID($_SESSION['user_id']); + + if ($usersDAO->Update($_SESSION['user_id'], + $user_row['user_group_id'], + $user_row['login'], + $user_row['email'], + $_POST['first_name'], + $_POST['last_name'], + $is_author, + $_POST['organization'], + $_POST['phone'], + $_POST['address'], + $_POST['city'], + $_POST['province'], + $_POST['country'], + $_POST['postal_code'], + $_POST['status'])) + + { + $msg->addFeedback('PROFILE_UPDATED'); + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +$row = $_current_user->getInfo(); + +if (!isset($_POST['submit'])) { + $_POST = $row; +} + +/* template starts here */ +$savant->assign('row', $row); + +global $onload; +$onload = 'document.form.first_name.focus();'; + +$savant->display('profile/index.tmpl.php'); +?> From e03ceba69f8e7e596fc2d416d0c2ca7eba645d91 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:54:42 +0700 Subject: [PATCH 30/94] Add files via upload --- tests/create_question_likert.php | 259 ++++++++++++------------ tests/create_question_long.php | 147 +++++++------- tests/create_question_matching.php | 223 +++++++++++---------- tests/create_question_matchingdd.php | 227 +++++++++++---------- tests/create_question_multianswer.php | 273 ++++++++++++++------------ tests/create_question_multichoice.php | 195 +++++++++--------- tests/create_question_ordering.php | 246 ++++++++++++----------- tests/create_question_truefalse.php | 137 +++++++------ tests/create_test.php | 115 ++++++----- tests/preview.php | 193 +++++++++--------- tests/question_cats_manage.php | 20 +- 11 files changed, 1085 insertions(+), 950 deletions(-) diff --git a/tests/create_question_likert.php b/tests/create_question_likert.php index fc9e6f14..f3d9b5cf 100644 --- a/tests/create_question_likert.php +++ b/tests/create_question_likert.php @@ -1,123 +1,136 @@ -addFeedback('CANCELLED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} else if (isset($_POST['submit'])) { - $_POST['question'] = trim($_POST['question']); - $_POST['category_id'] = intval($_POST['category_id']); - - $empty_fields = array(); - if ($_POST['question'] == ''){ - $empty_fields[] = _AT('question'); - } - if ($_POST['choice'][0] == '') { - $empty_fields[] = _AT('choice').' 1'; - } - - if ($_POST['choice'][1] == '') { - $empty_fields[] = _AT('choice').' 2'; - } - - if (!empty($empty_fields)) { - $msg->addError(array('EMPTY_FIELDS', implode(', ', $empty_fields))); - } - - if (!$msg->containsErrors()) { - $_POST['feedback'] = ''; - $_POST['question'] = htmlspecialchars($_POST['question'], ENT_QUOTES); - - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = trim(htmlspecialchars($_POST['choice'][$i], ENT_QUOTES)); - $_POST['answer'][$i] = intval($_POST['answer'][$i]); - - if ($_POST['choice'][$i] == '') { - /* an empty option can't be correct */ - $_POST['answer'][$i] = 0; - } - } - $values= array($_POST['category_id'], - $_course_id, - $_POST['feedback'], - $_POST['question'], - $_POST['choice'][0], - $_POST['choice'][1], - $_POST['choice'][2], - $_POST['choice'][3], - $_POST['choice'][4], - $_POST['choice'][5], - $_POST['choice'][6], - $_POST['choice'][7], - $_POST['choice'][8], - $_POST['choice'][9], - $_POST['answer'][0], - $_POST['answer'][1], - $_POST['answer'][2], - $_POST['answer'][3], - $_POST['answer'][4], - $_POST['answer'][5], - $_POST['answer'][6], - $_POST['answer'][7], - $_POST['answer'][8], - $_POST['answer'][9]); - $types = "iissssssssssssiiiiiiiiii"; - $sql = TR_SQL_QUESTION_LIKERT; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; - } - else { - $msg->addError('DB_NOT_UPDATED'); - } - } -} else if (isset($_POST['preset'])) { - // load preset - $_POST['preset_num'] = intval($_POST['preset_num']); - - if (isset($_likert_preset[$_POST['preset_num']])) { - $_POST['choice'] = $_likert_preset[$_POST['preset_num']]; - } else if ($_POST['preset_num']) { - $row = $testsQuestionsDAO->get($_POST[preset_num]); - if (isset($row)) { - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = $row['choice_' . $i]; - } - } - } -} - -global $onload; -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('likert_preset', $_likert_preset); -$savant->assign('testsQuestionsDAO', $testsQuestionsDAO); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_likert.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} else if (isset($_POST['submit'])) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + + $empty_fields = array(); + if ($_POST['question'] == ''){ + $empty_fields[] = _AT('question'); + } + if ($_POST['choice'][0] == '') { + $empty_fields[] = _AT('choice').' 1'; + } + + if ($_POST['choice'][1] == '') { + $empty_fields[] = _AT('choice').' 2'; + } + + if (!empty($empty_fields)) { + $msg->addError(array('EMPTY_FIELDS', implode(', ', $empty_fields))); + } + + if (!$msg->containsErrors()) { + $_POST['feedback'] = ''; + $_POST['question'] = $purifier->purify(htmlspecialchars($_POST['question'], ENT_QUOTES)); + + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $purifier->purify(trim(htmlspecialchars($_POST['choice'][$i], ENT_QUOTES))); + $_POST['answer'][$i] = intval($_POST['answer'][$i]); + + if ($_POST['choice'][$i] == '') { + /* an empty option can't be correct */ + $_POST['answer'][$i] = 0; + } + } + $values= array($_POST['category_id'], + $_course_id, + $_POST['feedback'], + $_POST['question'], + $_POST['choice'][0], + $_POST['choice'][1], + $_POST['choice'][2], + $_POST['choice'][3], + $_POST['choice'][4], + $_POST['choice'][5], + $_POST['choice'][6], + $_POST['choice'][7], + $_POST['choice'][8], + $_POST['choice'][9], + $_POST['answer'][0], + $_POST['answer'][1], + $_POST['answer'][2], + $_POST['answer'][3], + $_POST['answer'][4], + $_POST['answer'][5], + $_POST['answer'][6], + $_POST['answer'][7], + $_POST['answer'][8], + $_POST['answer'][9]); + $types = "iissssssssssssiiiiiiiiii"; + $sql = TR_SQL_QUESTION_LIKERT; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; + } + else { + $msg->addError('DB_NOT_UPDATED'); + } + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} else if (isset($_POST['preset'])) { + // load preset + $_POST['preset_num'] = intval($_POST['preset_num']); + + if (isset($_likert_preset[$_POST['preset_num']])) { + $_POST['choice'] = $_likert_preset[$_POST['preset_num']]; + } else if ($_POST['preset_num']) { + $row = $testsQuestionsDAO->get($_POST[preset_num]); + if (isset($row)) { + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $row['choice_' . $i]; + } + } + } +} + +global $onload; +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('likert_preset', $_likert_preset); +$savant->assign('testsQuestionsDAO', $testsQuestionsDAO); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_likert.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/create_question_long.php b/tests/create_question_long.php index cd94c078..f52a0927 100644 --- a/tests/create_question_long.php +++ b/tests/create_question_long.php @@ -1,67 +1,80 @@ -addFeedback('CANCELLED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} else if ($_POST['submit']) { - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['question'] = trim($_POST['question']); - $_POST['category_id'] = intval($_POST['category_id']); - $_POST['properties'] = intval($_POST['properties']); - - if ($_POST['question'] == ''){ - $msg->addError(array('EMPTY_FIELDS', _AT('question'))); - } - - if (!$msg->containsErrors()) { - - $values = array($_POST['category_id'], - $_course_id, - $_POST['feedback'], - $_POST['question'], - $_POST['properties']); - $types = "iissi"; - $sql = TR_SQL_QUESTION_LONG; - - if ($testsQuestionsDAO->execute($sql, $values, $types)) - { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; - } - } -} - -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -if (!isset($_POST['properties'])) { - $_POST['properties'] = 1; -} - -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_long.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} else if ($_POST['submit']) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + $_POST['properties'] = intval($_POST['properties']); + + if ($_POST['question'] == ''){ + $msg->addError(array('EMPTY_FIELDS', _AT('question'))); + } + + if (!$msg->containsErrors()) { + + $values = array($_POST['category_id'], + $_course_id, + $_POST['feedback'], + $_POST['question'], + $_POST['properties']); + $types = "iissi"; + $sql = TR_SQL_QUESTION_LONG; + + if ($testsQuestionsDAO->execute($sql, $values, $types)) + { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; + } + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +if (!isset($_POST['properties'])) { + $_POST['properties'] = 1; +} + +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_long.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); +?> diff --git a/tests/create_question_matching.php b/tests/create_question_matching.php index 0f40b0ca..bc56dff8 100644 --- a/tests/create_question_matching.php +++ b/tests/create_question_matching.php @@ -1,105 +1,118 @@ -addFeedback('CANCELLED'); - header('Location: question_db.php'); - exit; -} else if ($_POST['submit']) { - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['instructions'] = trim($_POST['instructions']); - $_POST['category_id'] = intval($_POST['category_id']); - - for ($i = 0 ; $i < 10; $i++) { - $_POST['question'][$i] = trim($_POST['question'][$i]); - $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i]; - $_POST['answer'][$i] = trim($_POST['answer'][$i]); - } - - if (!$_POST['question'][0] - || !$_POST['question'][1] - || !$_POST['answer'][0] - || !$_POST['answer'][1]) { - - $msg->addError('QUESTION_EMPTY'); - } - - - if (!$msg->containsErrors()) { - $values = array($_POST['category_id'], - $_course_id, - $_POST['feedback'], - $_POST['instructions'], - $_POST['question'][0], - $_POST['question'][1], - $_POST['question'][2], - $_POST['question'][3], - $_POST['question'][4], - $_POST['question'][5], - $_POST['question'][6], - $_POST['question'][7], - $_POST['question'][8], - $_POST['question'][9], - $_POST['question_answer'][0], - $_POST['question_answer'][1], - $_POST['question_answer'][2], - $_POST['question_answer'][3], - $_POST['question_answer'][4], - $_POST['question_answer'][5], - $_POST['question_answer'][6], - $_POST['question_answer'][7], - $_POST['question_answer'][8], - $_POST['question_answer'][9], - $_POST['answer'][0], - $_POST['answer'][1], - $_POST['answer'][2], - $_POST['answer'][3], - $_POST['answer'][4], - $_POST['answer'][5], - $_POST['answer'][6], - $_POST['answer'][7], - $_POST['answer'][8], - $_POST['answer'][9] - ); - $types = "iissssssssssssiiiiiiiiiissssssssss"; - $sql = TR_SQL_QUESTION_MATCHING; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; - } - } -} - -// for matching test questions -$_letters = array(_AT('a'), _AT('b'), _AT('c'), _AT('d'), _AT('e'), _AT('f'), _AT('g'), _AT('h'), _AT('i'), _AT('j')); - -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('letters', $_letters); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_matching.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: question_db.php'); + exit; +} else if ($_POST['submit']) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['instructions'] = $purifier->purify(trim($_POST['instructions'])); + $_POST['category_id'] = intval($_POST['category_id']); + + for ($i = 0 ; $i < 10; $i++) { + $_POST['question'][$i] = $purifier->purify(trim($_POST['question'][$i])); + $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i]; + $_POST['answer'][$i] = $purifier->purify(trim($_POST['answer'][$i])); + } + + if (!$_POST['question'][0] + || !$_POST['question'][1] + || !$_POST['answer'][0] + || !$_POST['answer'][1]) { + + $msg->addError('QUESTION_EMPTY'); + } + + + if (!$msg->containsErrors()) { + $values = array($_POST['category_id'], + $_course_id, + $_POST['feedback'], + $_POST['instructions'], + $_POST['question'][0], + $_POST['question'][1], + $_POST['question'][2], + $_POST['question'][3], + $_POST['question'][4], + $_POST['question'][5], + $_POST['question'][6], + $_POST['question'][7], + $_POST['question'][8], + $_POST['question'][9], + $_POST['question_answer'][0], + $_POST['question_answer'][1], + $_POST['question_answer'][2], + $_POST['question_answer'][3], + $_POST['question_answer'][4], + $_POST['question_answer'][5], + $_POST['question_answer'][6], + $_POST['question_answer'][7], + $_POST['question_answer'][8], + $_POST['question_answer'][9], + $_POST['answer'][0], + $_POST['answer'][1], + $_POST['answer'][2], + $_POST['answer'][3], + $_POST['answer'][4], + $_POST['answer'][5], + $_POST['answer'][6], + $_POST['answer'][7], + $_POST['answer'][8], + $_POST['answer'][9] + ); + $types = "iissssssssssssiiiiiiiiiissssssssss"; + $sql = TR_SQL_QUESTION_MATCHING; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; + } + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +// for matching test questions +$_letters = array(_AT('a'), _AT('b'), _AT('c'), _AT('d'), _AT('e'), _AT('f'), _AT('g'), _AT('h'), _AT('i'), _AT('j')); + +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('letters', $_letters); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_matching.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/create_question_matchingdd.php b/tests/create_question_matchingdd.php index 91727a1a..3e28e2a5 100644 --- a/tests/create_question_matchingdd.php +++ b/tests/create_question_matchingdd.php @@ -1,107 +1,120 @@ -addFeedback('CANCELLED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} else if ($_POST['submit']) { - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['instructions'] = trim($_POST['instructions']); - $_POST['category_id'] = intval($_POST['category_id']); - - for ($i = 0 ; $i < 10; $i++) { - $_POST['question'][$i] = trim($_POST['question'][$i]); - $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i]; - $_POST['answer'][$i] = trim($_POST['answer'][$i]); - } - - if (!$_POST['question'][0] - || !$_POST['question'][1] - || !$_POST['answer'][0] - || !$_POST['answer'][1]) { - - $msg->addError('QUESTION_EMPTY'); - } - - - if (!$msg->containsErrors()) { - - $values = array($_POST['category_id'], - $_course_id, - $_POST['feedback'], - $_POST['instructions'], - $_POST['question'][0], - $_POST['question'][1], - $_POST['question'][2], - $_POST['question'][3], - $_POST['question'][4], - $_POST['question'][5], - $_POST['question'][6], - $_POST['question'][7], - $_POST['question'][8], - $_POST['question'][9], - $_POST['question_answer'][0], - $_POST['question_answer'][1], - $_POST['question_answer'][2], - $_POST['question_answer'][3], - $_POST['question_answer'][4], - $_POST['question_answer'][5], - $_POST['question_answer'][6], - $_POST['question_answer'][7], - $_POST['question_answer'][8], - $_POST['question_answer'][9], - $_POST['answer'][0], - $_POST['answer'][1], - $_POST['answer'][2], - $_POST['answer'][3], - $_POST['answer'][4], - $_POST['answer'][5], - $_POST['answer'][6], - $_POST['answer'][7], - $_POST['answer'][8], - $_POST['answer'][9] - ); - $types = "iissssssssssssiiiiiiiiiissssssssss"; - $sql = TR_SQL_QUESTION_MATCHINGDD; - - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; - } - } -} - -// for matching test questions -$_letters = array(_AT('a'), _AT('b'), _AT('c'), _AT('d'), _AT('e'), _AT('f'), _AT('g'), _AT('h'), _AT('i'), _AT('j')); - -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('letters', $_letters); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_matchingdd.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} else if ($_POST['submit']) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['instructions'] = $purifier->purify(trim($_POST['instructions'])); + $_POST['category_id'] = intval($_POST['category_id']); + + for ($i = 0 ; $i < 10; $i++) { + $_POST['question'][$i] = $purifier->purify(trim($_POST['question'][$i])); + $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i]; + $_POST['answer'][$i] = $purifier->purify(trim($_POST['answer'][$i])); + } + + if (!$_POST['question'][0] + || !$_POST['question'][1] + || !$_POST['answer'][0] + || !$_POST['answer'][1]) { + + $msg->addError('QUESTION_EMPTY'); + } + + + if (!$msg->containsErrors()) { + + $values = array($_POST['category_id'], + $_course_id, + $_POST['feedback'], + $_POST['instructions'], + $_POST['question'][0], + $_POST['question'][1], + $_POST['question'][2], + $_POST['question'][3], + $_POST['question'][4], + $_POST['question'][5], + $_POST['question'][6], + $_POST['question'][7], + $_POST['question'][8], + $_POST['question'][9], + $_POST['question_answer'][0], + $_POST['question_answer'][1], + $_POST['question_answer'][2], + $_POST['question_answer'][3], + $_POST['question_answer'][4], + $_POST['question_answer'][5], + $_POST['question_answer'][6], + $_POST['question_answer'][7], + $_POST['question_answer'][8], + $_POST['question_answer'][9], + $_POST['answer'][0], + $_POST['answer'][1], + $_POST['answer'][2], + $_POST['answer'][3], + $_POST['answer'][4], + $_POST['answer'][5], + $_POST['answer'][6], + $_POST['answer'][7], + $_POST['answer'][8], + $_POST['answer'][9] + ); + $types = "iissssssssssssiiiiiiiiiissssssssss"; + $sql = TR_SQL_QUESTION_MATCHINGDD; + + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; + } + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +// for matching test questions +$_letters = array(_AT('a'), _AT('b'), _AT('c'), _AT('d'), _AT('e'), _AT('f'), _AT('g'), _AT('h'), _AT('i'), _AT('j')); + +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('letters', $_letters); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_matchingdd.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/create_question_multianswer.php b/tests/create_question_multianswer.php index 887a6de4..c5e4d251 100644 --- a/tests/create_question_multianswer.php +++ b/tests/create_question_multianswer.php @@ -1,130 +1,143 @@ -addFeedback('CANCELLED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} else if ($_POST['submit'] || $_POST['submit_yes']) { - $_POST['required'] = intval($_POST['required']); - $_POST['feedback'] = trim(htmlspecialchars($_POST['feedback'], ENT_QUOTES)); - $_POST['question'] = trim(htmlspecialchars($_POST['question'], ENT_QUOTES)); - $_POST['category_id'] = intval($_POST['category_id']); - - if ($_POST['question'] == ''){ - $msg->addError(array('EMPTY_FIELDS', _AT('question'))); - } - - if (!$msg->containsErrors()) { - $choice_new = array(); // stores the non-blank choices - $answer_new = array(); // stores the associated "answer" for the choices - for ($i=0; $i<10; $i++) { - /** - * Db defined it to be 255 length, chop strings off it it's less than that - * @harris - */ - $_POST['choice'][$i] = Utility::validateLength($_POST['choice'][$i], 255); - $_POST['choice'][$i] = trim(htmlspecialchars($_POST['choice'][$i], ENT_QUOTES)); - $_POST['answer'][$i] = intval($_POST['answer'][$i]); - - if ($_POST['choice'][$i] == '') { - /* an empty option can't be correct */ - $_POST['answer'][$i] = 0; - } else { - /* filter out empty choices/ remove gaps */ - $choice_new[] = $_POST['choice'][$i]; - $answer_new[] = $_POST['answer'][$i]; - - if ($_POST['answer'][$i] != 0) - $has_answer = TRUE; - } - } - - if ($has_answer != TRUE && !$_POST['submit_yes']) { - - $hidden_vars['required'] = htmlspecialchars($_POST['required'], ENT_QUOTES); - $hidden_vars['feedback'] = htmlspecialchars($_POST['feedback'], ENT_QUOTES); - $hidden_vars['question'] = htmlspecialchars($_POST['question'], ENT_QUOTES); - $hidden_vars['category_id'] = intval($_POST['category_id']); - $hidden_vars['_course_id'] = $_course_id; - - for ($i = 0; $i < count($choice_new); $i++) { - $hidden_vars['answer['.$i.']'] = htmlspecialchars($answer_new[$i], ENT_QUOTES); - $hidden_vars['choice['.$i.']'] = htmlspecialchars($choice_new[$i], ENT_QUOTES); - } - - $msg->addConfirm('NO_ANSWER', $hidden_vars); - } else { - - $_POST['answer'] = $answer_new; - $_POST['choice'] = $choice_new; - $_POST['answer'] = array_pad($_POST['answer'], 10, 0); - $_POST['choice'] = array_pad($_POST['choice'], 10, ''); - - $values = array( $_POST['category_id'], - $_course_id, - $_POST['feedback'], - $_POST['question'], - $_POST['choice'][0], - $_POST['choice'][1], - $_POST['choice'][2], - $_POST['choice'][3], - $_POST['choice'][4], - $_POST['choice'][5], - $_POST['choice'][6], - $_POST['choice'][7], - $_POST['choice'][8], - $_POST['choice'][9], - $_POST['answer'][0], - $_POST['answer'][1], - $_POST['answer'][2], - $_POST['answer'][3], - $_POST['answer'][4], - $_POST['answer'][5], - $_POST['answer'][6], - $_POST['answer'][7], - $_POST['answer'][8], - $_POST['answer'][9]); - $types = "iissssssssssssiiiiiiiiii"; - $sql = TR_SQL_QUESTION_MULTIANSWER; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; - } - } - } -} - -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$msg->printConfirm(); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_multianswer.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} else if ($_POST['submit'] || $_POST['submit_yes']) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['required'] = intval($_POST['required']); + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + + if ($_POST['question'] == ''){ + $msg->addError(array('EMPTY_FIELDS', _AT('question'))); + } + + if (!$msg->containsErrors()) { + $choice_new = array(); // stores the non-blank choices + $answer_new = array(); // stores the associated "answer" for the choices + for ($i=0; $i<10; $i++) { + /** + * Db defined it to be 255 length, chop strings off it it's less than that + * @harris + */ + $_POST['choice'][$i] = Utility::validateLength($_POST['choice'][$i], 255); + $_POST['choice'][$i] = $purifier->purify(trim($_POST['choice'][$i])); + $_POST['answer'][$i] = intval($_POST['answer'][$i]); + + if ($_POST['choice'][$i] == '') { + /* an empty option can't be correct */ + $_POST['answer'][$i] = 0; + } else { + /* filter out empty choices/ remove gaps */ + $choice_new[] = $purifier->purify($_POST['choice'][$i]); + $answer_new[] = $purifier->purify($_POST['answer'][$i]); + + if ($_POST['answer'][$i] != 0) + $has_answer = TRUE; + } + } + + if ($has_answer != TRUE && !$_POST['submit_yes']) { + + $hidden_vars['required'] = $purifier->purify(trim($_POST['required'])); + $hidden_vars['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $hidden_vars['question'] = $purifier->purify(trim($_POST['question'])); + $hidden_vars['category_id'] = intval($_POST['category_id']); + $hidden_vars['_course_id'] = $_course_id; + + for ($i = 0; $i < count($choice_new); $i++) { + $hidden_vars['answer['.$i.']'] = $purifier->purify($answer_new[$i]); + $hidden_vars['choice['.$i.']'] = $purifier->purify($choice_new[$i]); + } + + $msg->addConfirm('NO_ANSWER', $hidden_vars); + } else { + + $_POST['answer'] = $answer_new; + $_POST['choice'] = $choice_new; + $_POST['answer'] = array_pad($_POST['answer'], 10, 0); + $_POST['choice'] = array_pad($_POST['choice'], 10, ''); + + $values = array( $_POST['category_id'], + $_course_id, + $_POST['feedback'], + $_POST['question'], + $_POST['choice'][0], + $_POST['choice'][1], + $_POST['choice'][2], + $_POST['choice'][3], + $_POST['choice'][4], + $_POST['choice'][5], + $_POST['choice'][6], + $_POST['choice'][7], + $_POST['choice'][8], + $_POST['choice'][9], + $_POST['answer'][0], + $_POST['answer'][1], + $_POST['answer'][2], + $_POST['answer'][3], + $_POST['answer'][4], + $_POST['answer'][5], + $_POST['answer'][6], + $_POST['answer'][7], + $_POST['answer'][8], + $_POST['answer'][9]); + $types = "iissssssssssssiiiiiiiiii"; + $sql = TR_SQL_QUESTION_MULTIANSWER; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; + } + } + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$msg->printConfirm(); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_multianswer.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/create_question_multichoice.php b/tests/create_question_multichoice.php index 9a6673b2..b74daa69 100644 --- a/tests/create_question_multichoice.php +++ b/tests/create_question_multichoice.php @@ -1,91 +1,104 @@ -addFeedback('CANCELLED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} else if (isset($_POST['submit'])) { - $_POST['required'] = intval($_POST['required']); - $_POST['feedback'] = trim(htmlspecialchars($_POST['feedback'], ENT_QUOTES)); - $_POST['question'] = trim(htmlspecialchars($_POST['question'], ENT_QUOTES)); - $_POST['category_id'] = intval($_POST['category_id']); - $_POST['answer'] = intval($_POST['answer']); - - if ($_POST['question'] == ''){ - $msg->addError(array('EMPTY_FIELDS', _AT('question'))); - } - - if (!$msg->containsErrors()) { - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = trim(htmlspecialchars($_POST['choice'][$i], ENT_QUOTES)); - } - - $answers = array_fill(0, 10, 0); - $answers[$_POST['answer']] = 1; - $values = array($_POST['category_id'], - $_course_id, - $_POST['feedback'], - $_POST['question'], - $_POST['choice'][0], - $_POST['choice'][1], - $_POST['choice'][2], - $_POST['choice'][3], - $_POST['choice'][4], - $_POST['choice'][5], - $_POST['choice'][6], - $_POST['choice'][7], - $_POST['choice'][8], - $_POST['choice'][9], - $answers[0], - $answers[1], - $answers[2], - $answers[3], - $answers[4], - $answers[5], - $answers[6], - $answers[7], - $answers[8], - $answers[9]); - $types = "iissssssssssssiiiiiiiiii"; - $sql = TR_SQL_QUESTION_MULTI; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; - } - } -} else { - $_POST['answer'] = 0; -} - -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$msg->printConfirm(); - -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_multichoice.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} else if (isset($_POST['submit'])) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['required'] = intval($_POST['required']); + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + $_POST['answer'] = intval($_POST['answer']); + + if ($_POST['question'] == ''){ + $msg->addError(array('EMPTY_FIELDS', _AT('question'))); + } + + if (!$msg->containsErrors()) { + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $purifier->purify(trim($_POST['choice'][$i])); + } + + $answers = array_fill(0, 10, 0); + $answers[$_POST['answer']] = 1; + $values = array($_POST['category_id'], + $_course_id, + $_POST['feedback'], + $_POST['question'], + $_POST['choice'][0], + $_POST['choice'][1], + $_POST['choice'][2], + $_POST['choice'][3], + $_POST['choice'][4], + $_POST['choice'][5], + $_POST['choice'][6], + $_POST['choice'][7], + $_POST['choice'][8], + $_POST['choice'][9], + $answers[0], + $answers[1], + $answers[2], + $answers[3], + $answers[4], + $answers[5], + $answers[6], + $answers[7], + $answers[8], + $answers[9]); + $types = "iissssssssssssiiiiiiiiii"; + $sql = TR_SQL_QUESTION_MULTI; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; + } + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} else { + $_POST['answer'] = 0; +} + +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$msg->printConfirm(); + +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_multichoice.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/create_question_ordering.php b/tests/create_question_ordering.php index 2d78211d..72e340eb 100644 --- a/tests/create_question_ordering.php +++ b/tests/create_question_ordering.php @@ -1,116 +1,130 @@ -addFeedback('CANCELLED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} else if ($_POST['submit']) { - $missing_fields = array(); - - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['question'] = trim($_POST['question']); - $_POST['category_id'] = intval($_POST['category_id']); - - if ($_POST['question'] == ''){ - $missing_fields[] = _AT('question'); - } - - if (trim($_POST['choice'][0]) == '') { - $missing_fields[] = _AT('item').' 1'; - } - if (trim($_POST['choice'][1]) == '') { - $missing_fields[] = _AT('item').' 2'; - } - - if ($missing_fields) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } - - if (!$msg->containsErrors()) { - $choice_new = array(); // stores the non-blank choices - $answer_new = array(); // stores the non-blank answers - $order = 0; // order count - for ($i=0; $i<10; $i++) { - /** - * Db defined it to be 255 length, chop strings off it it's less than that - * @harris - */ - $_POST['choice'][$i] = Utility::validateLength($_POST['choice'][$i], 255); - $_POST['choice'][$i] = trim($_POST['choice'][$i]); - - if ($_POST['choice'][$i] != '') { - /* filter out empty choices/ remove gaps */ - $choice_new[] = $_POST['choice'][$i]; - $answer_new[] = $order++; - } - } - - $_POST['choice'] = array_pad($choice_new, 10, ''); - $answer_new = array_pad($answer_new, 10, 0); - - $values = array($_POST['category_id'], - $_course_id, - $_POST['feedback'], - $_POST['question'], - $_POST['choice'][0], - $_POST['choice'][1], - $_POST['choice'][2], - $_POST['choice'][3], - $_POST['choice'][4], - $_POST['choice'][5], - $_POST['choice'][6], - $_POST['choice'][7], - $_POST['choice'][8], - $_POST['choice'][9], - $answer_new[0], - $answer_new[1], - $answer_new[2], - $answer_new[3], - $answer_new[4], - $answer_new[5], - $answer_new[6], - $answer_new[7], - $answer_new[8], - $answer_new[9]); - $types = "iissssssssssssiiiiiiiiii"; - $sql = TR_SQL_QUESTION_ORDERING; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; - } - else - $msg->addError('DB_NOT_UPDATED'); - } -} - -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_ordering.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} else if ($_POST['submit']) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $missing_fields = array(); + + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + + if ($_POST['question'] == ''){ + $missing_fields[] = _AT('question'); + } + + if (trim($_POST['choice'][0]) == '') { + $missing_fields[] = _AT('item').' 1'; + } + if (trim($_POST['choice'][1]) == '') { + $missing_fields[] = _AT('item').' 2'; + } + + if ($missing_fields) { + $missing_fields = implode(', ', $missing_fields); + $msg->addError(array('EMPTY_FIELDS', $missing_fields)); + } + + if (!$msg->containsErrors()) { + $choice_new = array(); // stores the non-blank choices + $answer_new = array(); // stores the non-blank answers + $order = 0; // order count + for ($i=0; $i<10; $i++) { + /** + * Db defined it to be 255 length, chop strings off it it's less than that + + * @harris + */ + $_POST['choice'][$i] = Utility::validateLength($_POST['choice'][$i], 255); + $_POST['choice'][$i] = $purifier->purify(trim($_POST['choice'][$i])); + + if ($_POST['choice'][$i] != '') { + /* filter out empty choices/ remove gaps */ + $choice_new[] = $purifier->purify($_POST['choice'][$i]); + $answer_new[] = $order++; + } + } + + $_POST['choice'] = array_pad($choice_new, 10, ''); + $answer_new = array_pad($answer_new, 10, 0); + + $values = array($_POST['category_id'], + $_course_id, + $_POST['feedback'], + $_POST['question'], + $_POST['choice'][0], + $_POST['choice'][1], + $_POST['choice'][2], + $_POST['choice'][3], + $_POST['choice'][4], + $_POST['choice'][5], + $_POST['choice'][6], + $_POST['choice'][7], + $_POST['choice'][8], + $_POST['choice'][9], + $answer_new[0], + $answer_new[1], + $answer_new[2], + $answer_new[3], + $answer_new[4], + $answer_new[5], + $answer_new[6], + $answer_new[7], + $answer_new[8], + $answer_new[9]); + $types = "iissssssssssssiiiiiiiiii"; + $sql = TR_SQL_QUESTION_ORDERING; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; + } + else + $msg->addError('DB_NOT_UPDATED'); + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_ordering.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/create_question_truefalse.php b/tests/create_question_truefalse.php index 776d9278..af6c09c9 100644 --- a/tests/create_question_truefalse.php +++ b/tests/create_question_truefalse.php @@ -1,62 +1,75 @@ -addFeedback('CANCELLED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} else if ($_POST['submit']) { - $_POST['required'] = 1; //intval($_POST['required']); - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['question'] = trim($_POST['question']); - $_POST['category_id'] = intval($_POST['category_id']); - $_POST['answer'] = intval($_POST['answer']); - - if ($_POST['question'] == ''){ - $msg->addError(array('EMPTY_FIELDS', _AT('statement'))); - } - - if (!$msg->containsErrors()) { - $sql = TR_SQL_QUESTION_TRUEFALSE; - $values = array($_POST['category_id'], - $_course_id, - $_POST['feedback'], - $_POST['question'], - $_POST['answer']); - $types = "iisss"; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: question_db.php?_course_id='.$_course_id); - } - else - $msg->addError('DB_NOT_UPDATED'); - } -} - -$onload = 'document.form.category_id.focus();'; -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_truefalse.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} else if ($_POST['submit']) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['required'] = 1; //intval($_POST['required']); + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + $_POST['answer'] = intval($_POST['answer']); + + if ($_POST['question'] == ''){ + $msg->addError(array('EMPTY_FIELDS', _AT('statement'))); + } + + if (!$msg->containsErrors()) { + $sql = TR_SQL_QUESTION_TRUEFALSE; + $values = array($_POST['category_id'], + $_course_id, + $_POST['feedback'], + $_POST['question'], + $_POST['answer']); + $types = "iisss"; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: question_db.php?_course_id='.$_course_id); + } + else + $msg->addError('DB_NOT_UPDATED'); + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +$onload = 'document.form.category_id.focus();'; +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_truefalse.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/create_test.php b/tests/create_test.php index fcb70175..c0eb4e82 100644 --- a/tests/create_test.php +++ b/tests/create_test.php @@ -1,51 +1,64 @@ -addFeedback('CANCELLED'); - header('Location: index.php?_course_id='.$_course_id); - exit; -} else if (isset($_POST['submit'])) { - $testsDAO = new TestsDAO(); - - if ($testsDAO->Create($_course_id, $_POST['title'], $_POST['description'])) - { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: index.php?_course_id='.$_course_id); - exit; - } -} - -$onload = 'document.form.title.focus();'; - -$savant->assign('course_id', $_course_id); - -require_once(TR_INCLUDE_PATH.'header.inc.php'); -$msg->printErrors(); - -$savant->display('tests/create_edit_test.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); - -?> \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: index.php?_course_id='.$_course_id); + exit; +} else if (isset($_POST['submit'])) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $testsDAO = new TestsDAO(); + + if ($testsDAO->Create($_course_id, $purifier->purify($_POST['title']), $purifier->purify($_POST['description']))) + { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: index.php?_course_id='.$_course_id); + exit; + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +$onload = 'document.form.title.focus();'; + +$savant->assign('course_id', $_course_id); + +require_once(TR_INCLUDE_PATH.'header.inc.php'); +$msg->printErrors(); + +$savant->display('tests/create_edit_test.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); + +?> diff --git a/tests/preview.php b/tests/preview.php index bc0b3cbd..f5f7748e 100644 --- a/tests/preview.php +++ b/tests/preview.php @@ -1,94 +1,99 @@ -get($tid))) { - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -$rows = $testsQuestionsAssocDAO->getByTestID($tid); -$count = 1; -?> -
    - - -
    -

    - - - -
    - -
    -
    - - - display($row); - } - - // "back" button only appears when the request is from index page of "tests" module - if (stripos($_SERVER['HTTP_REFERER'], 'tests/index.php')) { ?> -
    - -
    - -
    -
    - -printErrors('NO_QUESTIONS'); -} - - -require_once(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +get($tid))) { + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +$rows = $testsQuestionsAssocDAO->getByTestID($tid); +$count = 1; +?> +
    + + +
    +

    + + + +
    + +
    +
    + + + display($row); + } + + // "back" button only appears when the request is from index page of "tests" module + if (stripos($_SERVER['HTTP_REFERER'], 'tests/index.php')) { ?> +
    + +
    + +
    +
    + +printErrors('NO_QUESTIONS'); +} + + +require_once(TR_INCLUDE_PATH.'footer.inc.php'); +?> diff --git a/tests/question_cats_manage.php b/tests/question_cats_manage.php index cc92364f..d30f4e0c 100644 --- a/tests/question_cats_manage.php +++ b/tests/question_cats_manage.php @@ -12,9 +12,16 @@ $page = 'tests'; define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsCategoriesDAO.class.php'); require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); global $_course_id; @@ -27,10 +34,11 @@ header('Location: question_cats.php'); exit; } else if (isset($_POST['submit'])) { + if (Token::isValid() AND Token::isRecent()) + { + $_POST['title'] = $purifier->purify(trim($_POST['title'])); - $_POST['title'] = trim($_POST['title']); - - if (!empty($_POST['title']) && !isset($_POST['catid'])) { + if (!empty($_POST['title']) && !isset($_POST['catid'])) { if ($testsQuestionsCategoriesDAO->Create($_course_id, $_POST['title'])) { $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); @@ -47,6 +55,10 @@ } else { $msg->addError(array('EMPTY_FIELDS', _AT('title'))); } + } else + { + $msg->addError('INVALID_TOKEN'); + } } if (isset($_GET['catid'])) { @@ -73,4 +85,4 @@ require_once(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +?> From 7a46655628f35431839326a76fbafb092acb9880 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:55:02 +0700 Subject: [PATCH 31/94] Add files via upload --- tests/html/tests_questions.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/html/tests_questions.inc.php b/tests/html/tests_questions.inc.php index fb48903d..fa5fc33f 100644 --- a/tests/html/tests_questions.inc.php +++ b/tests/html/tests_questions.inc.php @@ -30,7 +30,7 @@ $cats = array(); if ($_GET['category_id'] >= 0) { - $category_row = $testsQuestionsCategoriesDAO->get($_GET[category_id]); + $category_row = $testsQuestionsCategoriesDAO->get($_GET['category_id']); } else { $category_rows = $testsQuestionsCategoriesDAO->getByCourseID($_course_id); } From be2f8a6e658f25a991c2fc325782bd270970dd48 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:56:02 +0700 Subject: [PATCH 32/94] Add files via upload --- .../create_edit_question_likert.tmpl.php | 8 ++++++-- .../tests/create_edit_question_long.tmpl.php | 10 +++++++--- .../create_edit_question_matching.tmpl.php | 20 +++++++++++++------ .../create_edit_question_matchingdd.tmpl.php | 20 +++++++++++++++---- .../create_edit_question_multianswer.tmpl.php | 13 +++++++++--- .../create_edit_question_multichoice.tmpl.php | 4 ++++ .../create_edit_question_ordering.tmpl.php | 20 +++++++++++++++---- .../create_edit_question_truefalse.tmpl.php | 15 +++++++++++--- .../default/tests/create_edit_test.tmpl.php | 11 +++++++--- .../tests/question_cats_manage.tmpl.php | 7 ++++++- 10 files changed, 99 insertions(+), 29 deletions(-) diff --git a/themes/default/tests/create_edit_question_likert.tmpl.php b/themes/default/tests/create_edit_question_likert.tmpl.php index 451a6cc7..19440aac 100644 --- a/themes/default/tests/create_edit_question_likert.tmpl.php +++ b/themes/default/tests/create_edit_question_likert.tmpl.php @@ -10,7 +10,10 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + require_once(TR_INCLUDE_PATH.'../tests/classes/TestsUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?>
    @@ -77,7 +80,7 @@ - +
    ">
    - +
    +
    diff --git a/themes/default/tests/create_edit_question_long.tmpl.php b/themes/default/tests/create_edit_question_long.tmpl.php index be687df6..6a3aa671 100644 --- a/themes/default/tests/create_edit_question_long.tmpl.php +++ b/themes/default/tests/create_edit_question_long.tmpl.php @@ -10,7 +10,10 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + require_once(TR_INCLUDE_PATH.'../tests/classes/TestsUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> @@ -31,15 +34,15 @@ - +
    * - +
    @@ -51,6 +54,7 @@
    +
    diff --git a/themes/default/tests/create_edit_question_matching.tmpl.php b/themes/default/tests/create_edit_question_matching.tmpl.php index 69ebbe8f..5dd5f2a4 100644 --- a/themes/default/tests/create_edit_question_matching.tmpl.php +++ b/themes/default/tests/create_edit_question_matching.tmpl.php @@ -10,7 +10,10 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + require_once(TR_INCLUDE_PATH.'../tests/classes/TestsUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> @@ -31,15 +34,15 @@ - +
    - +
    @@ -64,7 +67,9 @@ + if (isset($_POST['question']) AND CSRF_Token::isValid() AND CSRF_Token::isRecent()) + echo htmlspecialchars(stripslashes($_POST['question'][$i])); + else echo htmlspecialchars(stripslashes($this->row['question'][$i])); ?>
    @@ -80,11 +85,14 @@
    + if (isset($_POST['answer']) AND CSRF_Token::isValid() AND CSRF_Token::isRecent()) + echo htmlspecialchars(stripslashes($_POST['answer'][$i])); + else echo htmlspecialchars(stripslashes($this->row['answer'][$i])); ?>
    +
    diff --git a/themes/default/tests/create_edit_question_matchingdd.tmpl.php b/themes/default/tests/create_edit_question_matchingdd.tmpl.php index f4300cb6..8dd670ca 100644 --- a/themes/default/tests/create_edit_question_matchingdd.tmpl.php +++ b/themes/default/tests/create_edit_question_matchingdd.tmpl.php @@ -10,7 +10,10 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + require_once(TR_INCLUDE_PATH.'../tests/classes/TestsUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> @@ -32,14 +35,18 @@ + if (isset($_POST['feedback']) AND CSRF_Token::isValid() AND CSRF_Token::isRecent()) + echo htmlspecialchars(stripslashes($_POST['feedback'])); + else echo htmlspecialchars(stripslashes($this->row['feedback'])); ?>
    + if (isset($_POST['instructions']) AND CSRF_Token::isValid() AND CSRF_Token::isRecent()) + echo htmlspecialchars(stripslashes($_POST['instructions'])); + else echo htmlspecialchars(stripslashes($this->row['instructions'])); ?>
    @@ -64,7 +71,9 @@ + if (isset($_POST['question'][$i]) AND CSRF_Token::isValid() AND CSRF_Token::isRecent()) + echo htmlspecialchars(stripslashes($_POST['question'][$i])); + else echo htmlspecialchars(stripslashes($this->row['question'][$i])); ?>
    @@ -80,11 +89,14 @@
    + if (isset($_POST['answer'][$i]) AND CSRF_Token::isValid() AND CSRF_Token::isRecent()) + echo htmlspecialchars(stripslashes($_POST['answer'][$i])); + else echo htmlspecialchars(stripslashes($this->row['answer'][$i])); ?>
    +
    diff --git a/themes/default/tests/create_edit_question_multianswer.tmpl.php b/themes/default/tests/create_edit_question_multianswer.tmpl.php index c585b368..3a346db8 100644 --- a/themes/default/tests/create_edit_question_multianswer.tmpl.php +++ b/themes/default/tests/create_edit_question_multianswer.tmpl.php @@ -10,7 +10,10 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + require_once(TR_INCLUDE_PATH.'../tests/classes/TestsUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> @@ -31,14 +34,16 @@ - +
    * + if (isset($_POST['question']) AND CSRF_Token::isValid() AND CSRF_Token::isRecent()) + echo htmlspecialchars(stripslashes($_POST['question'])); + else echo htmlspecialchars(stripslashes($this->row['question'])); ?>
    > - +
    +
    diff --git a/themes/default/tests/create_edit_question_multichoice.tmpl.php b/themes/default/tests/create_edit_question_multichoice.tmpl.php index 0d2baedf..6566f4f6 100644 --- a/themes/default/tests/create_edit_question_multichoice.tmpl.php +++ b/themes/default/tests/create_edit_question_multichoice.tmpl.php @@ -10,7 +10,10 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + require_once(TR_INCLUDE_PATH.'../tests/classes/TestsUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> @@ -55,6 +58,7 @@
    +
    diff --git a/themes/default/tests/create_edit_question_ordering.tmpl.php b/themes/default/tests/create_edit_question_ordering.tmpl.php index 748b87de..e2c1960b 100644 --- a/themes/default/tests/create_edit_question_ordering.tmpl.php +++ b/themes/default/tests/create_edit_question_ordering.tmpl.php @@ -10,7 +10,10 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + require_once(TR_INCLUDE_PATH.'../tests/classes/TestsUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> @@ -31,7 +34,10 @@ - +
    @@ -39,7 +45,10 @@ - +
    @@ -52,12 +61,15 @@
    - +
    +
    diff --git a/themes/default/tests/create_edit_question_truefalse.tmpl.php b/themes/default/tests/create_edit_question_truefalse.tmpl.php index 39ec21c1..51044844 100644 --- a/themes/default/tests/create_edit_question_truefalse.tmpl.php +++ b/themes/default/tests/create_edit_question_truefalse.tmpl.php @@ -10,7 +10,10 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + require_once(TR_INCLUDE_PATH.'../tests/classes/TestsUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> @@ -30,14 +33,19 @@
    - +
    * - +
    @@ -46,6 +54,7 @@
    +
    diff --git a/themes/default/tests/create_edit_test.tmpl.php b/themes/default/tests/create_edit_test.tmpl.php index 0bee40a7..f4cb7f7e 100644 --- a/themes/default/tests/create_edit_test.tmpl.php +++ b/themes/default/tests/create_edit_test.tmpl.php @@ -9,9 +9,13 @@ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation. */ /************************************************************************/ + +session_start(); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> - + tid)) { ?> @@ -19,15 +23,16 @@
    *
    - +

    - +
    +
    diff --git a/themes/default/tests/question_cats_manage.tmpl.php b/themes/default/tests/question_cats_manage.tmpl.php index 0659d0cb..ebffdb52 100644 --- a/themes/default/tests/question_cats_manage.tmpl.php +++ b/themes/default/tests/question_cats_manage.tmpl.php @@ -9,6 +9,10 @@ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation. */ /************************************************************************/ + +session_start(); + +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> @@ -22,10 +26,11 @@
    title; ?>
    *
    - +
    +
    From ec4324bf52be3c6e38bcbeca56ee1c23176f6edb Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sat, 15 Sep 2018 21:59:33 +0700 Subject: [PATCH 33/94] Add files via upload --- file_manager/index.php | 183 +++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 91 deletions(-) diff --git a/file_manager/index.php b/file_manager/index.php index d7fa0344..bee94b08 100644 --- a/file_manager/index.php +++ b/file_manager/index.php @@ -1,91 +1,92 @@ - - - -'; - } - - $fluid_dir = 'include/jscripts/infusion/'; - $framed = intval($_GET['framed']); - $popup = intval($_GET['popup']); - $current_path = TR_CONTENT_DIR.$_course_id.'/'; - - if ($_GET['pathext'] != '') { - $pathext = urldecode($_GET['pathext']); - } else if ($_POST['pathext'] != '') { - $pathext = $_POST['pathext']; - } - - if($_GET['back'] == 1) { - $pathext = substr($pathext, 0, -1); - $slashpos = strrpos($pathext, '/'); - if($slashpos == 0) { - $pathext = ''; - } else { - $pathext = substr($pathext, 0, ($slashpos+1)); - } - - } -} - -global $msg; -if (isset($_GET['msg'])) $msg->addFeedback($_GET['msg']); - -require('top.php'); -$_SESSION['done'] = 1; - -require(TR_INCLUDE_PATH.'../file_manager/filemanager_display.inc.php'); - -closedir($dir); - -?> - - + + + +'; + } + + $fluid_dir = 'include/jscripts/infusion/'; + $framed = intval($_GET['framed']); + $popup = intval($_GET['popup']); + $current_path = TR_CONTENT_DIR.$_course_id.'/'; + + if ($_GET['pathext'] != '') { + $pathext = urldecode($_GET['pathext']); + } else if ($_POST['pathext'] != '') { + $pathext = $_POST['pathext']; + } + + if($_GET['back'] == 1) { + $pathext = substr($pathext, 0, -1); + $slashpos = strrpos($pathext, '/'); + if($slashpos == 0) { + $pathext = ''; + } else { + $pathext = substr($pathext, 0, ($slashpos+1)); + } + + } +} + +global $msg; +if (isset($_GET['msg'])) $msg->addFeedback($_GET['msg']); + +require('top.php'); +$_SESSION['done'] = 1; + +require(TR_INCLUDE_PATH.'../file_manager/filemanager_display.inc.php'); + +closedir($dir); + +?> + + From 9f7690a8c7307014e4d7a49ad068b3804d1519e6 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sun, 16 Sep 2018 14:35:29 +0700 Subject: [PATCH 34/94] Add files via upload --- include/sidemenus/my_courses.inc.php | 163 ++++++++++++++------------- 1 file changed, 84 insertions(+), 79 deletions(-) diff --git a/include/sidemenus/my_courses.inc.php b/include/sidemenus/my_courses.inc.php index d6b4ba87..80799bef 100644 --- a/include/sidemenus/my_courses.inc.php +++ b/include/sidemenus/my_courses.inc.php @@ -1,79 +1,84 @@ - 0) { - $my_courses = $userCoursesDAO->getByUserID($_SESSION['user_id']); -} - -if (!is_array($my_courses)) { - $num_of_courses = 0; - $output = _AT('none_found'); -} else { - $num_of_courses = count($my_courses); - - $output .= '
      '."\n"; - - foreach ($my_courses as $row) { - // only display the first 200 character of course description - - if ($row['role'] == TR_USERROLE_AUTHOR) { - $output .= '
    1. '."\n"; - } else { - $output .= '
    2. '."\n"; - } - $output .= ' '.$row['title'].''."\n"; - if ($row['role'] == TR_USERROLE_VIEWER) { - $output .= ' '."\n"; - $output .= ' '. htmlspecialchars(_AT('remove_from_list')).''."\n"; - $output .= ' '."\n"; - } - if ($row['role'] == NULL && $_SESSION['user_id']>0) { - $output .= ' '."\n"; - $output .= ' '. htmlspecialchars(_AT('add_into_list')).''."\n"; - $output .= ' '."\n"; - } - //$output .= ' '."\n"; - //$output .= ' '. _AT('download_content_package').''."\n"; - //$output .= ' '."\n"; - //if ($row['role'] == TR_USERROLE_AUTHOR) { - //$output .= ' '."\n"; - //$output .= ' '. _AT('download_common_cartridge').''."\n"; - //$output .= ' '."\n"; - //} - $output .= '
    3. '."\n"; - } // end of foreach; - $output .= '
    '."\n"; -} -$savant->assign('title', _AT('my_courses').' '.'('.$num_of_courses.')'); -$savant->assign('dropdown_contents', $output); -//$savant->assign('default_status', "hide"); - -$savant->display('include/box.tmpl.php'); -?> + 0) { + $my_courses = $userCoursesDAO->getByUserID($_SESSION['user_id']); +} + +if (!is_array($my_courses)) { + $num_of_courses = 0; + $output = _AT('none_found'); +} else { + $num_of_courses = count($my_courses); + + $output .= '
      '."\n"; + + foreach ($my_courses as $row) { + // only display the first 200 character of course description + + if ($row['role'] == TR_USERROLE_AUTHOR) { + $output .= '
    1. '."\n"; + } else { + $output .= '
    2. '."\n"; + } + $output .= ' '.$purifier->purify(htmlspecialchars(stripslashes($row['title']))).''."\n"; + if ($row['role'] == TR_USERROLE_VIEWER) { + $output .= ' '."\n"; + $output .= ' '. htmlspecialchars(_AT('remove_from_list')).''."\n"; + $output .= ' '."\n"; + } + if ($row['role'] == NULL && $_SESSION['user_id']>0) { + $output .= ' '."\n"; + $output .= ' '. htmlspecialchars(_AT('add_into_list')).''."\n"; + $output .= ' '."\n"; + } + //$output .= ' '."\n"; + //$output .= ' '. _AT('download_content_package').''."\n"; + //$output .= ' '."\n"; + //if ($row['role'] == TR_USERROLE_AUTHOR) { + //$output .= ' '."\n"; + //$output .= ' '. _AT('download_common_cartridge').''."\n"; + //$output .= ' '."\n"; + //} + $output .= '
    3. '."\n"; + } // end of foreach; + $output .= '
    '."\n"; +} +$savant->assign('title', _AT('my_courses').' '.'('.$num_of_courses.')'); +$savant->assign('dropdown_contents', $output); +//$savant->assign('default_status', "hide"); + +$savant->display('include/box.tmpl.php'); +?> From 4d8fe701941152356050ff572d0a64a122792fff Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sun, 16 Sep 2018 14:42:52 +0700 Subject: [PATCH 35/94] Add files via upload --- home/course/course_property.php | 44 +++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/home/course/course_property.php b/home/course/course_property.php index feaf380d..142fb718 100644 --- a/home/course/course_property.php +++ b/home/course/course_property.php @@ -11,6 +11,8 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../../include/'); +define('TR_ClassCSRF_PATH', '../../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); require(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php'); @@ -22,6 +24,11 @@ require_once(TR_INCLUDE_PATH.'classes/DAO/TestsDAO.class.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/ContentTestsAssocDAO.class.php'); require_once(TR_INCLUDE_PATH.'lib/mysql_funcs.inc.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); global $_course_id; @@ -40,17 +47,19 @@ exit; } else if($_POST['submit']){ + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { if (isset($_POST['hide_course'])) $access = 'private'; else $access = 'public'; - - if ($_course_id > 0) { // update an existing course - $coursesDAO->UpdateField($_course_id, 'title', $_POST['title']); - $coursesDAO->UpdateField($_course_id, 'category_id', $_POST['category_id']); - $coursesDAO->UpdateField($_course_id, 'primary_language', $_POST['pri_lang']); - $coursesDAO->UpdateField($_course_id, 'description', $_POST['description']); - $coursesDAO->UpdateField($_course_id, 'copyright', $_POST['copyright']); + { + if ($_course_id > 0) { // update an existing course + $coursesDAO->UpdateField($_course_id, 'title', $purifier->purify(htmlspecialchars(stripslashes($_POST['title)'])))); + $coursesDAO->UpdateField($_course_id, 'category_id', $purifier->purify(htmlspecialchars(stripslashes($_POST['category_id'])))); + $coursesDAO->UpdateField($_course_id, 'primary_language', $purifier->purify(htmlspecialchars(stripslashes($_POST['pri_lang'])))); + $coursesDAO->UpdateField($_course_id, 'description', $purifier->purify(htmlspecialchars(stripslashes($_POST['description'])))); + $coursesDAO->UpdateField($_course_id, 'copyright', $purifier->purify(htmlspecialchars(stripslashes($_POST['copyright'])))); $coursesDAO->UpdateField($_course_id, 'access', $access); @@ -61,8 +70,15 @@ } else { // create a new course - if ($course_id = $coursesDAO->Create($_POST['this_author'], $_POST['category_id'], 'top', $access, $_POST['title'], $_POST['description'], - null, null, null, $_POST['copyright'], $_POST['pri_lang'], null, null)) + + if ($course_id = $coursesDAO->Create( + $purifier->purify($_POST['this_author']), + $purifier->purify($_POST['category_id']), 'top', $access, + $purifier->purify($_POST['title']), + $purifier->purify($_POST['description']), + null, null, null, + $purifier->purify($_POST['copyright']), + $_POST['pri_lang'], null, null)) { if(isset($_POST['_struct_name'])) { @@ -82,7 +98,13 @@ header('Location: '.TR_BASE_HREF.'home/course/index.php?_course_id='.$course_id); exit; } + } + } + } else + { + $msg->addError('INVALID_TOKEN'); } + } // display @@ -107,8 +129,4 @@ require(TR_INCLUDE_PATH.'footer.inc.php'); - - - - ?> From 83e613308908ee817c2bfcf0a85201c4217bc7bb Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sun, 16 Sep 2018 14:44:26 +0700 Subject: [PATCH 36/94] Add files via upload --- .../home/course/course_property.tmpl.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/themes/default/home/course/course_property.tmpl.php b/themes/default/home/course/course_property.tmpl.php index 73268eee..0d3ee3e3 100644 --- a/themes/default/home/course/course_property.tmpl.php +++ b/themes/default/home/course/course_property.tmpl.php @@ -9,13 +9,18 @@ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation. */ /************************************************************************/ + +session_start(); + global $_current_user; global $languageManager; require_once(TR_INCLUDE_PATH.'classes/CoursesUtility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); + ?> - + * : - + @@ -77,7 +82,7 @@ - + @@ -85,7 +90,7 @@ - + @@ -93,7 +98,7 @@ - course_row['access'] == 'private') echo "checked"; ?> /> + course_row['access'] == 'private' AND CSRF_Token::isValid() AND CSRF_Token::isRecent()) echo "checked"; else $this->course_row['access']?> /> @@ -109,6 +114,7 @@

    +
    From 6ce95f2caa62806380929c96f3b18d7d36637bea Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sun, 16 Sep 2018 15:10:28 +0700 Subject: [PATCH 37/94] Add ClassCSRF and/or HTMLPurifier Paths --- home/editor/accessibility.php | 251 +++--- home/editor/add_content.php | 3 +- home/editor/add_forum.php | 189 ++-- home/editor/arrange_content.php | 83 +- home/editor/delete_content.php | 145 +-- home/editor/edit_content.php | 660 +++++++------- home/editor/edit_content_folder.php | 371 ++++---- home/editor/edit_content_struct.php | 418 ++++----- home/editor/editor_tab_functions.inc.php | 1046 +++++++++++----------- home/editor/forums_tool.php | 3 +- home/editor/import_export_content.php | 387 ++++---- home/editor/index.php | 57 +- home/editor/preview.php | 157 ++-- home/editor/remove_alternative.php | 131 +-- home/editor/save_alternative.php | 171 ++-- 15 files changed, 2065 insertions(+), 2007 deletions(-) diff --git a/home/editor/accessibility.php b/home/editor/accessibility.php index 2aee3c77..78493407 100644 --- a/home/editor/accessibility.php +++ b/home/editor/accessibility.php @@ -1,125 +1,126 @@ -printInfos('NO_PAGE_CONTENT'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (isset($contentManager)) $content_row = $contentManager->getContentPage($cid); - -if (!$content_row || !isset($contentManager)) { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('MISSING_CONTENT'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -$course_base_href = ''; -$content_base_href = ''; - -//make decisions -if ($_POST['make_decision']) -{ - //get list of decisions - $desc_query = ''; - if (is_array($_POST['d'])) { - foreach ($_POST['d'] as $sequenceID => $decision) { - $desc_query .= '&'.$sequenceID.'='.$decision; - } - } - - $checker_url = TR_ACHECKER_URL. 'decisions.php?' - .'uri='.urlencode($_POST['pg_url']).'&id='.TR_ACHECKER_WEB_SERVICE_ID - .'&session='.$_POST['sessionid'].'&output=html'.$desc_query; - - if (@file_get_contents($checker_url) === false) { - $msg->addInfo('DECISION_NOT_SAVED'); - } -} -else if (isset($_POST['reverse'])) -{ - $reverse_url = TR_ACHECKER_URL. 'decisions.php?' - .'uri='.urlencode($_POST['pg_url']).'&id='.TR_ACHECKER_WEB_SERVICE_ID - .'&session='.$_POST['sessionid'].'&output=html&reverse=true&'.key($_POST['reverse']).'=N'; - - if (@file_get_contents($reverse_url) === false) { - $msg->addInfo('DECISION_NOT_REVERSED'); - } else { - $msg->addInfo('DECISION_REVERSED'); - } -} - -$popup = intval($_GET['popup']); -require(TR_INCLUDE_PATH.'header.inc.php'); -?> - -

    -'; - echo ' '; - - if (!$cid) { - $msg->printInfos('SAVE_CONTENT'); - - echo '
    '; - - return; - } - -$msg->printInfos(); -if ($_POST['body_text'] != '') { - //save temp file - $_POST['content_path'] = $content_row['content_path']; - write_temp_file(); - - $pg_url = TR_BASE_HREF.'get_acheck.php/'.$cid . '.html'; - $checker_url = TR_ACHECKER_URL.'checkacc.php?uri='.urlencode($pg_url).'&id='.TR_ACHECKER_WEB_SERVICE_ID - . '&guide=WCAG2-L2&output=html'; - - $report = @file_get_contents($checker_url); - - if (stristr($report, '
    ')) { - $msg->printErrors('INVALID_URL'); - } else if ($report === false) { - $msg->printInfos('SERVICE_UNAVAILABLE'); - } else { - echo ' '; - echo $report; - - echo '

    '._AT('access_credit').'

    '; - } - //delete file - @unlink(TR_CONTENT_DIR . $cid . '.html'); - -} else { - $msg->printInfos('NO_PAGE_CONTENT'); -} -?> -
    - - \ No newline at end of file +printInfos('NO_PAGE_CONTENT'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +if (isset($contentManager)) $content_row = $contentManager->getContentPage($cid); + +if (!$content_row || !isset($contentManager)) { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('MISSING_CONTENT'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +$course_base_href = ''; +$content_base_href = ''; + +//make decisions +if ($_POST['make_decision']) +{ + //get list of decisions + $desc_query = ''; + if (is_array($_POST['d'])) { + foreach ($_POST['d'] as $sequenceID => $decision) { + $desc_query .= '&'.$sequenceID.'='.$decision; + } + } + + $checker_url = TR_ACHECKER_URL. 'decisions.php?' + .'uri='.urlencode($_POST['pg_url']).'&id='.TR_ACHECKER_WEB_SERVICE_ID + .'&session='.$_POST['sessionid'].'&output=html'.$desc_query; + + if (@file_get_contents($checker_url) === false) { + $msg->addInfo('DECISION_NOT_SAVED'); + } +} +else if (isset($_POST['reverse'])) +{ + $reverse_url = TR_ACHECKER_URL. 'decisions.php?' + .'uri='.urlencode($_POST['pg_url']).'&id='.TR_ACHECKER_WEB_SERVICE_ID + .'&session='.$_POST['sessionid'].'&output=html&reverse=true&'.key($_POST['reverse']).'=N'; + + if (@file_get_contents($reverse_url) === false) { + $msg->addInfo('DECISION_NOT_REVERSED'); + } else { + $msg->addInfo('DECISION_REVERSED'); + } +} + +$popup = intval($_GET['popup']); +require(TR_INCLUDE_PATH.'header.inc.php'); +?> +
    +
    +'; + echo ' '; + + if (!$cid) { + $msg->printInfos('SAVE_CONTENT'); + + echo '
    '; + + return; + } + +$msg->printInfos(); +if ($_POST['body_text'] != '') { + //save temp file + $_POST['content_path'] = $content_row['content_path']; + write_temp_file(); + + $pg_url = TR_BASE_HREF.'get_acheck.php/'.$cid . '.html'; + $checker_url = TR_ACHECKER_URL.'checkacc.php?uri='.urlencode($pg_url).'&id='.TR_ACHECKER_WEB_SERVICE_ID + . '&guide=WCAG2-L2&output=html'; + + $report = @file_get_contents($checker_url); + + if (stristr($report, '
    ')) { + $msg->printErrors('INVALID_URL'); + } else if ($report === false) { + $msg->printInfos('SERVICE_UNAVAILABLE'); + } else { + echo ' '; + echo $report; + + echo '

    '._AT('access_credit').'

    '; + } + //delete file + @unlink(TR_CONTENT_DIR . $cid . '.html'); + +} else { + $msg->printInfos('NO_PAGE_CONTENT'); +} +?> +
    +
    + diff --git a/home/editor/add_content.php b/home/editor/add_content.php index dd7e9721..0a9b37f3 100644 --- a/home/editor/add_content.php +++ b/home/editor/add_content.php @@ -11,10 +11,11 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../../include/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'vitals.inc.php'); global $_course_id; require('./edit_content.php?_course_id='.$_course_id); -?> \ No newline at end of file +?> diff --git a/home/editor/add_forum.php b/home/editor/add_forum.php index dde55b2f..c6103954 100644 --- a/home/editor/add_forum.php +++ b/home/editor/add_forum.php @@ -1,94 +1,95 @@ -Create($_POST['title'], $_POST['body']); - if($forum_id) { - - if($forum_content->Create($cid, $forum_id) & $forum_course->Create($forum_id, $crid)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - $msg->printFeedbacks(); - } - } else { - $msg->printErrors(); - } - -} else if(isset($_POST['save'])) { - $checks = $_POST['check']; - - $rows_forums_content = $forum_content->getByContent($cid); - - $forums_id = array(); - foreach ($rows_forums_content as $row_forum_content) { - $forums_id[] = $row_forum_content['forum_id']; - } - - $new_ass = array_diff($checks, $forums_id); - - if(count($checks) == 0) - $del_ass = $forums_id; - else - $del_ass = array_diff($forums_id, $checks); - - - - - - foreach ($new_ass as $new) { - if($forum_content->Create($cid, $new)) - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - } - - - - foreach ($del_ass as $del) { - - if($forum_content->Delete($del, $cid)) - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - } - - - $msg->printAll(); - - -} - -?> - - +Create($_POST['title'], $_POST['body']); + if($forum_id) { + + if($forum_content->Create($cid, $forum_id) & $forum_course->Create($forum_id, $crid)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + $msg->printFeedbacks(); + } + } else { + $msg->printErrors(); + } + +} else if(isset($_POST['save'])) { + $checks = $_POST['check']; + + $rows_forums_content = $forum_content->getByContent($cid); + + $forums_id = array(); + foreach ($rows_forums_content as $row_forum_content) { + $forums_id[] = $row_forum_content['forum_id']; + } + + $new_ass = array_diff($checks, $forums_id); + + if(count($checks) == 0) + $del_ass = $forums_id; + else + $del_ass = array_diff($forums_id, $checks); + + + + + + foreach ($new_ass as $new) { + if($forum_content->Create($cid, $new)) + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + + } + + + + foreach ($del_ass as $del) { + + if($forum_content->Delete($del, $cid)) + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + + } + + + $msg->printAll(); + + +} + +?> + + diff --git a/home/editor/arrange_content.php b/home/editor/arrange_content.php index f8fb3ff5..49b3439b 100644 --- a/home/editor/arrange_content.php +++ b/home/editor/arrange_content.php @@ -1,37 +1,46 @@ -moveContent($_POST['moved_cid'], $new_pid, $new_ordering); - header('Location: '.TR_BASE_HREF.'home/editor/arrange_content.php?_course_id='.$_course_id); - exit; -} - -if (!defined('TR_INCLUDE_PATH')) { exit; } - -$savant->assign('languageManager', $languageManager); -$savant->assign('course_id', $_course_id); - -$savant->display('home/editor/arrange_content.tmpl.php'); - -?> +moveContent($_POST['moved_cid'], $new_pid, $new_ordering); + header('Location: '.TR_BASE_HREF.'home/editor/arrange_content.php?_course_id='.$_course_id); + exit; + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +if (!defined('TR_INCLUDE_PATH')) { exit; } + +$savant->assign('languageManager', $languageManager); +$savant->assign('course_id', $_course_id); + +$savant->display('home/editor/arrange_content.tmpl.php'); + +?> diff --git a/home/editor/delete_content.php b/home/editor/delete_content.php index 170db2d7..c0e74024 100644 --- a/home/editor/delete_content.php +++ b/home/editor/delete_content.php @@ -1,70 +1,75 @@ -deleteContent($cid); - - $msg->addFeedback('CONTENT_DELETED'); - header('Location: '.TR_BASE_HREF.'home/course/index.php?_course_id='.$_course_id); - exit; -} else if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - $cid = intval($_POST['_cid']); - $row = $contentManager->getContentPage($cid); - if ($row['content_type'] == CONTENT_TYPE_FOLDER) { - header('Location: '.TR_BASE_HREF.'home/editor/edit_content_folder.php?_cid='.$cid); - } else { - header('Location: '.TR_BASE_HREF.'home/course/content.php?_cid='.$cid); - } - exit; -} - -$path = $contentManager->getContentPath($cid); -require(TR_INCLUDE_PATH.'header.inc.php'); - -if ($_GET['cid'] == 0) { - $msg->printErrors('ID_ZERO'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -$children = $contentManager->getContent($_GET['cid']); - -$hidden_vars['_cid'] = $_GET['cid']; - -if (is_array($children) && (count($children)>0) ) { - $msg->addConfirm('SUB_CONTENT_DELETE', $hidden_vars); -// $msg->addConfirm('GLOSSARY_REMAINS', $hidden_vars); -//} else { -// $msg->addConfirm('GLOSSARY_REMAINS', $hidden_vars); -} - -$row = $contentManager->getContentPage($_GET['cid']); -$title = $row['title']; - -$msg->addConfirm(array('DELETE', $title), $hidden_vars); -$msg->printConfirm(); - -require(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +deleteContent($cid); + + $msg->addFeedback('CONTENT_DELETED'); + header('Location: '.TR_BASE_HREF.'home/course/index.php?_course_id='.$_course_id); + exit; +} else if (isset($_POST['submit_no'])) { + $msg->addFeedback('CANCELLED'); + $cid = intval($_POST['_cid']); + $row = $contentManager->getContentPage($cid); + if ($row['content_type'] == CONTENT_TYPE_FOLDER) { + header('Location: '.TR_BASE_HREF.'home/editor/edit_content_folder.php?_cid='.$cid); + } else { + header('Location: '.TR_BASE_HREF.'home/course/content.php?_cid='.$cid); + } + exit; +} + +$path = $contentManager->getContentPath($cid); +require(TR_INCLUDE_PATH.'header.inc.php'); + +if ($_GET['cid'] == 0) { + $msg->printErrors('ID_ZERO'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +$children = $contentManager->getContent($_GET['cid']); + +$hidden_vars['_cid'] = $_GET['cid']; + +if (is_array($children) && (count($children)>0) ) { + $msg->addConfirm('SUB_CONTENT_DELETE', $hidden_vars); +// $msg->addConfirm('GLOSSARY_REMAINS', $hidden_vars); +//} else { +// $msg->addConfirm('GLOSSARY_REMAINS', $hidden_vars); +} + +$row = $contentManager->getContentPage($_GET['cid']); +$title = $purifier->purify($row['title']); + +$msg->addConfirm(array('DELETE', $title), $hidden_vars); +$msg->printConfirm(); + +require(TR_INCLUDE_PATH.'footer.inc.php'); +?> diff --git a/home/editor/edit_content.php b/home/editor/edit_content.php index 95c32f75..d992501e 100644 --- a/home/editor/edit_content.php +++ b/home/editor/edit_content.php @@ -1,329 +1,331 @@ -isAdmin()){ -$savant->assign('isAdmin', $_current_user->isAdmin()); -} -require(TR_INCLUDE_PATH.'../home/editor/editor_tab_functions.inc.php'); - -if ($_POST['close'] || $_GET['close']) { - if ($_GET['close']) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - } else { - $msg->addFeedback('CLOSED'); - if ($cid == 0) { - header('Location: '.TR_BASE_HREF.'home/course/index.php?_course_id='.$_course_id); - exit; - } - } - - if (!isset($_content_id) || $_content_id == 0) { - header('Location: '.TR_BASE_HREF.'home/course/index.php?_course_id='.$_course_id); - exit; - } - header('Location: '.TR_BASE_HREF.'home/course/content.php?_cid='.$_content_id); - exit; -} - -$tabs = get_tabs(); -$num_tabs = count($tabs); -for ($i=0; $i < $num_tabs; $i++) { - if (isset($_POST['button_'.$i]) && ($_POST['button_'.$i] != -1)) { - $current_tab = $i; - $_POST['current_tab'] = $i; - break; - } -} - -if (isset($_GET['tab'])) { - $current_tab = intval($_GET['tab']); -} -if (isset($_POST['current_tab'])) { - $current_tab = intval($_POST['current_tab']); -} - -if (isset($_POST['submit_file'])) { - paste_from_file(body_text); -} else if (isset($_POST['submit']) && ($_POST['submit'] != 'submit1')) { - /* we're saving. redirects if successful. */ - save_changes(true, $current_tab); -} - -if (isset($_POST['submit_file_alt'])) { - paste_from_file(body_text_alt); -} else if (isset($_POST['submit']) && ($_POST['submit'] != 'submit1')) { - /* we're saving. redirects if successful. */ - save_changes(true, $current_tab); -} - -if (isset($_POST['submit'])) { - /* we're saving. redirects if successful. */ - save_changes(true, $current_tab); -} - -if (!isset($current_tab) && isset($_POST['button_1']) && ($_POST['button_1'] == -1) && !isset($_POST['submit'])) { - $current_tab = 1; -} else if (!isset($current_tab)) { - $current_tab = 0; -} - -if ($cid) { - $_section[0][0] = _AT('edit_content'); -} else { - $_section[0][0] = _AT('add_content'); -} - -if($current_tab == 0) { - $_custom_head .= ' - - - '; -} - -if ($cid) { - if (isset($contentManager)) $content_row = $contentManager->getContentPage($cid); - - if (!$content_row || !isset($contentManager)) { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('MISSING_CONTENT'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - $path = $contentManager->getContentPath($cid); - $content_tests = $contentManager->getContentTestsAssoc($cid); - - if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { - $course_base_href = 'get.php/'; - } else { - $course_base_href = 'content/' . $_SESSION['course_id'] . '/'; - } - - if ($content_row['content_path']) { - $content_base_href .= $content_row['content_path'].'/'; - } -} else { - if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { - $content_base_href = 'get.php/'; - } else { - $content_base_href = 'content/' . $_SESSION['course_id'] . '/'; - } -} - -/* TAB 0 --> Content *//* TAB 2 --> Page */ -if (($current_tab == 0) || ($current_tab == 2)) { - if ($_POST['formatting'] == null){ - // this is a fresh load from just logged in - if (isset($_SESSION['prefs']['PREF_CONTENT_EDITOR']) && $_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 0) { - $_POST['formatting'] = 0; - } else { - $_POST['formatting'] = 1; - } - } -} - -require(TR_INCLUDE_PATH.'header.inc.php'); - -if ($current_tab == 0 || $current_tab == 2) -{ - $simple = true; - if ($_POST['complexeditor'] == '1') { - $simple = false; - } - load_editor($simple, false, "none"); -} - -$pid = intval($_REQUEST['pid']); -?> - -
    -getContent($pid))+1; - } else { - $_POST['pid'] = 0; - $_POST['ordering'] = count($contentManager->getContent(0))+1; - } - } - } - - echo ''; - echo ''; - echo ''; - if ($_REQUEST['sub'] == 1) - { - echo ''; - echo ''; - } - echo ''; - if (($current_tab != 0) && (($_current_tab != 2))) { - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - - - - } - - echo ''; - echo ''; - - echo ''; - - echo ''; - - echo ''; - - //content test association - echo ''; - - /* get glossary terms */ - - // adapted content - $sql = "SELECT pr.primary_resource_id, prt.type_id - FROM ".TABLE_PREFIX."primary_resources pr, ". - TABLE_PREFIX."primary_resources_types prt - WHERE pr.content_id = ? - AND pr.language_code = ? - AND pr.primary_resource_id = prt.primary_resource_id"; - $values = array($cid, $_SESSION['lang']); - $types = "is"; - $types = $dao->execute($sql, $values, $types); - - $i = 0; - if (is_array($types)) { - foreach ($types as $type) { - $row_alternatives['alt_'.$type['primary_resource_id'].'_'.$type['type_id']] = 1; - } - } - - if ($current_tab != 2 && isset($_POST['use_post_for_alt'])) - { - echo ''; - if (is_array($_POST)) { - foreach ($_POST as $alt_id => $alt_value) { - if (substr($alt_id, 0 ,4) == 'alt_'){ - echo ''; - } - } - } - } - - //tests - if ($current_tab != 5){ - // set content associated tests - if (isset($_POST['visited_tests'])) { - echo ''."\n"; - if (is_array($_POST['tid'])) { - foreach ($_POST['tid'] as $i=>$tid){ - echo ''; - } - } - } else { - $i = 0; - if (is_array($content_tests)) { - foreach ($content_tests as $content_test_row) { - echo ''; - } - } - } - } - - if ($do_check) { - $changes_made = check_for_changes($content_row, $row_alternatives); - } -?> - -
    - -
    - -
    - - -
    - - - /> - -
    - - -
    - /> -
    - - - - -
    -
    - - +isAdmin()){ +$savant->assign('isAdmin', $_current_user->isAdmin()); +} +require(TR_INCLUDE_PATH.'../home/editor/editor_tab_functions.inc.php'); + +if ($_POST['close'] || $_GET['close']) { + if ($_GET['close']) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + } else { + $msg->addFeedback('CLOSED'); + if ($cid == 0) { + header('Location: '.TR_BASE_HREF.'home/course/index.php?_course_id='.$_course_id); + exit; + } + } + + if (!isset($_content_id) || $_content_id == 0) { + header('Location: '.TR_BASE_HREF.'home/course/index.php?_course_id='.$_course_id); + exit; + } + header('Location: '.TR_BASE_HREF.'home/course/content.php?_cid='.$_content_id); + exit; +} + +$tabs = get_tabs(); +$num_tabs = count($tabs); +for ($i=0; $i < $num_tabs; $i++) { + if (isset($_POST['button_'.$i]) && ($_POST['button_'.$i] != -1)) { + $current_tab = $i; + $_POST['current_tab'] = $i; + break; + } +} + +if (isset($_GET['tab'])) { + $current_tab = intval($_GET['tab']); +} +if (isset($_POST['current_tab'])) { + $current_tab = intval($_POST['current_tab']); +} + +if (isset($_POST['submit_file'])) { + paste_from_file(body_text); +} else if (isset($_POST['submit']) && ($_POST['submit'] != 'submit1')) { + /* we're saving. redirects if successful. */ + save_changes(true, $current_tab); +} + +if (isset($_POST['submit_file_alt'])) { + paste_from_file(body_text_alt); +} else if (isset($_POST['submit']) && ($_POST['submit'] != 'submit1')) { + /* we're saving. redirects if successful. */ + save_changes(true, $current_tab); +} + +if (isset($_POST['submit'])) { + /* we're saving. redirects if successful. */ + save_changes(true, $current_tab); +} + +if (!isset($current_tab) && isset($_POST['button_1']) && ($_POST['button_1'] == -1) && !isset($_POST['submit'])) { + $current_tab = 1; +} else if (!isset($current_tab)) { + $current_tab = 0; +} + +if ($cid) { + $_section[0][0] = _AT('edit_content'); +} else { + $_section[0][0] = _AT('add_content'); +} + +if($current_tab == 0) { + $_custom_head .= ' + + + '; +} + +if ($cid) { + if (isset($contentManager)) $content_row = $contentManager->getContentPage($cid); + + if (!$content_row || !isset($contentManager)) { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('MISSING_CONTENT'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + + $path = $contentManager->getContentPath($cid); + $content_tests = $contentManager->getContentTestsAssoc($cid); + + if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { + $course_base_href = 'get.php/'; + } else { + $course_base_href = 'content/' . $_SESSION['course_id'] . '/'; + } + + if ($content_row['content_path']) { + $content_base_href .= $content_row['content_path'].'/'; + } +} else { + if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { + $content_base_href = 'get.php/'; + } else { + $content_base_href = 'content/' . $_SESSION['course_id'] . '/'; + } +} + +/* TAB 0 --> Content *//* TAB 2 --> Page */ +if (($current_tab == 0) || ($current_tab == 2)) { + if ($_POST['formatting'] == null){ + // this is a fresh load from just logged in + if (isset($_SESSION['prefs']['PREF_CONTENT_EDITOR']) && $_SESSION['prefs']['PREF_CONTENT_EDITOR'] == 0) { + $_POST['formatting'] = 0; + } else { + $_POST['formatting'] = 1; + } + } +} + +require(TR_INCLUDE_PATH.'header.inc.php'); + +if ($current_tab == 0 || $current_tab == 2) +{ + $simple = true; + if ($_POST['complexeditor'] == '1') { + $simple = false; + } + load_editor($simple, false, "none"); +} + +$pid = intval($_REQUEST['pid']); +?> + +
    +getContent($pid))+1; + } else { + $_POST['pid'] = 0; + $_POST['ordering'] = count($contentManager->getContent(0))+1; + } + } + } + + echo ''; + echo ''; + echo ''; + if ($_REQUEST['sub'] == 1) + { + echo ''; + echo ''; + } + echo ''; + if (($current_tab != 0) && (($_current_tab != 2))) { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + + + } + + echo ''; + echo ''; + + echo ''; + + echo ''; + + echo ''; + + //content test association + echo ''; + + /* get glossary terms */ + + // adapted content + $sql = "SELECT pr.primary_resource_id, prt.type_id + FROM ".TABLE_PREFIX."primary_resources pr, ". + TABLE_PREFIX."primary_resources_types prt + WHERE pr.content_id = ? + AND pr.language_code = ? + AND pr.primary_resource_id = prt.primary_resource_id"; + $values = array($cid, $_SESSION['lang']); + $types = "is"; + $types = $dao->execute($sql, $values, $types); + + $i = 0; + if (is_array($types)) { + foreach ($types as $type) { + $row_alternatives['alt_'.$type['primary_resource_id'].'_'.$type['type_id']] = 1; + } + } + + if ($current_tab != 2 && isset($_POST['use_post_for_alt'])) + { + echo ''; + if (is_array($_POST)) { + foreach ($_POST as $alt_id => $alt_value) { + if (substr($alt_id, 0 ,4) == 'alt_'){ + echo ''; + } + } + } + } + + //tests + if ($current_tab != 5){ + // set content associated tests + if (isset($_POST['visited_tests'])) { + echo ''."\n"; + if (is_array($_POST['tid'])) { + foreach ($_POST['tid'] as $i=>$tid){ + echo ''; + } + } + } else { + $i = 0; + if (is_array($content_tests)) { + foreach ($content_tests as $content_test_row) { + echo ''; + } + } + } + } + + if ($do_check) { + $changes_made = check_for_changes($content_row, $row_alternatives); + } +?> + +
    + +
    + +
    + + +
    + + + /> + +
    + + +
    + /> +
    + + + + +
    +
    + + diff --git a/home/editor/edit_content_folder.php b/home/editor/edit_content_folder.php index e32c9a13..fda3a065 100644 --- a/home/editor/edit_content_folder.php +++ b/home/editor/edit_content_folder.php @@ -1,179 +1,192 @@ - 0 && isset($contentManager)) { - $content_row = $contentManager->getContentPage($cid); -} - -// save changes -if ($_POST['submit']) -{ - if ($_POST['title'] == '') { - $msg->addError(array('EMPTY_FIELDS', _AT('title'))); - } - - if (!$msg->containsErrors()) - { - $_POST['title'] = $content_row['title'] = $_POST['title']; - - if ($cid > 0) - { // edit existing content - $err = $contentManager->editContent($cid, - $_POST['title'], - '', - '', - $content_row['formatting'], - '', - $content_row['use_customized_head'], - ''); - } - else - { // add new content - // find out ordering and content_parent_id - if ($pid) - { // insert sub content folder - $ordering = count($contentManager->getContent($pid))+1; - } - else - { // insert a top content folder - $ordering = count($contentManager->getContent(0)) + 1; - $pid = 0; - } - - $cid = $contentManager->addContent($_SESSION['course_id'], - $pid, - $ordering, - $_POST['title'], - '', - '', - '', - 0, - '', - 0, - '', - 1, - CONTENT_TYPE_FOLDER); - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: '.$_base_path.'home/editor/edit_content_folder.php?_cid='.$cid); - exit; - } -} - -if ($cid > 0) -{ // edit existing content folder - if (!$content_row || !isset($contentManager)) { - $_pages['home/editor/edit_content_folder.php']['title_var'] = 'missing_content'; - $_pages['home/editor/edit_content_folder.php']['parent'] = 'index.php'; - $_pages['home/editor/edit_content_folder.php']['ignore'] = true; - - require(TR_INCLUDE_PATH.'header.inc.php'); - - $msg->addError('MISSING_CONTENT'); - $msg->printAll(); - - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } /* else: */ - - /* the "heading navigation": */ - $path = $contentManager->getContentPath($cid); - - if ($content_row['content_path']) { - $content_base_href = $content_row['content_path'].'/'; - } - - $parent_headings = ''; - $num_in_path = count($path); - - /* the page title: */ - $page_title = ''; - $page_title .= $content_row['title']; - - for ($i=0; $i<$num_in_path; $i++) { - $content_info = $path[$i]; - if ($_SESSION['prefs']['PREF_NUMBERING']) { - if ($contentManager->_menu_info[$content_info['content_id']]['content_parent_id'] == 0) { - $top_num = $contentManager->_menu_info[$content_info['content_id']]['ordering']; - $parent_headings .= $top_num; - } else { - $top_num = $top_num.'.'.$contentManager->_menu_info[$content_info['content_id']]['ordering']; - $parent_headings .= $top_num; - } - if ($_SESSION['prefs']['PREF_NUMBERING']) { - $path[$i]['content_number'] = $top_num . ' '; - } - $parent_headings .= ' '; - } - } - - if ($_SESSION['prefs']['PREF_NUMBERING']) { - if ($top_num != '') { - $top_num = $top_num.'.'.$content_row['ordering']; - $page_title .= $top_num.' '; - } else { - $top_num = $content_row['ordering']; - $page_title .= $top_num.' '; - } - } - - $parent = 0; - - reset($path); - $first_page = current($path); - - ContentUtility::saveLastCid($cid); - - if (isset($top_num) && $top_num != (int) $top_num) { - $top_num = substr($top_num, 0, strpos($top_num, '.')); - } - $_tool_shortcuts = ContentUtility::getToolShortcuts($content_row); // used by header.tmpl.php - - // display pre-tests - $savant->assign('ftitle', $content_row['title']); - $savant->assign('cid', $cid); -} - -if ($pid > 0 || !isset($pid)) { - $savant->assign('pid', $pid); - $savant->assign('course_id', $_course_id); -} - -$onload = "document.form.title.focus();"; -require(TR_INCLUDE_PATH.'header.inc.php'); -$savant->display('home/editor/edit_content_folder.tmpl.php'); -require(TR_INCLUDE_PATH.'footer.inc.php'); - -//save last visit page. -$_SESSION['last_visited_page'] = $server_protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; -?> \ No newline at end of file + 0 && isset($contentManager)) { + $content_row = $contentManager->getContentPage($cid); +} + +// save changes +if ($_POST['submit']) +{ + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + if ($_POST['title'] == '') { + $msg->addError(array('EMPTY_FIELDS', _AT('title'))); + } + + if (!$msg->containsErrors()) + { + $_POST['title'] = $content_row['title'] = $_POST['title']; + + if ($cid > 0) + { // edit existing content + $err = $contentManager->editContent($cid, + $_POST['title'], + '', + '', + $content_row['formatting'], + '', + $content_row['use_customized_head'], + ''); + } + else + { // add new content + // find out ordering and content_parent_id + if ($pid) + { // insert sub content folder + $ordering = count($contentManager->getContent($pid))+1; + } + else + { // insert a top content folder + $ordering = count($contentManager->getContent(0)) + 1; + $pid = 0; + } + + $cid = $contentManager->addContent($_SESSION['course_id'], + $pid, + $ordering, + $_POST['title'], + '', + '', + '', + 0, + '', + 0, + '', + 1, + CONTENT_TYPE_FOLDER); + } + + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: '.$_base_path.'home/editor/edit_content_folder.php?_cid='.$cid); + exit; + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +if ($cid > 0) +{ // edit existing content folder + if (!$content_row || !isset($contentManager)) { + $_pages['home/editor/edit_content_folder.php']['title_var'] = 'missing_content'; + $_pages['home/editor/edit_content_folder.php']['parent'] = 'index.php'; + $_pages['home/editor/edit_content_folder.php']['ignore'] = true; + + require(TR_INCLUDE_PATH.'header.inc.php'); + + $msg->addError('MISSING_CONTENT'); + $msg->printAll(); + + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } /* else: */ + + /* the "heading navigation": */ + $path = $contentManager->getContentPath($cid); + + if ($content_row['content_path']) { + $content_base_href = $content_row['content_path'].'/'; + } + + $parent_headings = ''; + $num_in_path = count($path); + + /* the page title: */ + $page_title = ''; + $page_title .= $content_row['title']; + + for ($i=0; $i<$num_in_path; $i++) { + $content_info = $path[$i]; + if ($_SESSION['prefs']['PREF_NUMBERING']) { + if ($contentManager->_menu_info[$content_info['content_id']]['content_parent_id'] == 0) { + $top_num = $contentManager->_menu_info[$content_info['content_id']]['ordering']; + $parent_headings .= $top_num; + } else { + $top_num = $top_num.'.'.$contentManager->_menu_info[$content_info['content_id']]['ordering']; + $parent_headings .= $top_num; + } + if ($_SESSION['prefs']['PREF_NUMBERING']) { + $path[$i]['content_number'] = $top_num . ' '; + } + $parent_headings .= ' '; + } + } + + if ($_SESSION['prefs']['PREF_NUMBERING']) { + if ($top_num != '') { + $top_num = $top_num.'.'.$content_row['ordering']; + $page_title .= $top_num.' '; + } else { + $top_num = $content_row['ordering']; + $page_title .= $top_num.' '; + } + } + + $parent = 0; + + reset($path); + $first_page = current($path); + + ContentUtility::saveLastCid($cid); + + if (isset($top_num) && $top_num != (int) $top_num) { + $top_num = substr($top_num, 0, strpos($top_num, '.')); + } + $_tool_shortcuts = ContentUtility::getToolShortcuts($content_row); // used by header.tmpl.php + + // display pre-tests + $savant->assign('ftitle', $content_row['title']); + $savant->assign('cid', $cid); +} + +if ($pid > 0 || !isset($pid)) { + $savant->assign('pid', $pid); + $savant->assign('course_id', $_course_id); +} + +$onload = "document.form.title.focus();"; +require(TR_INCLUDE_PATH.'header.inc.php'); +$savant->display('home/editor/edit_content_folder.tmpl.php'); +require(TR_INCLUDE_PATH.'footer.inc.php'); + +//save last visit page. +$_SESSION['last_visited_page'] = $server_protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; +?> diff --git a/home/editor/edit_content_struct.php b/home/editor/edit_content_struct.php index f01ed62a..dd41cb57 100644 --- a/home/editor/edit_content_struct.php +++ b/home/editor/edit_content_struct.php @@ -1,202 +1,216 @@ -'."\n"; - - -global $_content_id, $contentManager, $_course_id; -$cid = $_content_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR); - -if (isset($_GET['pid'])) $pid = intval($_GET['pid']); -if (isset($_POST['_course_id'])) $_course_id = intval($_POST['_course_id']); - -if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { - $course_base_href = 'get.php/'; -} else { - $course_base_href = 'content/' . $_course_id . '/'; -} - - - -if ($cid > 0 && isset($contentManager)) { - $content_row = $contentManager->getContentPage($cid); -} - -// save changes -if ($_POST['submit']) -{ - if ($_POST['title'] == '') { - $msg->addError(array('EMPTY_FIELDS', _AT('title'))); - } - - if (!$msg->containsErrors()) - { - $_POST['title'] = $content_row['title'] = htmlspecialchars($_POST['title'], ENT_QUOTES, 'UTF-8'); - - if ($cid > 0) - { // edit existing content - $err = $contentManager->editContent($cid, - $_POST['title'], - '', - '', - $content_row['formatting'], - '', - $content_row['use_customized_head'], - ''); - } - else - { // add new content - // find out ordering and content_parent_id - if ($pid) - { // insert sub content folder - $ordering = count($contentManager->getContent($pid))+1; - } - else - { // insert a top content folder - $ordering = count($contentManager->getContent(0)) + 1; - $pid = 0; - } - - $cid = $contentManager->addContent($_SESSION['course_id'], - $pid, - $ordering, - $_POST['title'], - '', - '', - '', - 0, - '', - 0, - '', - 1, - CONTENT_TYPE_FOLDER); - - $struc_manag = new StructureManager($_POST['title']); - $page_temp = $struc_manag->get_page_temp(); - - $struc_manag->createStruct($page_temp, $cid, $_course_id); - - - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: '.$_base_path.'home/editor/edit_content_folder.php?_cid='.$cid); - exit; - } -} - -if ($cid > 0) -{ // edit existing content folder - - - if (!$content_row || !isset($contentManager)) { - $_pages['home/editor/edit_content_folder.php']['title_var'] = 'missing_content'; - $_pages['home/editor/edit_content_folder.php']['parent'] = 'index.php'; - $_pages['home/editor/edit_content_folder.php']['ignore'] = true; - - require(TR_INCLUDE_PATH.'header.inc.php'); - - $msg->addError('MISSING_CONTENT'); - $msg->printAll(); - - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } /* else: */ - - /* the "heading navigation": */ - $path = $contentManager->getContentPath($cid); - - if ($content_row['content_path']) { - $content_base_href = $content_row['content_path'].'/'; - } - - $parent_headings = ''; - $num_in_path = count($path); - - /* the page title: */ - $page_title = ''; - $page_title .= $content_row['title']; - - - for ($i=0; $i<$num_in_path; $i++) { - $content_info = $path[$i]; - if ($_SESSION['prefs']['PREF_NUMBERING']) { - if ($contentManager->_menu_info[$content_info['content_id']]['content_parent_id'] == 0) { - $top_num = $contentManager->_menu_info[$content_info['content_id']]['ordering']; - $parent_headings .= $top_num; - } else { - $top_num = $top_num.'.'.$contentManager->_menu_info[$content_info['content_id']]['ordering']; - $parent_headings .= $top_num; - } - if ($_SESSION['prefs']['PREF_NUMBERING']) { - $path[$i]['content_number'] = $top_num . ' '; - } - $parent_headings .= ' '; - } - } - - - - if ($_SESSION['prefs']['PREF_NUMBERING']) { - if ($top_num != '') { - $top_num = $top_num.'.'.$content_row['ordering']; - $page_title .= $top_num.' '; - } else { - $top_num = $content_row['ordering']; - $page_title .= $top_num.' '; - } - } - - - $parent = 0; - - reset($path); - $first_page = current($path); - - ContentUtility::saveLastCid($cid); - - if (isset($top_num) && $top_num != (int) $top_num) { - $top_num = substr($top_num, 0, strpos($top_num, '.')); - } - $_tool_shortcuts = ContentUtility::getToolShortcuts($content_row); // used by header.tmpl.php - - // display pre-tests - $savant->assign('ftitle', $content_row['title']); - $savant->assign('cid', $cid); -} - - -if ($pid > 0 || !isset($pid)) { - $savant->assign('pid', $pid); - $savant->assign('course_id', $_course_id); -} - -$onload = "document.form.title.focus();"; -require(TR_INCLUDE_PATH.'header.inc.php'); -$savant->display('home/editor/edit_content_struct.tmpl.php'); -require(TR_INCLUDE_PATH.'footer.inc.php'); - - - - -//save last visit page. -$_SESSION['last_visited_page'] = $server_protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; -?> - +'."\n"; + + +global $_content_id, $contentManager, $_course_id; +$cid = $_content_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR); + +if (isset($_GET['pid'])) $pid = intval($_GET['pid']); +if (isset($_POST['_course_id'])) $_course_id = intval($_POST['_course_id']); + +if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { + $course_base_href = 'get.php/'; +} else { + $course_base_href = 'content/' . $_course_id . '/'; +} + + + +if ($cid > 0 && isset($contentManager)) { + $content_row = $contentManager->getContentPage($cid); +} + +// save changes +if ($_POST['submit']) +{ + if ($_POST['title'] == '') { + $msg->addError(array('EMPTY_FIELDS', _AT('title'))); + } + + if (!$msg->containsErrors()) + { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['title'] = $content_row['title'] = $purifier->purify(htmlspecialchars($_POST['title'], ENT_QUOTES, 'UTF-8')); + + if ($cid > 0) + { // edit existing content + $err = $contentManager->editContent($cid, + $_POST['title'], + '', + '', + $content_row['formatting'], + '', + $content_row['use_customized_head'], + ''); + } + else + { // add new content + // find out ordering and content_parent_id + if ($pid) + { // insert sub content folder + $ordering = count($contentManager->getContent($pid))+1; + } + else + { // insert a top content folder + $ordering = count($contentManager->getContent(0)) + 1; + $pid = 0; + } + + $cid = $contentManager->addContent($_SESSION['course_id'], + $pid, + $ordering, + $_POST['title'], + '', + '', + '', + 0, + '', + 0, + '', + 1, + CONTENT_TYPE_FOLDER); + + $struc_manag = new StructureManager($_POST['title']); + $page_temp = $struc_manag->get_page_temp(); + + $struc_manag->createStruct($page_temp, $cid, $_course_id); + + + } + + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: '.$_base_path.'home/editor/edit_content_folder.php?_cid='.$cid); + exit; + } else + { + $msg->addError('INVALID_TOKEN'); + } + } +} + +if ($cid > 0) +{ // edit existing content folder + + + if (!$content_row || !isset($contentManager)) { + $_pages['home/editor/edit_content_folder.php']['title_var'] = 'missing_content'; + $_pages['home/editor/edit_content_folder.php']['parent'] = 'index.php'; + $_pages['home/editor/edit_content_folder.php']['ignore'] = true; + + require(TR_INCLUDE_PATH.'header.inc.php'); + + $msg->addError('MISSING_CONTENT'); + $msg->printAll(); + + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } /* else: */ + + /* the "heading navigation": */ + $path = $contentManager->getContentPath($cid); + + if ($content_row['content_path']) { + $content_base_href = $content_row['content_path'].'/'; + } + + $parent_headings = ''; + $num_in_path = count($path); + + /* the page title: */ + $page_title = ''; + $page_title .= $content_row['title']; + + + for ($i=0; $i<$num_in_path; $i++) { + $content_info = $path[$i]; + if ($_SESSION['prefs']['PREF_NUMBERING']) { + if ($contentManager->_menu_info[$content_info['content_id']]['content_parent_id'] == 0) { + $top_num = $contentManager->_menu_info[$content_info['content_id']]['ordering']; + $parent_headings .= $top_num; + } else { + $top_num = $top_num.'.'.$contentManager->_menu_info[$content_info['content_id']]['ordering']; + $parent_headings .= $top_num; + } + if ($_SESSION['prefs']['PREF_NUMBERING']) { + $path[$i]['content_number'] = $top_num . ' '; + } + $parent_headings .= ' '; + } + } + + + + if ($_SESSION['prefs']['PREF_NUMBERING']) { + if ($top_num != '') { + $top_num = $top_num.'.'.$content_row['ordering']; + $page_title .= $top_num.' '; + } else { + $top_num = $content_row['ordering']; + $page_title .= $top_num.' '; + } + } + + + $parent = 0; + + reset($path); + $first_page = current($path); + + ContentUtility::saveLastCid($cid); + + if (isset($top_num) && $top_num != (int) $top_num) { + $top_num = substr($top_num, 0, strpos($top_num, '.')); + } + $_tool_shortcuts = ContentUtility::getToolShortcuts($content_row); // used by header.tmpl.php + + // display pre-tests + $savant->assign('ftitle', $content_row['title']); + $savant->assign('cid', $cid); +} + + +if ($pid > 0 || !isset($pid)) { + $savant->assign('pid', $pid); + $savant->assign('course_id', $_course_id); +} + +$onload = "document.form.title.focus();"; +require(TR_INCLUDE_PATH.'header.inc.php'); +$savant->display('home/editor/edit_content_struct.tmpl.php'); +require(TR_INCLUDE_PATH.'footer.inc.php'); + + + + +//save last visit page. +$_SESSION['last_visited_page'] = $server_protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; +?> + diff --git a/home/editor/editor_tab_functions.inc.php b/home/editor/editor_tab_functions.inc.php index c5f73ff4..e775f8d9 100644 --- a/home/editor/editor_tab_functions.inc.php +++ b/home/editor/editor_tab_functions.inc.php @@ -1,522 +1,524 @@ - $strValue) - { - if (strtoupper($strItem) == strtoupper($strValue)) - { - return $key; - } - } - return false; -} - - -function get_tabs() { -/* Check if the page template_layout and are enabled or disabled */ - include_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php'); - $dao = new DAO(); - - $inc=0; - $tabs[$inc] = array('content', 'edit.inc.php', 'n'); - - $sql="SELECT value FROM ".TABLE_PREFIX."config WHERE name='enable_template_layout'"; - $result=$dao->execute($sql); - if(is_array($result)) - { - foreach ($result as $support) { - if($support['value']==TR_STATUS_ENABLED) - $tabs[++$inc] = array('layouts', 'layout.inc.php', 'l'); - } - } - $sql="SELECT value FROM ".TABLE_PREFIX."config WHERE name='enable_template_page'"; - $result=$dao->execute($sql); - if(is_array($result)) - { - foreach ($result as $support) { - if($support['value']==TR_STATUS_ENABLED) - $tabs[++$inc] = array('page_templates', 'page_template.inc.php', 'g'); - } - } - - $tabs[++$inc] = array('metadata', 'properties.inc.php', 'p'); - $tabs[++$inc] = array('alternative_content', 'alternatives.inc.php', 'a'); - $tabs[++$inc] = array('tests', 'tests.inc.php', 't'); - return $tabs; -} - - -function output_tabs($current_tab, $changes) { - global $_base_path; - $tabs = get_tabs(); - $num_tabs = count($tabs); -?> - - - - - - - - - - - - -
    - - <?php echo _AT('usaved_changes_made'); ?> - - -   - - <?php echo _AT('usaved_changes_made'); ?> - - - '; ?> -   
    - 1) return; - - include_once(TR_INCLUDE_PATH.'classes/A4a/A4a.class.php'); - include_once(TR_INCLUDE_PATH.'classes/XML/XML_HTMLSax/XML_HTMLSax.php'); /* for XML_HTMLSax */ - include_once(TR_INCLUDE_PATH.'classes/ContentOutputParser.class.php'); /* for parser */ - - // initialize content_base_href; used in format_content - if (!isset($content_base_href)) { - $content_row = $contentManager->getContentPage($cid); - // return if the cid is not found - if (!is_array($content_row)) { - return; - } - $content_base_href = $content_row["content_path"].'/'; - } - - $body = ContentUtility::formatContent($content, $formatting); - - $handler = new ContentOutputParser(); - $parser = new XML_HTMLSax(); - $parser->set_object($handler); - $parser->set_element_handler('openHandler','closeHandler'); - - $my_files = array(); - $parser->parse($body); - $my_files = array_unique($my_files); - - foreach ($my_files as $file) { - /* filter out full urls */ - $url_parts = @parse_url($file); - - // file should be relative to content - if ((substr($file, 0, 1) == '/')) { - continue; - } - - // The URL of the movie from youtube.com has been converted above in embed_media(). - // For example: http://www.youtube.com/watch?v=a0ryB0m0MiM is converted to - // http://www.youtube.com/v/a0ryB0m0MiM to make it playable. This creates the problem - // that the parsed-out url (http://www.youtube.com/v/a0ryB0m0MiM) does not match with - // the URL saved in content table (http://www.youtube.com/watch?v=a0ryB0m0MiM). - // The code below is to convert the URL back to original. - $file = ContentUtility::convertYoutubePlayURLToWatchURL($file); - - $resources[] = convertAmp($file); // converts & to & - } - - $a4a = new A4a($cid); - $db_primary_resources = $a4a->getPrimaryResources(); - - // clean up the removed resources - foreach ($db_primary_resources as $primary_rid=>$db_resource){ - //if this file from our table is not found in the $resource, then it's not used. - if(count($resources) == 0 || !in_array($db_resource['resource'], $resources)){ - // The following ends up deleting all original resourse type from the db - // Why is it here? - //$a4a->deletePrimaryResource($primary_rid); - } - } - - if (count($resources) == 0) return; - - // insert the new resources - foreach($resources as $primary_resource) - { - if (!$a4a->getPrimaryResourceByName($primary_resource)){ - $a4a->setPrimaryResource($cid, $primary_resource, $_SESSION['lang']); - } - } -} - -// save all changes to the DB -function save_changes($redir, $current_tab) { - global $contentManager, $msg, $_course_id, $_content_id; - - $_POST['pid'] = intval($_POST['pid']); - $_POST['_cid'] = intval($_POST['_cid']); - - - $_POST['alternatives'] = intval($_POST['alternatives']); - - $_POST['title'] = trim($_POST['title']); - $_POST['head'] = trim($_POST['head']); - $_POST['use_customized_head'] = isset($_POST['use_customized_head'])?$_POST['use_customized_head']:0; - $_POST['body_text'] = stripslashes(trim($_POST['body_text'])); - $_POST['weblink_text'] = trim($_POST['weblink_text']); - $_POST['formatting'] = intval($_POST['formatting']); - $_POST['keywords'] = stripslashes(trim($_POST['keywords'])); - $_POST['test_message'] = trim($_POST['test_message']); - - //if weblink is selected, use it - if ($_POST['formatting']==CONTENT_TYPE_WEBLINK) { - $url = $_POST['weblink_text']; - $validated_url = isValidURL($url); - if (!validated_url || $validated_url !== $url) { - $msg->addError(array('INVALID_INPUT', _AT('weblink'))); - } else { - $_POST['body_text'] = $url; - $content_type_pref = CONTENT_TYPE_WEBLINK; - } - } else { - $content_type_pref = CONTENT_TYPE_CONTENT; - } - - // add or edit content - if ($_POST['_cid']) { - /* editing an existing page */ - $err = $contentManager->editContent($_POST['_cid'], $_POST['title'], $_POST['body_text'], - $_POST['keywords'], $_POST['formatting'], - $_POST['head'], $_POST['use_customized_head'], - $_POST['test_message']); - - - $cid = $_POST['_cid']; - } else { - /* insert new */ - $cid = $contentManager->addContent($_course_id, - $_POST['pid'], - $_POST['ordering'], - $_POST['title'], - $_POST['body_text'], - $_POST['keywords'], - $_POST['related'], - $_POST['formatting'], - $_POST['head'], - $_POST['use_customized_head'], - $_POST['test_message'], - $content_type_pref); - - $_POST['_cid'] = $cid; - $_REQUEST['_cid'] = $cid; - } - - - - - if ($cid == 0) return; - - // re-populate a4a tables based on the new content - populate_a4a($cid, $orig_body_text, $_POST['formatting']); - - - if (isset($_GET['tab'])) { - $current_tab = intval($_GET['tab']); - } - if (isset($_POST['current_tab'])) { - $current_tab = intval($_POST['current_tab']); - } - - // adapted content: save primary content type - if (isset($_POST['use_post_for_alt'])) - { - include_once(TR_INCLUDE_PATH.'classes/DAO/PrimaryResourcesTypesDAO.class.php'); - $primaryResourcesTypesDAO = new PrimaryResourcesTypesDAO(); - - // 1. delete old primary content type - - $sql = "DELETE FROM ".TABLE_PREFIX."primary_resources_types - WHERE primary_resource_id in - (SELECT DISTINCT primary_resource_id - FROM ".TABLE_PREFIX."primary_resources - WHERE content_id=? - AND language_code=?)"; - $values=array($cid, $_SESSION['lang']); - $types = "ii"; - $primaryResourcesTypesDAO->execute($sql, $values, $types); - - // 2. insert the new primary content type - - $sql = "SELECT pr.primary_resource_id, rt.type_id - FROM ".TABLE_PREFIX."primary_resources pr, ". - TABLE_PREFIX."resource_types rt - WHERE pr.content_id = ? - AND pr.language_code = ?"; - $values = array($cid, $_SESSION['lang']); - $types = "is"; - $all_types_rows = $primaryResourcesTypesDAO->execute($sql, $values, $types); - - if (is_array($all_types_rows)) { - foreach ($all_types_rows as $type) { - if (isset($_POST['alt_'.$type['primary_resource_id'].'_'.$type['type_id']])) - { - $primaryResourcesTypesDAO->Create($type['primary_resource_id'], $type['type_id']); - } - } - } - } - - include_once(TR_INCLUDE_PATH.'classes/DAO/ContentTestsAssocDAO.class.php'); - $contentTestsAssocDAO = new ContentTestsAssocDAO(); - $test_rows = $contentTestsAssocDAO->getByContent($_POST['_cid']); - $db_test_array = array(); - if (is_array($test_rows)) { - foreach ($test_rows as $row) { - $db_test_array[] = $row['test_id']; - } - } - - if (is_array($_POST['tid']) && sizeof($_POST['tid']) > 0){ - $toBeDeleted = array_diff($db_test_array, $_POST['tid']); - $toBeAdded = array_diff($_POST['tid'], $db_test_array); - //Delete entries - if (!empty($toBeDeleted)){ - $num_of_ids = count($toBeDeleted); - $sql = 'DELETE FROM '. TABLE_PREFIX .'content_tests_assoc WHERE content_id=? AND test_id IN ('.substr(str_repeat("? , ", $num_of_ids), 0, -2).')'; - $values = $toBeDeleted; - $types = "i"; - $types .= str_pad("", $num_of_ids, "i"); - $contentTestsAssocDAO->execute($sql, $values, $types); - } - - //Add entries - if (!empty($toBeAdded)){ - foreach ($toBeAdded as $i => $tid){ - $tid = intval($tid); - - if ($contentTestsAssocDAO->Create($_POST['_cid'], $tid) === false){ - $msg->addError('DB_NOT_UPDATED'); - } - } - } - } else { - //All tests has been removed. - $contentTestsAssocDAO->DeleteByContentID($_POST['_cid']); - } - //End Add test - - if (!$msg->containsErrors() && $redir) { - $_SESSION['save_n_close'] = $_POST['save_n_close']; - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: '.basename($_SERVER['PHP_SELF']).'?_cid='.$cid.SEP.'close='.addslashes($_POST['save_n_close']).SEP.'tab='.addslashes($_POST['current_tab']).SEP.'displayhead='.addslashes($_POST['displayhead']).SEP.'alternatives='.addslashes($_POST['alternatives'])); - exit; - } else { - return; - } -} - -function check_for_changes($row, $row_alternatives) { - global $contentManager, $cid, $glossary, $glossary_ids_related; - - $changes = array(); - - if ($row && strcmp(trim(addslashes($_POST['title'])), addslashes($row['title']))) { - $changes[0] = true; - } else if (!$row && $_POST['title']) { - $changes[0] = true; - } - - if ($row && strcmp(addslashes(trim($_POST['head'])), trim(addslashes($row['head'])))) { - $changes[0] = true; - } else if (!$row && $_POST['head']) { - $changes[0] = true; - } - - if ($row && strcmp(addslashes(trim($_POST['body_text'])), trim(addslashes($row['text'])))) { - $changes[0] = true; - } else if (!$row && $_POST['body_text']) { - $changes[0] = true; - } - - if ($row && strcmp(addslashes(trim($_POST['weblink_text'])), trim(addslashes($row['text'])))) { - $changes[0] = true; - } else if (!$row && $_POST['weblink_text']) { - $changes[0] = true; - } - - /* use customized head: */ - if ($row && isset($_POST['use_customized_head']) && ($_POST['use_customized_head'] != $row['use_customized_head'])) { - $changes[0] = true; - } - - /* formatting: */ - if ($row && strcmp(trim($_POST['formatting']), $row['formatting'])) { - $changes[0] = true; - } else if (!$row && $_POST['formatting']) { - $changes[0] = true; - } - - /* keywords */ - if ($row && strcmp(trim($_POST['keywords']), $row['keywords'])) { - $changes[1] = true; - } else if (!$row && $_POST['keywords']) { - $changes[1] = true; - } - - /* adapted content */ - if (isset($_POST['use_post_for_alt'])) - { - foreach ($_POST as $alt_id => $alt_value) { - if (substr($alt_id, 0 ,4) == 'alt_' && $alt_value != $row_alternatives[$alt_id]){ - $changes[2] = true; - break; - } - } - } - - /* test & survey */ - if ($row && isset($_POST['test_message']) && $_POST['test_message'] != $row['test_message']){ - $changes[3] = true; - } - - $content_tests = $contentManager->getContentTestsAssoc($cid); - - if (isset($_POST['visited_tests'])) { - if (!is_array($content_tests) && is_array($_POST['tid'])) { - $changes[3] = true; - } - if (is_array($content_tests)) { - for ($i = 0; $i < count($content_tests); $i++) { - if ($content_tests[$i]['test_id'] <> $_POST['tid'][$i]) { - $changes[3] = true; - break; - } - } - } - } - - return $changes; -} - -function paste_from_file() { - global $msg; - - include_once(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php'); - if ($_FILES['uploadedfile_paste']['name'] == '') { - $msg->addError('FILE_NOT_SELECTED'); - return; - } - if ($_FILES['uploadedfile_paste']['name'] - && (($_FILES['uploadedfile_paste']['type'] == 'text/plain') - || ($_FILES['uploadedfile_paste']['type'] == 'text/html')) ) - { - - $path_parts = pathinfo($_FILES['uploadedfile_paste']['name']); - $ext = strtolower($path_parts['extension']); - - if (in_array($ext, array('html', 'htm'))) { - $_POST['body_text'] = file_get_contents($_FILES['uploadedfile_paste']['tmp_name']); - - /* get the of this page */ - - $start_pos = strpos(strtolower($_POST['body_text']), ''); - $end_pos = strpos(strtolower($_POST['body_text']), ''); - - if (($start_pos !== false) && ($end_pos !== false)) { - $start_pos += strlen(''); - $_POST['title'] = trim(substr($_POST['body_text'], $start_pos, $end_pos-$start_pos)); - } - unset($start_pos); - unset($end_pos); - - $_POST['head'] = ContentUtility::getHtmlHeadByTag($_POST['body_text'], array("link", "style", "script")); - if (strlen(trim($_POST['head'])) > 0) - $_POST['use_customized_head'] = 1; - else - $_POST['use_customized_head'] = 0; - - $_POST['body_text'] = ContentUtility::getHtmlBody($_POST['body_text']); - - $msg->addFeedback('FILE_PASTED'); - } else if ($ext == 'txt') { - $_POST['body_text'] = file_get_contents($_FILES['uploadedfile_paste']['tmp_name']); - //LAW - $msg->addFeedback('FILE_PASTED'); - - } - } else { - $msg->addError('BAD_FILE_TYPE'); - } - - return; -} - -//for accessibility checker -function write_temp_file() { - global $_POST, $msg; - - if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { - $content_base = 'get.php/'; - } else { - $content_base = 'content/' . $_SESSION['course_id'] . '/'; - } - - if ($_POST['content_path']) { - $content_base .= $_POST['content_path'] . '/'; - } - - $file_name = $_POST['_cid'].'.html'; - - if ($handle = fopen(TR_CONTENT_DIR . $file_name, 'wb+')) { - - if (!@fwrite($handle, stripslashes($_POST['body_text']))) { - $msg->addError('FILE_NOT_SAVED'); - } - } else { - $msg->addError('FILE_NOT_SAVED'); - } - $msg->printErrors(); -} -?> +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2013 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); + +if (!defined('TR_INCLUDE_PATH')) { exit; } + +function in_array_cin($strItem, $arItems) +{ + foreach ($arItems as $key => $strValue) + { + if (strtoupper($strItem) == strtoupper($strValue)) + { + return $key; + } + } + return false; +} + + +function get_tabs() { +/* Check if the page template_layout and are enabled or disabled */ + include_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php'); + $dao = new DAO(); + + $inc=0; + $tabs[$inc] = array('content', 'edit.inc.php', 'n'); + + $sql="SELECT value FROM ".TABLE_PREFIX."config WHERE name='enable_template_layout'"; + $result=$dao->execute($sql); + if(is_array($result)) + { + foreach ($result as $support) { + if($support['value']==TR_STATUS_ENABLED) + $tabs[++$inc] = array('layouts', 'layout.inc.php', 'l'); + } + } + $sql="SELECT value FROM ".TABLE_PREFIX."config WHERE name='enable_template_page'"; + $result=$dao->execute($sql); + if(is_array($result)) + { + foreach ($result as $support) { + if($support['value']==TR_STATUS_ENABLED) + $tabs[++$inc] = array('page_templates', 'page_template.inc.php', 'g'); + } + } + + $tabs[++$inc] = array('metadata', 'properties.inc.php', 'p'); + $tabs[++$inc] = array('alternative_content', 'alternatives.inc.php', 'a'); + $tabs[++$inc] = array('tests', 'tests.inc.php', 't'); + return $tabs; +} + + +function output_tabs($current_tab, $changes) { + global $_base_path; + $tabs = get_tabs(); + $num_tabs = count($tabs); +?> + <table class="etabbed-table"> + <tr> + <?php + for ($i=0; $i < $num_tabs; $i++): + if ($current_tab == $i):?> + <td class="editor_tab_selected"> + <?php if ($changes[$i]): ?> + <img src="<?php echo $_base_path; ?>images/changes_bullet.gif" alt="<?php echo _AT('usaved_changes_made'); ?>" height="12" width="15" /> + <?php endif; ?> + <?php echo _AT($tabs[$i][0]); ?> + </td> + <td class="tab-spacer"> </td> + <?php else: ?> + <td class="editor_tab"> + <?php if ($changes[$i]): ?> + <img src="<?php echo $_base_path; ?>images/changes_bullet.gif" alt="<?php echo _AT('usaved_changes_made'); ?>" height="12" width="15" /> + <?php endif; ?> + + <?php echo '<input type="submit" name="button_'.$i.'" value="'._AT($tabs[$i][0]).'" title="'._AT($tabs[$i][0]).' - alt '.$tabs[$i][2].'" class="editor_buttontab" accesskey="'.$tabs[$i][2].'" onmouseover="this.style.cursor=\'pointer\';" '.$clickEvent.' />'; ?> + </td> + <td class="tab-spacer"> </td> + <?php endif; ?> + <?php endfor; ?> + <td > </td> + </tr> + </table> +<?php } +/** + * Strips all tags and encodes special characters in the URL + * Returns false if the URL is invalid + * + * @param string $url + * @return mixed - returns a stripped and encoded URL or false if URL is invalid + */ +function isValidURL($url) { + if (substr($url,0,4) === 'http') { + return filter_var(filter_var($url, FILTER_SANITIZE_STRING), FILTER_VALIDATE_URL); + } + return false; +} + +/* + * Parse the primary resources out of the content and save into db. + * Clean up the removed primary resources from db. + * @param: $cid: content id + * @param: $content + * @return: none + */ +function populate_a4a($cid, $content, $formatting){ + global $my_files, $content_base_href, $contentManager; + + // Defining alternatives is only available for content type "html". + // But don't clean up the a4a tables at other content types in case the user needs them back at html. + + + if ($formatting <> 1) return; + + include_once(TR_INCLUDE_PATH.'classes/A4a/A4a.class.php'); + include_once(TR_INCLUDE_PATH.'classes/XML/XML_HTMLSax/XML_HTMLSax.php'); /* for XML_HTMLSax */ + include_once(TR_INCLUDE_PATH.'classes/ContentOutputParser.class.php'); /* for parser */ + + // initialize content_base_href; used in format_content + if (!isset($content_base_href)) { + $content_row = $contentManager->getContentPage($cid); + // return if the cid is not found + if (!is_array($content_row)) { + return; + } + $content_base_href = $content_row["content_path"].'/'; + } + + $body = ContentUtility::formatContent($content, $formatting); + + $handler = new ContentOutputParser(); + $parser = new XML_HTMLSax(); + $parser->set_object($handler); + $parser->set_element_handler('openHandler','closeHandler'); + + $my_files = array(); + $parser->parse($body); + $my_files = array_unique($my_files); + + foreach ($my_files as $file) { + /* filter out full urls */ + $url_parts = @parse_url($file); + + // file should be relative to content + if ((substr($file, 0, 1) == '/')) { + continue; + } + + // The URL of the movie from youtube.com has been converted above in embed_media(). + // For example: http://www.youtube.com/watch?v=a0ryB0m0MiM is converted to + // http://www.youtube.com/v/a0ryB0m0MiM to make it playable. This creates the problem + // that the parsed-out url (http://www.youtube.com/v/a0ryB0m0MiM) does not match with + // the URL saved in content table (http://www.youtube.com/watch?v=a0ryB0m0MiM). + // The code below is to convert the URL back to original. + $file = ContentUtility::convertYoutubePlayURLToWatchURL($file); + + $resources[] = convertAmp($file); // converts & to & + } + + $a4a = new A4a($cid); + $db_primary_resources = $a4a->getPrimaryResources(); + + // clean up the removed resources + foreach ($db_primary_resources as $primary_rid=>$db_resource){ + //if this file from our table is not found in the $resource, then it's not used. + if(count($resources) == 0 || !in_array($db_resource['resource'], $resources)){ + // The following ends up deleting all original resourse type from the db + // Why is it here? + //$a4a->deletePrimaryResource($primary_rid); + } + } + + if (count($resources) == 0) return; + + // insert the new resources + foreach($resources as $primary_resource) + { + if (!$a4a->getPrimaryResourceByName($primary_resource)){ + $a4a->setPrimaryResource($cid, $primary_resource, $_SESSION['lang']); + } + } +} + +// save all changes to the DB +function save_changes($redir, $current_tab) { + global $contentManager, $msg, $_course_id, $_content_id; + + $_POST['pid'] = intval($_POST['pid']); + $_POST['_cid'] = intval($_POST['_cid']); + + + $_POST['alternatives'] = intval($_POST['alternatives']); + + $_POST['title'] = trim($_POST['title']); + $_POST['head'] = trim($_POST['head']); + $_POST['use_customized_head'] = isset($_POST['use_customized_head'])?$_POST['use_customized_head']:0; + $_POST['body_text'] = stripslashes(trim($_POST['body_text'])); + $_POST['weblink_text'] = trim($_POST['weblink_text']); + $_POST['formatting'] = intval($_POST['formatting']); + $_POST['keywords'] = stripslashes(trim($_POST['keywords'])); + $_POST['test_message'] = trim($_POST['test_message']); + + //if weblink is selected, use it + if ($_POST['formatting']==CONTENT_TYPE_WEBLINK) { + $url = $_POST['weblink_text']; + $validated_url = isValidURL($url); + if (!validated_url || $validated_url !== $url) { + $msg->addError(array('INVALID_INPUT', _AT('weblink'))); + } else { + $_POST['body_text'] = $url; + $content_type_pref = CONTENT_TYPE_WEBLINK; + } + } else { + $content_type_pref = CONTENT_TYPE_CONTENT; + } + + // add or edit content + if ($_POST['_cid']) { + /* editing an existing page */ + $err = $contentManager->editContent($_POST['_cid'], $_POST['title'], $_POST['body_text'], + $_POST['keywords'], $_POST['formatting'], + $_POST['head'], $_POST['use_customized_head'], + $_POST['test_message']); + + + $cid = $_POST['_cid']; + } else { + /* insert new */ + $cid = $contentManager->addContent($_course_id, + $_POST['pid'], + $_POST['ordering'], + $_POST['title'], + $_POST['body_text'], + $_POST['keywords'], + $_POST['related'], + $_POST['formatting'], + $_POST['head'], + $_POST['use_customized_head'], + $_POST['test_message'], + $content_type_pref); + + $_POST['_cid'] = $cid; + $_REQUEST['_cid'] = $cid; + } + + + + + if ($cid == 0) return; + + // re-populate a4a tables based on the new content + populate_a4a($cid, $orig_body_text, $_POST['formatting']); + + + if (isset($_GET['tab'])) { + $current_tab = intval($_GET['tab']); + } + if (isset($_POST['current_tab'])) { + $current_tab = intval($_POST['current_tab']); + } + + // adapted content: save primary content type + if (isset($_POST['use_post_for_alt'])) + { + include_once(TR_INCLUDE_PATH.'classes/DAO/PrimaryResourcesTypesDAO.class.php'); + $primaryResourcesTypesDAO = new PrimaryResourcesTypesDAO(); + + // 1. delete old primary content type + + $sql = "DELETE FROM ".TABLE_PREFIX."primary_resources_types + WHERE primary_resource_id in + (SELECT DISTINCT primary_resource_id + FROM ".TABLE_PREFIX."primary_resources + WHERE content_id=? + AND language_code=?)"; + $values=array($cid, $_SESSION['lang']); + $types = "ii"; + $primaryResourcesTypesDAO->execute($sql, $values, $types); + + // 2. insert the new primary content type + + $sql = "SELECT pr.primary_resource_id, rt.type_id + FROM ".TABLE_PREFIX."primary_resources pr, ". + TABLE_PREFIX."resource_types rt + WHERE pr.content_id = ? + AND pr.language_code = ?"; + $values = array($cid, $_SESSION['lang']); + $types = "is"; + $all_types_rows = $primaryResourcesTypesDAO->execute($sql, $values, $types); + + if (is_array($all_types_rows)) { + foreach ($all_types_rows as $type) { + if (isset($_POST['alt_'.$type['primary_resource_id'].'_'.$type['type_id']])) + { + $primaryResourcesTypesDAO->Create($type['primary_resource_id'], $type['type_id']); + } + } + } + } + + include_once(TR_INCLUDE_PATH.'classes/DAO/ContentTestsAssocDAO.class.php'); + $contentTestsAssocDAO = new ContentTestsAssocDAO(); + $test_rows = $contentTestsAssocDAO->getByContent($_POST['_cid']); + $db_test_array = array(); + if (is_array($test_rows)) { + foreach ($test_rows as $row) { + $db_test_array[] = $row['test_id']; + } + } + + if (is_array($_POST['tid']) && sizeof($_POST['tid']) > 0){ + $toBeDeleted = array_diff($db_test_array, $_POST['tid']); + $toBeAdded = array_diff($_POST['tid'], $db_test_array); + //Delete entries + if (!empty($toBeDeleted)){ + $num_of_ids = count($toBeDeleted); + $sql = 'DELETE FROM '. TABLE_PREFIX .'content_tests_assoc WHERE content_id=? AND test_id IN ('.substr(str_repeat("? , ", $num_of_ids), 0, -2).')'; + $values = $toBeDeleted; + $types = "i"; + $types .= str_pad("", $num_of_ids, "i"); + $contentTestsAssocDAO->execute($sql, $values, $types); + } + + //Add entries + if (!empty($toBeAdded)){ + foreach ($toBeAdded as $i => $tid){ + $tid = intval($tid); + + if ($contentTestsAssocDAO->Create($_POST['_cid'], $tid) === false){ + $msg->addError('DB_NOT_UPDATED'); + } + } + } + } else { + //All tests has been removed. + $contentTestsAssocDAO->DeleteByContentID($_POST['_cid']); + } + //End Add test + + if (!$msg->containsErrors() && $redir) { + $_SESSION['save_n_close'] = $_POST['save_n_close']; + + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: '.basename($_SERVER['PHP_SELF']).'?_cid='.$cid.SEP.'close='.addslashes($_POST['save_n_close']).SEP.'tab='.addslashes($_POST['current_tab']).SEP.'displayhead='.addslashes($_POST['displayhead']).SEP.'alternatives='.addslashes($_POST['alternatives'])); + exit; + } else { + return; + } +} + +function check_for_changes($row, $row_alternatives) { + global $contentManager, $cid, $glossary, $glossary_ids_related; + + $changes = array(); + + if ($row && strcmp(trim(addslashes($_POST['title'])), addslashes($row['title']))) { + $changes[0] = true; + } else if (!$row && $_POST['title']) { + $changes[0] = true; + } + + if ($row && strcmp(addslashes(trim($_POST['head'])), trim(addslashes($row['head'])))) { + $changes[0] = true; + } else if (!$row && $_POST['head']) { + $changes[0] = true; + } + + if ($row && strcmp(addslashes(trim($_POST['body_text'])), trim(addslashes($row['text'])))) { + $changes[0] = true; + } else if (!$row && $_POST['body_text']) { + $changes[0] = true; + } + + if ($row && strcmp(addslashes(trim($_POST['weblink_text'])), trim(addslashes($row['text'])))) { + $changes[0] = true; + } else if (!$row && $_POST['weblink_text']) { + $changes[0] = true; + } + + /* use customized head: */ + if ($row && isset($_POST['use_customized_head']) && ($_POST['use_customized_head'] != $row['use_customized_head'])) { + $changes[0] = true; + } + + /* formatting: */ + if ($row && strcmp(trim($_POST['formatting']), $row['formatting'])) { + $changes[0] = true; + } else if (!$row && $_POST['formatting']) { + $changes[0] = true; + } + + /* keywords */ + if ($row && strcmp(trim($_POST['keywords']), $row['keywords'])) { + $changes[1] = true; + } else if (!$row && $_POST['keywords']) { + $changes[1] = true; + } + + /* adapted content */ + if (isset($_POST['use_post_for_alt'])) + { + foreach ($_POST as $alt_id => $alt_value) { + if (substr($alt_id, 0 ,4) == 'alt_' && $alt_value != $row_alternatives[$alt_id]){ + $changes[2] = true; + break; + } + } + } + + /* test & survey */ + if ($row && isset($_POST['test_message']) && $_POST['test_message'] != $row['test_message']){ + $changes[3] = true; + } + + $content_tests = $contentManager->getContentTestsAssoc($cid); + + if (isset($_POST['visited_tests'])) { + if (!is_array($content_tests) && is_array($_POST['tid'])) { + $changes[3] = true; + } + if (is_array($content_tests)) { + for ($i = 0; $i < count($content_tests); $i++) { + if ($content_tests[$i]['test_id'] <> $_POST['tid'][$i]) { + $changes[3] = true; + break; + } + } + } + } + + return $changes; +} + +function paste_from_file() { + global $msg; + + include_once(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php'); + if ($_FILES['uploadedfile_paste']['name'] == '') { + $msg->addError('FILE_NOT_SELECTED'); + return; + } + if ($_FILES['uploadedfile_paste']['name'] + && (($_FILES['uploadedfile_paste']['type'] == 'text/plain') + || ($_FILES['uploadedfile_paste']['type'] == 'text/html')) ) + { + + $path_parts = pathinfo($_FILES['uploadedfile_paste']['name']); + $ext = strtolower($path_parts['extension']); + + if (in_array($ext, array('html', 'htm'))) { + $_POST['body_text'] = file_get_contents($_FILES['uploadedfile_paste']['tmp_name']); + + /* get the <title> of this page */ + + $start_pos = strpos(strtolower($_POST['body_text']), ''); + $end_pos = strpos(strtolower($_POST['body_text']), ''); + + if (($start_pos !== false) && ($end_pos !== false)) { + $start_pos += strlen(''); + $_POST['title'] = trim(substr($_POST['body_text'], $start_pos, $end_pos-$start_pos)); + } + unset($start_pos); + unset($end_pos); + + $_POST['head'] = ContentUtility::getHtmlHeadByTag($_POST['body_text'], array("link", "style", "script")); + if (strlen(trim($_POST['head'])) > 0) + $_POST['use_customized_head'] = 1; + else + $_POST['use_customized_head'] = 0; + + $_POST['body_text'] = ContentUtility::getHtmlBody($_POST['body_text']); + + $msg->addFeedback('FILE_PASTED'); + } else if ($ext == 'txt') { + $_POST['body_text'] = file_get_contents($_FILES['uploadedfile_paste']['tmp_name']); + //LAW + $msg->addFeedback('FILE_PASTED'); + + } + } else { + $msg->addError('BAD_FILE_TYPE'); + } + + return; +} + +//for accessibility checker +function write_temp_file() { + global $_POST, $msg; + + if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { + $content_base = 'get.php/'; + } else { + $content_base = 'content/' . $_SESSION['course_id'] . '/'; + } + + if ($_POST['content_path']) { + $content_base .= $_POST['content_path'] . '/'; + } + + $file_name = $_POST['_cid'].'.html'; + + if ($handle = fopen(TR_CONTENT_DIR . $file_name, 'wb+')) { + + if (!@fwrite($handle, stripslashes($_POST['body_text']))) { + $msg->addError('FILE_NOT_SAVED'); + } + } else { + $msg->addError('FILE_NOT_SAVED'); + } + $msg->printErrors(); +} +?> diff --git a/home/editor/forums_tool.php b/home/editor/forums_tool.php index 01a73f0b..7e108abb 100644 --- a/home/editor/forums_tool.php +++ b/home/editor/forums_tool.php @@ -11,6 +11,7 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../../include/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); require(TR_INCLUDE_PATH.'vitals.inc.php'); @@ -157,4 +158,4 @@ </table> </div> -</form> \ No newline at end of file +</form> diff --git a/home/editor/import_export_content.php b/home/editor/import_export_content.php index 51b9900f..18982ece 100644 --- a/home/editor/import_export_content.php +++ b/home/editor/import_export_content.php @@ -1,193 +1,194 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); - -global $_course_id, $_content_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR); - -require(TR_INCLUDE_PATH.'header.inc.php'); -if (!isset($_main_menu)) { - $_main_menu = $contentManager->getContent(); -} - -// The length of the content/folder title to display. -// This is to fix the issue that, when any one of the content title is too long, -// the dropdown box for the export selection stretches out of the "export" fieldset border. -$len_of_title_to_display = 65; - -function print_menu_sections(&$menu, $only_print_content_folder = false, $parent_content_id = 0, $depth = 0, $ordering = '') { - global $len_of_title_to_display; - - $my_children = $menu[$parent_content_id]; - $cid = $_GET['cid']; - - if (!is_array($my_children)) { - return; - } - foreach ($my_children as $children) { - /* test content association, we don't want to display the test pages - * as part of the menu section. If test, skip it. - */ - if (isset($children['test_id'])){ - continue; - } - if ($only_print_content_folder && $children['content_type'] != CONTENT_TYPE_FOLDER) { - continue; - } - - echo '<option value="'.$children['content_id'].'"'; - if ($cid == $children['content_id']) { - echo ' selected="selected"'; - } - echo '>'; - echo str_pad('', $depth, '-') . ' '; - if ($parent_content_id == 0) { - $new_ordering = $children['ordering']; - echo $children['ordering']; - } else { - $new_ordering = $ordering.'.'.$children['ordering']; - echo $ordering . '.'. $children['ordering']; - } - if (strlen($children['title']) > $len_of_title_to_display) { - $title = substr($children['title'], 0, $len_of_title_to_display).' ...'; - } else { - $title = $children['title']; - } - - echo ' '.$title.'</option>'; - - print_menu_sections($menu, $only_print_content_folder, $children['content_id'], $depth+1, $new_ordering); - } -} - -?> -<form name="exportForm" method="post" action="home/ims/ims_export.php"> -<div class="input-form"> - <input type="hidden" name="_course_id" value="<?php echo $_course_id; ?>" /> - <fieldset class="group_form"><legend class="group_form"><?php echo _AT('export_content'); ?></legend> - <div class="row"> - <p><?php echo _AT('export_content_info'); ?></p> - </div> - -<?php if ($_main_menu[0]): ?> - <div class="row"> - <label for="select_cid"><?php echo _AT('export_content_package_what'); ?></label><br /> - <select name="cid" id="select_cid"> - <option value="0"><?php echo _AT('export_entire_course_or_chap'); ?></option> - <option value="0"></option> - <?php - print_menu_sections($_main_menu); - ?> - </select> - </div> - - <div class="row"> - <input type="radio" name="export_as" id="to_cp" value="1" checked="checked" onclick="changeFormAction('cp');" /> - <label for="to_cp"><?php echo _AT('content_package'); ?></label> <br /> - <input type="radio" name="export_as" id="to_cc" value="1" onclick="changeFormAction('cc');" /> - <label for="to_cc"><?php echo _AT('common_cartridge'); ?> </label> - </div> - <div class="row"> - <input type="checkbox" name="to_a4a" id="to_a4a" value="1" /> - <label for="to_a4a"><?php echo _AT('a4a_export'); ?></label> - </div> - - <div class="row buttons"> - <input type="submit" name="submit" value="<?php echo _AT('export'); ?>" /> - <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" /> - </div> - </fieldset> -<?php else: ?> - <div class="row"> - <strong><?php echo _AT('none_found'); ?></strong> - </div> -<?php endif; ?> - -</div> -</form> - -<form name="form1" method="post" action="home/ims/ims_import.php" enctype="multipart/form-data" onsubmit="openWindow('<?php echo TR_BASE_HREF; ?>home/prog.php');"> -<div class="input-form"> - <input type="hidden" name="_course_id" value="<?php echo $_course_id; ?>" /> - <fieldset class="group_form"><legend class="group_form"><?php echo _AT('import_content'); ?></legend> - <div class="row"> - - <p><?php echo _AT('import_content_info'); ?></p> - </div> - - <div class="row"> - <label for="select_cid2"><?php echo _AT('import_content_package_where'); ?></label><br /> - <select name="cid" id="select_cid2"> - <option value="0"><?php echo _AT('import_content_package_bottom_subcontent'); ?></option> - <option value="0"></option> - <?php - print_menu_sections($_main_menu, true); - ?> - </select> - </div> - - <div class="row"> - <input type="checkbox" name="allow_test_import" id="allow_test_import" checked="checked" /> - <label for="allow_test_import"><?php echo _AT('test_import_package'); ?></label> <br /> - <input type="checkbox" name="allow_a4a_import" id="allow_a4a_import" checked="checked" /> - <label for="allow_a4a_import"><?php echo _AT('a4a_import_package'); ?></label><br /> - <input type="checkbox" name="ignore_validation" id="ignore_validation" value="1" /> - <label for="ignore_validation"><?php echo _AT('ignore_validation'); ?></label> <br /> - </div> - - <div class="row"> - <label for="to_file"><?php echo _AT('upload_content_package'); ?></label><br /> - <input type="file" name="file" id="to_file" /> - </div> - - <div class="row"> - <label for="to_url"><?php echo _AT('specify_url_to_content_package'); ?></label><br /> - <input type="text" name="url" value="http://" size="40" id="to_url" /> - </div> - - <div class="row buttons"> - <input type="submit" name="submit" onclick="setClickSource('submit');" value="<?php echo _AT('import'); ?>" /> - <input type="submit" name="cancel" onclick="document.form1.enctype='';setClickSource('cancel');" value="<?php echo _AT('cancel'); ?>" /> - </div> -</div> -</form> - -<script language="javascript" type="text/javascript"> - -var but_src; -function setClickSource(name) { - but_src = name; -} - -function openWindow(page) { - if (but_src != "cancel") { - newWindow = window.open(page, "progWin", "width=400,height=200,toolbar=no,location=no"); - newWindow.focus(); - } -} - -//Change form action -function changeFormAction(type){ - var obj = document.exportForm; - if (type=="cc"){ - obj.action = "home/imscc/ims_export.php"; - } else if (type=="cp"){ - obj.action = "home/ims/ims_export.php"; - } -} - -</script> - -<?php require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../../include/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); + +global $_course_id, $_content_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR); + +require(TR_INCLUDE_PATH.'header.inc.php'); +if (!isset($_main_menu)) { + $_main_menu = $contentManager->getContent(); +} + +// The length of the content/folder title to display. +// This is to fix the issue that, when any one of the content title is too long, +// the dropdown box for the export selection stretches out of the "export" fieldset border. +$len_of_title_to_display = 65; + +function print_menu_sections(&$menu, $only_print_content_folder = false, $parent_content_id = 0, $depth = 0, $ordering = '') { + global $len_of_title_to_display; + + $my_children = $menu[$parent_content_id]; + $cid = $_GET['cid']; + + if (!is_array($my_children)) { + return; + } + foreach ($my_children as $children) { + /* test content association, we don't want to display the test pages + * as part of the menu section. If test, skip it. + */ + if (isset($children['test_id'])){ + continue; + } + if ($only_print_content_folder && $children['content_type'] != CONTENT_TYPE_FOLDER) { + continue; + } + + echo '<option value="'.$children['content_id'].'"'; + if ($cid == $children['content_id']) { + echo ' selected="selected"'; + } + echo '>'; + echo str_pad('', $depth, '-') . ' '; + if ($parent_content_id == 0) { + $new_ordering = $children['ordering']; + echo $children['ordering']; + } else { + $new_ordering = $ordering.'.'.$children['ordering']; + echo $ordering . '.'. $children['ordering']; + } + if (strlen($children['title']) > $len_of_title_to_display) { + $title = substr($children['title'], 0, $len_of_title_to_display).' ...'; + } else { + $title = $children['title']; + } + + echo ' '.$title.'</option>'; + + print_menu_sections($menu, $only_print_content_folder, $children['content_id'], $depth+1, $new_ordering); + } +} + +?> +<form name="exportForm" method="post" action="home/ims/ims_export.php"> +<div class="input-form"> + <input type="hidden" name="_course_id" value="<?php echo $_course_id; ?>" /> + <fieldset class="group_form"><legend class="group_form"><?php echo _AT('export_content'); ?></legend> + <div class="row"> + <p><?php echo _AT('export_content_info'); ?></p> + </div> + +<?php if ($_main_menu[0]): ?> + <div class="row"> + <label for="select_cid"><?php echo _AT('export_content_package_what'); ?></label><br /> + <select name="cid" id="select_cid"> + <option value="0"><?php echo _AT('export_entire_course_or_chap'); ?></option> + <option value="0"></option> + <?php + print_menu_sections($_main_menu); + ?> + </select> + </div> + + <div class="row"> + <input type="radio" name="export_as" id="to_cp" value="1" checked="checked" onclick="changeFormAction('cp');" /> + <label for="to_cp"><?php echo _AT('content_package'); ?></label> <br /> + <input type="radio" name="export_as" id="to_cc" value="1" onclick="changeFormAction('cc');" /> + <label for="to_cc"><?php echo _AT('common_cartridge'); ?> </label> + </div> + <div class="row"> + <input type="checkbox" name="to_a4a" id="to_a4a" value="1" /> + <label for="to_a4a"><?php echo _AT('a4a_export'); ?></label> + </div> + + <div class="row buttons"> + <input type="submit" name="submit" value="<?php echo _AT('export'); ?>" /> + <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" /> + </div> + </fieldset> +<?php else: ?> + <div class="row"> + <strong><?php echo _AT('none_found'); ?></strong> + </div> +<?php endif; ?> + +</div> +</form> + +<form name="form1" method="post" action="home/ims/ims_import.php" enctype="multipart/form-data" onsubmit="openWindow('<?php echo TR_BASE_HREF; ?>home/prog.php');"> +<div class="input-form"> + <input type="hidden" name="_course_id" value="<?php echo $_course_id; ?>" /> + <fieldset class="group_form"><legend class="group_form"><?php echo _AT('import_content'); ?></legend> + <div class="row"> + + <p><?php echo _AT('import_content_info'); ?></p> + </div> + + <div class="row"> + <label for="select_cid2"><?php echo _AT('import_content_package_where'); ?></label><br /> + <select name="cid" id="select_cid2"> + <option value="0"><?php echo _AT('import_content_package_bottom_subcontent'); ?></option> + <option value="0"></option> + <?php + print_menu_sections($_main_menu, true); + ?> + </select> + </div> + + <div class="row"> + <input type="checkbox" name="allow_test_import" id="allow_test_import" checked="checked" /> + <label for="allow_test_import"><?php echo _AT('test_import_package'); ?></label> <br /> + <input type="checkbox" name="allow_a4a_import" id="allow_a4a_import" checked="checked" /> + <label for="allow_a4a_import"><?php echo _AT('a4a_import_package'); ?></label><br /> + <input type="checkbox" name="ignore_validation" id="ignore_validation" value="1" /> + <label for="ignore_validation"><?php echo _AT('ignore_validation'); ?></label> <br /> + </div> + + <div class="row"> + <label for="to_file"><?php echo _AT('upload_content_package'); ?></label><br /> + <input type="file" name="file" id="to_file" /> + </div> + + <div class="row"> + <label for="to_url"><?php echo _AT('specify_url_to_content_package'); ?></label><br /> + <input type="text" name="url" value="http://" size="40" id="to_url" /> + </div> + + <div class="row buttons"> + <input type="submit" name="submit" onclick="setClickSource('submit');" value="<?php echo _AT('import'); ?>" /> + <input type="submit" name="cancel" onclick="document.form1.enctype='';setClickSource('cancel');" value="<?php echo _AT('cancel'); ?>" /> + </div> +</div> +</form> + +<script language="javascript" type="text/javascript"> + +var but_src; +function setClickSource(name) { + but_src = name; +} + +function openWindow(page) { + if (but_src != "cancel") { + newWindow = window.open(page, "progWin", "width=400,height=200,toolbar=no,location=no"); + newWindow.focus(); + } +} + +//Change form action +function changeFormAction(type){ + var obj = document.exportForm; + if (type=="cc"){ + obj.action = "home/imscc/ims_export.php"; + } else if (type=="cp"){ + obj.action = "home/ims/ims_export.php"; + } +} + +</script> + +<?php require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/home/editor/index.php b/home/editor/index.php index 6f5a440c..33d40358 100644 --- a/home/editor/index.php +++ b/home/editor/index.php @@ -1,28 +1,29 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -/** Commented by Cindy Li on Apr 27, 2010 - * Modified from ATutor home/editor/*, SVN revision 9807 - */ - -define('TR_INCLUDE_PATH', '../../include/'); -require (TR_INCLUDE_PATH.'vitals.inc.php'); - -$_section[0][0] = 'Blank Page'; - -require (TR_INCLUDE_PATH.'header.inc.php'); - -?> -blank page -<?php -require (TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +/** Commented by Cindy Li on Apr 27, 2010 + * Modified from ATutor home/editor/*, SVN revision 9807 + */ + +define('TR_INCLUDE_PATH', '../../include/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); +require (TR_INCLUDE_PATH.'vitals.inc.php'); + +$_section[0][0] = 'Blank Page'; + +require (TR_INCLUDE_PATH.'header.inc.php'); + +?> +blank page +<?php +require (TR_INCLUDE_PATH.'footer.inc.php'); +?> diff --git a/home/editor/preview.php b/home/editor/preview.php index e45f296a..018c74bb 100644 --- a/home/editor/preview.php +++ b/home/editor/preview.php @@ -1,76 +1,81 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../../include/'); - -require(TR_INCLUDE_PATH.'vitals.inc.php'); -require(TR_INCLUDE_PATH.'../home/editor/editor_tab_functions.inc.php'); - -// commented out this require which was causing the a redeclare error #4846 -// delete the following line when its confirmed the require is not needed -// require(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php'); - -global $_course_id, $_content_id, $contentManager; - -Utility::authenticate(TR_PRIV_ISAUTHOR); - -$cid = $_content_id; - -if ($cid == 0) { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printInfos('NO_PAGE_CONTENT'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (isset($contentManager)) $content_row = $contentManager->getContentPage($cid); - -if (!$content_row || !isset($contentManager)) { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('MISSING_CONTENT'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { - $course_base_href = 'get.php/'; -} else { - $course_base_href = 'content/' . $_course_id . '/'; -} - -if ($content_row['content_path']) { - $content_base_href .= $content_row['content_path'].'/'; -} - -$popup = intval($_GET['popup']); -require(TR_INCLUDE_PATH.'header.inc.php'); -?> - <div class="row"> - <?php - echo '<h2>'.AT_print(stripslashes($_POST['title']), 'content.title').'</h2>'; - if ($_POST['formatting'] == CONTENT_TYPE_WEBLINK) { - $url = $_POST['weblink_text']; - $validated_url = isValidURL($url); - if (!validated_url || $validated_url !== $url) { - $msg->addError(array('INVALID_INPUT', _AT('weblink'))); - $msg->printErrors(); - } else { - echo ContentUtility::formatContent($url, $_POST['formatting']); - } - } else { - echo ContentUtility::formatContent(stripslashes($_POST['body_text']), $_POST['formatting']); - } - ?> - </div> -<?php -require(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../../include/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); + +require(TR_INCLUDE_PATH.'vitals.inc.php'); +require(TR_INCLUDE_PATH.'../home/editor/editor_tab_functions.inc.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +// commented out this require which was causing the a redeclare error #4846 +// delete the following line when its confirmed the require is not needed +// require(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php'); + +global $_course_id, $_content_id, $contentManager; + +Utility::authenticate(TR_PRIV_ISAUTHOR); + +$cid = $_content_id; + +if ($cid == 0) { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printInfos('NO_PAGE_CONTENT'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +if (isset($contentManager)) $content_row = $contentManager->getContentPage($cid); + +if (!$content_row || !isset($contentManager)) { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('MISSING_CONTENT'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { + $course_base_href = 'get.php/'; +} else { + $course_base_href = 'content/' . $_course_id . '/'; +} + +if ($content_row['content_path']) { + $content_base_href .= $content_row['content_path'].'/'; +} + +$popup = intval($_GET['popup']); +require(TR_INCLUDE_PATH.'header.inc.php'); +?> + <div class="row"> + <?php + echo '<h2>'.AT_print($purifier->purify(stripslashes($_POST['title'])), 'content.title').'</h2>'; + if ($_POST['formatting'] == CONTENT_TYPE_WEBLINK) { + $url = $_POST['weblink_text']; + $validated_url = isValidURL($url); + if (!validated_url || $validated_url !== $url) { + $msg->addError(array('INVALID_INPUT', _AT('weblink'))); + $msg->printErrors(); + } else { + echo ContentUtility::formatContent($url, $_POST['formatting']); + } + } else { + echo ContentUtility::formatContent($purifier->purify(stripslashes($_POST['body_text'])), $_POST['formatting']); + } + ?> + </div> +<?php +require(TR_INCLUDE_PATH.'footer.inc.php'); +?> diff --git a/home/editor/remove_alternative.php b/home/editor/remove_alternative.php index 6ce4c0e5..611c193e 100644 --- a/home/editor/remove_alternative.php +++ b/home/editor/remove_alternative.php @@ -1,65 +1,66 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -/** - * This script handles the ajax post submit from "content editor" =? "adpated content" - * to remove selected alternative from database - * @see home/editor/editor_tabs/alternatives.inc.php - * @var $_POST values: - * pid: primary resource id - * a_type: alternative type, must be one of the values in resource_types.type_id - */ - -define('TR_INCLUDE_PATH', '../../include/'); -require (TR_INCLUDE_PATH.'vitals.inc.php'); - -$pid = intval($_POST['pid']); -$type_id = intval($_POST['a_type']); - -// check post vars -if ($pid == 0 || $type_id == 0) exit; - -require_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php'); -$dao = new DAO(); - -// delete the existing alternative for this (pid, a_type) -$sql = "SELECT sr.secondary_resource_id - FROM ".TABLE_PREFIX."secondary_resources sr, ".TABLE_PREFIX."secondary_resources_types srt - WHERE sr.secondary_resource_id = srt.secondary_resource_id - AND sr.primary_resource_id = ? - AND sr.language_code = ? - AND srt.type_id=?"; -$values = array($pid, $_SESSION['lang'], $type_id); -$types = "isi"; -$existing_secondary_rows = $dao->execute($sql, $values, $types); - -if (is_array($existing_secondary_rows)) { - foreach ($existing_secondary_rows as $existing_secondary) - { - - $sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources - WHERE secondary_resource_id = ?"; - $values = $existing_secondary['secondary_resource_id']; - $dao->execute($sql, $values, $types); - - $sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources_types - WHERE secondary_resource_id = ? - AND type_id=?"; - $values = array($existing_secondary['secondary_resource_id'], $type_id); - $types = "ii"; - $dao->execute($sql, $values, $types); - } -} - -exit; - -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +/** + * This script handles the ajax post submit from "content editor" =? "adpated content" + * to remove selected alternative from database + * @see home/editor/editor_tabs/alternatives.inc.php + * @var $_POST values: + * pid: primary resource id + * a_type: alternative type, must be one of the values in resource_types.type_id + */ + +define('TR_INCLUDE_PATH', '../../include/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); +require (TR_INCLUDE_PATH.'vitals.inc.php'); + +$pid = intval($_POST['pid']); +$type_id = intval($_POST['a_type']); + +// check post vars +if ($pid == 0 || $type_id == 0) exit; + +require_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php'); +$dao = new DAO(); + +// delete the existing alternative for this (pid, a_type) +$sql = "SELECT sr.secondary_resource_id + FROM ".TABLE_PREFIX."secondary_resources sr, ".TABLE_PREFIX."secondary_resources_types srt + WHERE sr.secondary_resource_id = srt.secondary_resource_id + AND sr.primary_resource_id = ? + AND sr.language_code = ? + AND srt.type_id=?"; +$values = array($pid, $_SESSION['lang'], $type_id); +$types = "isi"; +$existing_secondary_rows = $dao->execute($sql, $values, $types); + +if (is_array($existing_secondary_rows)) { + foreach ($existing_secondary_rows as $existing_secondary) + { + + $sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources + WHERE secondary_resource_id = ?"; + $values = $existing_secondary['secondary_resource_id']; + $dao->execute($sql, $values, $types); + + $sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources_types + WHERE secondary_resource_id = ? + AND type_id=?"; + $values = array($existing_secondary['secondary_resource_id'], $type_id); + $types = "ii"; + $dao->execute($sql, $values, $types); + } +} + +exit; + +?> diff --git a/home/editor/save_alternative.php b/home/editor/save_alternative.php index f54d2d86..aab27e93 100644 --- a/home/editor/save_alternative.php +++ b/home/editor/save_alternative.php @@ -1,85 +1,86 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -/** - * This script handles the ajax post submit from "content editor" =? "adpated content" - * to save the selected alternative into database - * @see file_manager/filemanager_display.inc.php - * @var $_POST values: - * pid: primary resource id - * a_type: alternative type, must be one of the values in resource_types.type_id - * alternative: the location and name of the selected alternative - */ - -define('TR_INCLUDE_PATH', '../../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); - -$pid = intval($_POST['pid']); -$type_id = intval($_POST['a_type']); -$secondary_resource = trim($_POST['alternative']); - -// check post vars -if ($pid == 0 || $type_id == 0 || $secondary_resource == '') exit; - -require_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php'); -$dao = new DAO(); - -// delete the existing alternative for this (pid, a_type) -$sql = "SELECT sr.secondary_resource_id - FROM ".TABLE_PREFIX."secondary_resources sr, ".TABLE_PREFIX."secondary_resources_types srt - WHERE sr.secondary_resource_id = srt.secondary_resource_id - AND sr.primary_resource_id = ? - AND sr.language_code = ? - AND srt.type_id=?"; -$values = array($pid, $_SESSION['lang'], $type_id); -$types = "iii"; - -$existing_secondary_rows = $dao->execute($sql, $values, $types); - -if (is_array($existing_secondary_rows)) { - foreach ($existing_secondary_rows as $existing_secondary) - { - /*$sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources - WHERE secondary_resource_id = ".$existing_secondary['secondary_resource_id']; - */ - $sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources - WHERE secondary_resource_id = ?"; - $values = $existing_secondary['secondary_resource_id']; - $types = "i"; - $dao->execute($sql, $values, $types); - - $sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources_types - WHERE secondary_resource_id = ? - AND type_id=?"; - $values = array($existing_secondary['secondary_resource_id'], $type_id); - $dao->execute($sql, $values, $types); - } -} - -// insert new alternative -$sql = "INSERT INTO ".TABLE_PREFIX."secondary_resources (primary_resource_id, secondary_resource, language_code) - VALUES (?, ?, ?)"; -$values = array($pid, $secondary_resource, $_SESSION['lang']); -$types = "iss"; -$dao->execute($sql, $values, $types); - -$secondary_resource_id = $dao->ac_insert_id(); - -$sql = "INSERT INTO ".TABLE_PREFIX."secondary_resources_types (secondary_resource_id, type_id) - VALUES (?, ?)"; -$values = array($secondary_resource_id, $type_id); -$types = "ii"; -$dao->execute($sql, $values, $types); - -exit; - -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +/** + * This script handles the ajax post submit from "content editor" =? "adpated content" + * to save the selected alternative into database + * @see file_manager/filemanager_display.inc.php + * @var $_POST values: + * pid: primary resource id + * a_type: alternative type, must be one of the values in resource_types.type_id + * alternative: the location and name of the selected alternative + */ + +define('TR_INCLUDE_PATH', '../../include/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); + +$pid = intval($_POST['pid']); +$type_id = intval($_POST['a_type']); +$secondary_resource = trim($_POST['alternative']); + +// check post vars +if ($pid == 0 || $type_id == 0 || $secondary_resource == '') exit; + +require_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php'); +$dao = new DAO(); + +// delete the existing alternative for this (pid, a_type) +$sql = "SELECT sr.secondary_resource_id + FROM ".TABLE_PREFIX."secondary_resources sr, ".TABLE_PREFIX."secondary_resources_types srt + WHERE sr.secondary_resource_id = srt.secondary_resource_id + AND sr.primary_resource_id = ? + AND sr.language_code = ? + AND srt.type_id=?"; +$values = array($pid, $_SESSION['lang'], $type_id); +$types = "iii"; + +$existing_secondary_rows = $dao->execute($sql, $values, $types); + +if (is_array($existing_secondary_rows)) { + foreach ($existing_secondary_rows as $existing_secondary) + { + /*$sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources + WHERE secondary_resource_id = ".$existing_secondary['secondary_resource_id']; + */ + $sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources + WHERE secondary_resource_id = ?"; + $values = $existing_secondary['secondary_resource_id']; + $types = "i"; + $dao->execute($sql, $values, $types); + + $sql = "DELETE FROM ".TABLE_PREFIX."secondary_resources_types + WHERE secondary_resource_id = ? + AND type_id=?"; + $values = array($existing_secondary['secondary_resource_id'], $type_id); + $dao->execute($sql, $values, $types); + } +} + +// insert new alternative +$sql = "INSERT INTO ".TABLE_PREFIX."secondary_resources (primary_resource_id, secondary_resource, language_code) + VALUES (?, ?, ?)"; +$values = array($pid, $secondary_resource, $_SESSION['lang']); +$types = "iss"; +$dao->execute($sql, $values, $types); + +$secondary_resource_id = $dao->ac_insert_id(); + +$sql = "INSERT INTO ".TABLE_PREFIX."secondary_resources_types (secondary_resource_id, type_id) + VALUES (?, ?)"; +$values = array($secondary_resource_id, $type_id); +$types = "ii"; +$dao->execute($sql, $values, $types); + +exit; + +?> From 1410568d942824d775b8b0ac9eb053b8261f9b88 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sun, 16 Sep 2018 15:12:08 +0700 Subject: [PATCH 38/94] Add CSRF Token --- .../home/editor/arrange_content.tmpl.php | 104 +++---- .../home/editor/edit_content_folder.tmpl.php | 7 +- .../home/editor/edit_content_struct.tmpl.php | 255 +++++++++--------- 3 files changed, 190 insertions(+), 176 deletions(-) diff --git a/themes/default/home/editor/arrange_content.tmpl.php b/themes/default/home/editor/arrange_content.tmpl.php index 0f60af3f..cc9febc7 100644 --- a/themes/default/home/editor/arrange_content.tmpl.php +++ b/themes/default/home/editor/arrange_content.tmpl.php @@ -1,50 +1,54 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -if (!defined('TR_INCLUDE_PATH')) { exit; } - -global $contentManager; - -require(TR_INCLUDE_PATH.'header.inc.php'); -?> -<div class="input-form"> -<form action="<?php echo $_SERVER['PHP_SELF'].'?_course_id='.$this->course_id; if ($this->cid > 0) echo SEP.'_cid='.$this->cid; else if ($this->pid > 0) echo SEP.'pid='.$this->pid;?>" method="post" name="form"> - <input type="hidden" name="button_1" value="-1" /> -<?php - if ($contentManager->getNumSections() > (1 - (bool)(!$cid))) { - echo '<p>' - , _AT('editor_properties_instructions', - '<img src="'.$_base_path.'images/after.gif" alt="'._AT('after_topic', '').'" title="'._AT('after_topic', '').'" />', - '<img src="'.$_base_path.'images/before.gif" alt="'._AT('before_topic', '').'" title="'._AT('before_topic', '').'" />', - '<img src="'.$_base_path.'images/child_of.gif" alt="'._AT('child_of', '').'" title="'._AT('child_of', '').'" />') - , '</p>'; - - } - - ?><br /> - <table border="0" align="center"> - <tr> - <th colspan="3"><?php echo _AT('move'); ?></th> - <th><?php echo _AT('content'); ?></th> - </tr> - <tr> - <td colspan="3"> </td> - <td><?php echo _AT('home'); ?></td> - </tr> -<?php - $contentManager->printActionMenu($contentManager->_menu, 0, 0, '', array(), "movable"); - -?> - </table> -</form> -</div> -<?php require(TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +session_start(); + +if (!defined('TR_INCLUDE_PATH')) { exit; } + +global $contentManager; + +require(TR_INCLUDE_PATH.'header.inc.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +?> +<div class="input-form"> +<form action="<?php echo $_SERVER['PHP_SELF'].'?_course_id='.$this->course_id; if ($this->cid > 0) echo SEP.'_cid='.$this->cid; else if ($this->pid > 0) echo SEP.'pid='.$this->pid;?>" method="post" name="form"> + <?php echo CSRF_Token::display(); ?><br> + <input type="hidden" name="button_1" value="-1" /> +<?php + if ($contentManager->getNumSections() > (1 - (bool)(!$cid))) { + echo '<p>' + , _AT('editor_properties_instructions', + '<img src="'.$_base_path.'images/after.gif" alt="'._AT('after_topic', '').'" title="'._AT('after_topic', '').'" />', + '<img src="'.$_base_path.'images/before.gif" alt="'._AT('before_topic', '').'" title="'._AT('before_topic', '').'" />', + '<img src="'.$_base_path.'images/child_of.gif" alt="'._AT('child_of', '').'" title="'._AT('child_of', '').'" />') + , '</p>'; + + } + + ?><br /> + <table border="0" align="center"> + <tr> + <th colspan="3"><?php echo _AT('move'); ?></th> + <th><?php echo _AT('content'); ?></th> + </tr> + <tr> + <td colspan="3"> </td> + <td><?php echo _AT('home'); ?></td> + </tr> +<?php + $contentManager->printActionMenu($contentManager->_menu, 0, 0, '', array(), "movable"); + +?> + </table> +</form> +</div> +<?php require(TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/themes/default/home/editor/edit_content_folder.tmpl.php b/themes/default/home/editor/edit_content_folder.tmpl.php index bbac5857..1c503177 100644 --- a/themes/default/home/editor/edit_content_folder.tmpl.php +++ b/themes/default/home/editor/edit_content_folder.tmpl.php @@ -10,12 +10,16 @@ /* as published by the Free Software Foundation. */ /************************************************************************/ +session_start(); + if (!defined('TR_INCLUDE_PATH')) { exit; } global $onload, $contentManager; $onload = 'document.form.title.focus();'; + +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); ?> -<form action="<?php echo $_SERVER['PHP_SELF'].'?'; if ($this->cid > 0) echo '_cid='.$this->cid; else if ($this->pid > 0) echo 'pid='.$this->pid.SEP.'_course_id='.$this->course_id; else echo '_course_id='.$this->course_id;?>" method="post" name="form"> +<form action="<?php echo $_SERVER['PHP_SELF'].'?'; if ($this->cid > 0) echo '_cid='.$this->cid; else if ($this->pid > 0) echo 'pid='.$this->pid.SEP.'_course_id='.$this->course_id; else echo '_course_id='.$this->course_id;?>" method="post" name="form" autocomplete="off"> <div class="input-form" style="width:95%;margin-left:1.5em;"> <!-- <?php if ($this->shortcuts): @@ -34,6 +38,7 @@ </div> <div class="row buttons"> + <?php echo CSRF_Token::display(); ?><br> <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" title="<?php echo _AT('save_changes'); ?> alt-s" accesskey="s" /> </div> </div> diff --git a/themes/default/home/editor/edit_content_struct.tmpl.php b/themes/default/home/editor/edit_content_struct.tmpl.php index f950a869..206b97e4 100644 --- a/themes/default/home/editor/edit_content_struct.tmpl.php +++ b/themes/default/home/editor/edit_content_struct.tmpl.php @@ -1,125 +1,130 @@ -<?php - -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -if (!defined('TR_INCLUDE_PATH')) { exit; } - -global $onload; -$onload = 'document.form.title.focus();'; -?> -<form action="<?php echo $_SERVER['PHP_SELF'].'?'; if ($this->cid > 0) echo '_cid='.$this->cid; else if ($this->pid > 0) echo 'pid='.$this->pid.SEP.'_course_id='.$this->course_id; else echo '_course_id='.$this->course_id;?>" method="post" name="form"> -<div class="input-form" style="width:95%;margin-left:1.5em;"> -<!-- <?php -if ($this->shortcuts): -?> - <fieldset id="shortcuts" style="margin-top:1em;float:right;clear:right;"><legend><?php echo _AT('shortcuts'); ?></legend> - <ul> - <?php foreach ($this->shortcuts as $link): ?> - <li><a href="<?php echo $link['url']; ?>"><?php echo $link['title']; ?></a></li> - <?php endforeach; ?> - </ul> -</fieldset> -<?php endif; ?> --> - <div class="row"> - <div style="font-weight:bold;"><span class="required" title="<?php echo _AT('required_field'); ?>">*</span><label for="ftitle"><?php echo _AT('choose_structure'); ?></label></div> - - <?php - - $mod_path['templates'] = realpath(TR_BASE_HREF . 'templates').'/'; - $mod_path['templates_int'] = realpath(TR_INCLUDE_PATH . '../templates').'/'; - $mod_path['templates_sys'] = $mod_path['templates_int'] . 'system/'; - $mod_path['structs_dir'] = $mod_path['templates'] . 'structures/'; - $mod_path['structs_dir_int'] = $mod_path['templates_int'] . 'structures/'; - - include_once($mod_path['templates_sys'].'Structures.class.php'); - - $structs = new Structures($mod_path); - - $structsList = $structs->getStructsList(); - if (!is_array($structsList)) { - $num_of_structs = 0; - $output = _AT('none_found'); - } else { - - echo '<div style=" weight: 10%; margin: 10px;">'; - - echo '<ol class="remove-margin-left" id="layout_list"> '; - foreach ($structsList as $struct) { - echo "<li>"; - - echo '<input type="radio" name="title" id="'.$struct['name'].'" class="formfield" value="'.$struct['short_name'].'"/>'; - echo '<label for="'.$struct['name'].'">'.$struct['name'].'</label>'; - $value = ""; - - - - foreach ($structsList as $val) { - if(isset($_POST['struct']) && $_POST['struct'] == $val['short_name']) - $check = true; - else - $check = false; - - if($val['name'] == $struct['name']){ - ?> - <div style=" margin-bottom: 10px; margin-top:-1.5em;; <?php if($check) echo 'border: 2px #cccccc dotted;';?> "> - - - <!-- <li id="<?php echo $val['short_name'];?>"> <?php echo $val['name'];?> </li> --> - - <!--<p style="margin-left: 10px; font-size:90%;"><span style="font-style:italic;"><?php echo _AT('description'); ?>:</span> - <?php echo $val['description']; ?></p> --> - - - <div style="font-size:95%; "> -<!-- - <a title="outline_collapsed" id="a_outline_<?php echo $val['short_name'];?>" onclick="javascript: trans.utility.toggleOutline('<?php echo $val['short_name'];?>', '<?php echo _AT('hide_outline'); ?>', '<?php echo _AT('show_outline'); ?>'); " href="javascript:void(0)"><?php echo _AT('show_outline'); ?></a> - <div style="display: none;" id="div_outline_<?php echo $val['short_name'];?>"> - <?php $struc_manag = new StructureManager($val['short_name']); - $struc_manag->printPreview(false, $val['short_name']); ?> - </div> --> - <div style=" margin-bottom: 10px; <?php if($check) echo 'border: 2px #cccccc dotted;';?> "> - <div class="struct_preview"> - <div style="display: inline;" id="div_outline_<?php echo $struct['short_name'];?>"> - <?php - $struc_manag = new StructureManager($struct['short_name']); - $struc_manag->printPreview(false, $struct['short_name']); - ?> - </div> - </div> - </div> - - </div> - </div> - - <?php - } - } - - - echo '</li>'; - } - - echo '</ol></div>'; - - } - - ?> - - <!-- <input type="checkbox"" name="title" id="ftitle1" class="formfield" value="bao"></input> --> - - </div> - - <div class="row buttons"> - <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" title="<?php echo _AT('save_changes'); ?> alt-s" accesskey="s" /> - </div> -</div> -</form> +<?php + +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +session_start(); + +if (!defined('TR_INCLUDE_PATH')) { exit; } + +global $onload; +$onload = 'document.form.title.focus();'; + +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +?> +<form action="<?php echo $_SERVER['PHP_SELF'].'?'; if ($this->cid > 0) echo '_cid='.$this->cid; else if ($this->pid > 0) echo 'pid='.$this->pid.SEP.'_course_id='.$this->course_id; else echo '_course_id='.$this->course_id;?>" method="post" name="form"> +<div class="input-form" style="width:95%;margin-left:1.5em;"> +<!-- <?php +if ($this->shortcuts): +?> + <fieldset id="shortcuts" style="margin-top:1em;float:right;clear:right;"><legend><?php echo _AT('shortcuts'); ?></legend> + <ul> + <?php foreach ($this->shortcuts as $link): ?> + <li><a href="<?php echo $link['url']; ?>"><?php echo $link['title']; ?></a></li> + <?php endforeach; ?> + </ul> +</fieldset> +<?php endif; ?> --> + <div class="row"> + <div style="font-weight:bold;"><span class="required" title="<?php echo _AT('required_field'); ?>">*</span><label for="ftitle"><?php echo _AT('choose_structure'); ?></label></div> + + <?php + + $mod_path['templates'] = realpath(TR_BASE_HREF . 'templates').'/'; + $mod_path['templates_int'] = realpath(TR_INCLUDE_PATH . '../templates').'/'; + $mod_path['templates_sys'] = $mod_path['templates_int'] . 'system/'; + $mod_path['structs_dir'] = $mod_path['templates'] . 'structures/'; + $mod_path['structs_dir_int'] = $mod_path['templates_int'] . 'structures/'; + + include_once($mod_path['templates_sys'].'Structures.class.php'); + + $structs = new Structures($mod_path); + + $structsList = $structs->getStructsList(); + if (!is_array($structsList)) { + $num_of_structs = 0; + $output = _AT('none_found'); + } else { + + echo '<div style=" weight: 10%; margin: 10px;">'; + + echo '<ol class="remove-margin-left" id="layout_list"> '; + foreach ($structsList as $struct) { + echo "<li>"; + + echo '<input type="radio" name="title" id="'.$struct['name'].'" class="formfield" value="'.$struct['short_name'].'"/>'; + echo '<label for="'.$struct['name'].'">'.$struct['name'].'</label>'; + $value = ""; + + + + foreach ($structsList as $val) { + if(isset($_POST['struct']) && $_POST['struct'] == $val['short_name']) + $check = true; + else + $check = false; + + if($val['name'] == $struct['name']){ + ?> + <div style=" margin-bottom: 10px; margin-top:-1.5em;; <?php if($check) echo 'border: 2px #cccccc dotted;';?> "> + + + <!-- <li id="<?php echo $val['short_name'];?>"> <?php echo $val['name'];?> </li> --> + + <!--<p style="margin-left: 10px; font-size:90%;"><span style="font-style:italic;"><?php echo _AT('description'); ?>:</span> + <?php echo $val['description']; ?></p> --> + + + <div style="font-size:95%; "> +<!-- + <a title="outline_collapsed" id="a_outline_<?php echo $val['short_name'];?>" onclick="javascript: trans.utility.toggleOutline('<?php echo $val['short_name'];?>', '<?php echo _AT('hide_outline'); ?>', '<?php echo _AT('show_outline'); ?>'); " href="javascript:void(0)"><?php echo _AT('show_outline'); ?></a> + <div style="display: none;" id="div_outline_<?php echo $val['short_name'];?>"> + <?php $struc_manag = new StructureManager($val['short_name']); + $struc_manag->printPreview(false, $val['short_name']); ?> + </div> --> + <div style=" margin-bottom: 10px; <?php if($check) echo 'border: 2px #cccccc dotted;';?> "> + <div class="struct_preview"> + <div style="display: inline;" id="div_outline_<?php echo $struct['short_name'];?>"> + <?php + $struc_manag = new StructureManager($struct['short_name']); + $struc_manag->printPreview(false, $struct['short_name']); + ?> + </div> + </div> + </div> + + </div> + </div> + + <?php + } + } + + + echo '</li>'; + } + + echo '</ol></div>'; + + } + + ?> + + <!-- <input type="checkbox"" name="title" id="ftitle1" class="formfield" value="bao"></input> --> + + </div> + + <div class="row buttons"> + <?php echo CSRF_Token::display(); ?><br> + <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" title="<?php echo _AT('save_changes'); ?> alt-s" accesskey="s" /> + </div> +</div> +</form> From 04dfc7a6097d36d9153a6761703bd8e4b7233191 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sun, 16 Sep 2018 19:21:40 +0700 Subject: [PATCH 39/94] Add files via upload --- tests/edit_question_likert.php | 353 ++++++++++++++------------- tests/edit_question_long.php | 207 ++++++++-------- tests/edit_question_matching.php | 356 ++++++++++++++------------- tests/edit_question_matchingdd.php | 340 +++++++++++++------------- tests/edit_question_multianswer.php | 356 ++++++++++++++------------- tests/edit_question_multichoice.php | 310 ++++++++++++------------ tests/edit_question_ordering.php | 358 +++++++++++++++------------- tests/edit_question_truefalse.php | 236 +++++++++--------- tests/edit_test.php | 112 +++++---- 9 files changed, 1375 insertions(+), 1253 deletions(-) diff --git a/tests/edit_question_likert.php b/tests/edit_question_likert.php index dfc57086..b60979a7 100644 --- a/tests/edit_question_likert.php +++ b/tests/edit_question_likert.php @@ -1,170 +1,183 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'../tests/lib/likert_presets.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); - -$qid = intval($_GET['qid']); -if ($qid == 0){ - $qid = intval($_POST['qid']); -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; -} else if (isset($_POST['submit'])) { - $_POST['question'] = trim($_POST['question']); - $_POST['category_id'] = intval($_POST['category_id']); - $_POST['alignment'] = intval($_POST['alignment']); - - $empty_fields = array(); - if ($_POST['question'] == ''){ - $empty_fields[] = _AT('question'); - } - if ($_POST['choice'][0] == '') { - $empty_fields[] = _AT('choice').' 1'; - } - - if ($_POST['choice'][1] == '') { - $empty_fields[] = _AT('choice').' 2'; - } - - if (!empty($empty_fields)) { - $msg->addError(array('EMPTY_FIELDS', implode(', ', $empty_fields))); - } - - if (!$msg->containsErrors()) { - - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = trim($_POST['choice'][$i]); - $_POST['answer'][$i] = intval($_POST['answer'][$i]); - - if ($_POST['choice'][$i] == '') { - /* an empty option can't be correct */ - $_POST['answer'][$i] = 0; - } - } - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET - category_id=?, - feedback=?, - question=?, - choice_0=?, - choice_1=?, - choice_2=?, - choice_3=?, - choice_4=?, - choice_5=?, - choice_6=?, - choice_7=?, - choice_8=?, - choice_9=?, - answer_0=?, - answer_1=?, - answer_2=?, - answer_3=?, - answer_4=?, - answer_5=?, - answer_6=?, - answer_7=?, - answer_8=?, - answer_9=? - WHERE question_id=?"; - $values= array($_POST['category_id'], - $_POST['feedback'], - $_POST['question'], - $_POST['choice'][0], - $_POST['choice'][1], - $_POST['choice'][2], - $_POST['choice'][3], - $_POST['choice'][4], - $_POST['choice'][5], - $_POST['choice'][6], - $_POST['choice'][7], - $_POST['choice'][8], - $_POST['choice'][9], - $_POST['answer'][0], - $_POST['answer'][1], - $_POST['answer'][2], - $_POST['answer'][3], - $_POST['answer'][4], - $_POST['answer'][5], - $_POST['answer'][6], - $_POST['answer'][7], - $_POST['answer'][8], - $_POST['answer'][9], - $_POST['qid']); - $types = "issssssssssssiiiiiiiiiii"; - $testsQuestionsDAO->execute($sql, $values, $types); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; - } -} else if (isset($_POST['preset'])) { - // load preset - $_POST['preset_num'] = intval($_POST['preset_num']); - - if (isset($_likert_preset[$_POST['preset_num']])) { - $_POST['choice'] = $_likert_preset[$_POST['preset_num']]; - } else if ($_POST['preset_num']) { - if ($row = $testsQuestionsDAO->get($_POST['preset_num'])){ - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = $row['choice_' . $i]; - } - } - } -} else { - if (!($row = $testsQuestionsDAO->get($qid))){ - require_once(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - $_POST['question'] = $row['question']; - $_POST['category_id'] = $row['category_id']; - - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = $row['choice_'.$i]; - } -} - -global $onload; -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('likert_preset', $_likert_preset); -$savant->assign('testsQuestionsDAO', $testsQuestionsDAO); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_likert.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'../tests/lib/likert_presets.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +global $_course_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); + +$qid = intval($_GET['qid']); +if ($qid == 0){ + $qid = intval($_POST['qid']); +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; +} else if (isset($_POST['submit'])) { + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + $_POST['alignment'] = intval($_POST['alignment']); + + $empty_fields = array(); + if ($_POST['question'] == ''){ + $empty_fields[] = _AT('question'); + } + if ($_POST['choice'][0] == '') { + $empty_fields[] = _AT('choice').' 1'; + } + + if ($_POST['choice'][1] == '') { + $empty_fields[] = _AT('choice').' 2'; + } + + if (!empty($empty_fields)) { + $msg->addError(array('EMPTY_FIELDS', implode(', ', $empty_fields))); + } + + if (!$msg->containsErrors()) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $purifier->purify(trim($_POST['choice'][$i])); + $_POST['answer'][$i] = intval($_POST['answer'][$i]); + + if ($_POST['choice'][$i] == '') { + /* an empty option can't be correct */ + $_POST['answer'][$i] = 0; + } + } + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET + category_id=?, + feedback=?, + question=?, + choice_0=?, + choice_1=?, + choice_2=?, + choice_3=?, + choice_4=?, + choice_5=?, + choice_6=?, + choice_7=?, + choice_8=?, + choice_9=?, + answer_0=?, + answer_1=?, + answer_2=?, + answer_3=?, + + answer_4=?, + answer_5=?, + answer_6=?, + answer_7=?, + answer_8=?, + answer_9=? + WHERE question_id=?"; + $values= array($_POST['category_id'], + $_POST['feedback'], + $_POST['question'], + $_POST['choice'][0], + $_POST['choice'][1], + $_POST['choice'][2], + $_POST['choice'][3], + $_POST['choice'][4], + $_POST['choice'][5], + $_POST['choice'][6], + $_POST['choice'][7], + $_POST['choice'][8], + $_POST['choice'][9], + $_POST['answer'][0], + $_POST['answer'][1], + $_POST['answer'][2], + $_POST['answer'][3], + $_POST['answer'][4], + $_POST['answer'][5], + $_POST['answer'][6], + $_POST['answer'][7], + $_POST['answer'][8], + $_POST['answer'][9], + $_POST['qid']); + $types = "issssssssssssiiiiiiiiiii"; + $testsQuestionsDAO->execute($sql, $values, $types); + + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; + } else + { + $msg->addError('INVALID_TOKEN'); + } + } +} else if (isset($_POST['preset'])) { + // load preset + $_POST['preset_num'] = intval($_POST['preset_num']); + + if (isset($_likert_preset[$_POST['preset_num']])) { + $_POST['choice'] = $_likert_preset[$_POST['preset_num']]; + } else if ($_POST['preset_num']) { + if ($row = $testsQuestionsDAO->get($_POST['preset_num'])){ + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $row['choice_' . $i]; + } + } + } +} else { + if (!($row = $testsQuestionsDAO->get($qid))){ + require_once(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + + $_POST['question'] = $row['question']; + $_POST['category_id'] = $row['category_id']; + + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $row['choice_'.$i]; + } +} + +global $onload; +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('likert_preset', $_likert_preset); +$savant->assign('testsQuestionsDAO', $testsQuestionsDAO); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_likert.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/edit_question_long.php b/tests/edit_question_long.php index c575fe16..71487341 100644 --- a/tests/edit_question_long.php +++ b/tests/edit_question_long.php @@ -1,97 +1,110 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); - -$qid = intval($_GET['qid']); -if ($qid == 0){ - $qid = intval($_POST['qid']); -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; -} else if (isset($_POST['submit'])) { - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['question'] = trim($_POST['question']); - $_POST['category_id'] = intval($_POST['category_id']); - $_POST['properties'] = intval($_POST['properties']); - - if ($_POST['question'] == ''){ - $msg->addError(array('EMPTY_FIELDS', _AT('question'))); - } - - if (!$msg->containsErrors()) { - $_POST['question'] = addslashes($_POST['question']); - $_POST['feedback'] = addslashes($_POST['feedback']); -/* - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET category_id=$_POST[category_id], - feedback='$_POST[feedback]', - question='$_POST[question]', - properties=$_POST[properties] - WHERE question_id=$_POST[qid]"; */ - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET category_id=?, - feedback=?, - question=?, - properties=? - WHERE question_id=?"; - $values = array($_POST['category_id'], - $_POST['feedback'], - $_POST['question'], - $_POST['properties'], - $_POST['qid'] ); - $types = "issii"; - $testsQuestionsDAO->execute($sql, $values, $types); - - $msg->addFeedback('QUESTION_UPDATED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; - } -} - -if (!isset($_POST['submit'])) { - if (!($row = $testsQuestionsDAO->get($qid))){ - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - $_POST = $row; -} - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$msg->printErrors(); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_long.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); + +$qid = intval($_GET['qid']); +if ($qid == 0){ + $qid = intval($_POST['qid']); +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; +} else if (isset($_POST['submit'])) { + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + $_POST['properties'] = intval($_POST['properties']); + + if ($_POST['question'] == ''){ + $msg->addError(array('EMPTY_FIELDS', _AT('question'))); + } + + if (!$msg->containsErrors()) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['question'] = addslashes($_POST['question']); + $_POST['feedback'] = addslashes($_POST['feedback']); +/* + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET category_id=$_POST[category_id], + feedback='$_POST[feedback]', + question='$_POST[question]', + properties=$_POST[properties] + WHERE question_id=$_POST[qid]"; */ + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET category_id=?, + feedback=?, + question=?, + properties=? + WHERE question_id=?"; + $values = array($_POST['category_id'], + $_POST['feedback'], + $_POST['question'], + $_POST['properties'], + $_POST['qid'] ); + $types = "issii"; + $testsQuestionsDAO->execute($sql, $values, $types); + + $msg->addFeedback('QUESTION_UPDATED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; + } else + { + $msg->addError('INVALID_TOKEN'); + } + } +} + +if (!isset($_POST['submit'])) { + if (!($row = $testsQuestionsDAO->get($qid))){ + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + + $_POST = $row; +} + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$msg->printErrors(); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_long.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); +?> diff --git a/tests/edit_question_matching.php b/tests/edit_question_matching.php index a6e278f8..0b414a30 100644 --- a/tests/edit_question_matching.php +++ b/tests/edit_question_matching.php @@ -1,170 +1,186 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'../tests/lib/likert_presets.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); - -// for matching test questions -$_letters = array(_AT('a'), _AT('b'), _AT('c'), _AT('d'), _AT('e'), _AT('f'), _AT('g'), _AT('h'), _AT('i'), _AT('j')); - -$qid = intval($_GET['qid']); -if ($qid == 0){ - $qid = intval($_POST['qid']); -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; -} else if (isset($_POST['submit'])) { - $_POST['tid'] = intval($_POST['tid']); - $_POST['qid'] = intval($_POST['qid']); - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['instructions'] = trim($_POST['instructions']); - $_POST['category_id'] = intval($_POST['category_id']); - - for ($i = 0 ; $i < 10; $i++) { - $_POST['question'][$i] = addslashes(trim($_POST['question'][$i])); - $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i]; - $_POST['answer'][$i] = addslashes(trim($_POST['answer'][$i])); - } - - if (!$_POST['question'][0] - || !$_POST['question'][1] - || !$_POST['answer'][0] - || !$_POST['answer'][1]) { - - $msg->addError('QUESTION_EMPTY'); - } - - if (!$msg->containsErrors()) { - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET - category_id=?, - feedback=?, - question=?, - choice_0=?, - choice_1=?, - choice_2=?, - choice_3=?, - choice_4=?, - choice_5=?, - choice_6=?, - choice_7=?, - choice_8=?, - choice_9=?, - answer_0=?, - answer_1=?, - answer_2=?, - answer_3=?, - answer_4=?, - answer_5=?, - answer_6=?, - answer_7=?, - answer_8=?, - answer_9=?, - option_0=?, - option_1=?, - option_2=?, - option_3=?, - option_4=?, - option_5=?, - option_6=?, - option_7=?, - option_8=?, - option_9=? - WHERE question_id=?"; - $values = array($_POST['category_id'], - $_POST['feedback'], - $_POST['instructions'], - $_POST['question'][0], - $_POST['question'][1], - $_POST['question'][2], - $_POST['question'][3], - $_POST['question'][4], - $_POST['question'][5], - $_POST['question'][6], - $_POST['question'][7], - $_POST['question'][8], - $_POST['question'][9], - $_POST['question_answer'][0], - $_POST['question_answer'][1], - $_POST['question_answer'][2], - $_POST['question_answer'][3], - $_POST['question_answer'][4], - $_POST['question_answer'][5], - $_POST['question_answer'][6], - $_POST['question_answer'][7], - $_POST['question_answer'][8], - $_POST['question_answer'][9], - $_POST['answer'][0], - $_POST['answer'][1], - $_POST['answer'][2], - $_POST['answer'][3], - $_POST['answer'][4], - $_POST['answer'][5], - $_POST['answer'][6], - $_POST['answer'][7], - $_POST['answer'][8], - $_POST['answer'][9], - $_POST['qid'] - ); - $types = "issssssssssssiiiiiiiiiissssssssssi"; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; - } - } -} else { - if (!($row = $testsQuestionsDAO->get($qid))){ - require_once(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - $_POST['feedback'] = $row['feedback']; - $_POST['instructions'] = $row['question']; - $_POST['category_id'] = $row['category_id']; - - for ($i=0; $i<10; $i++) { - $_POST['question'][$i] = $row['choice_'.$i]; - $_POST['question_answer'][$i] = $row['answer_'.$i]; - $_POST['answer'][$i] = $row['option_'.$i]; - } -} - -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('letters', $_letters); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_matching.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'../tests/lib/likert_presets.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); + +// for matching test questions +$_letters = array(_AT('a'), _AT('b'), _AT('c'), _AT('d'), _AT('e'), _AT('f'), _AT('g'), _AT('h'), _AT('i'), _AT('j')); + +$qid = intval($_GET['qid']); +if ($qid == 0){ + $qid = intval($_POST['qid']); +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; +} else if (isset($_POST['submit'])) { + $_POST['tid'] = intval($_POST['tid']); + $_POST['qid'] = intval($_POST['qid']); + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['instructions'] = $purifier->purify(trim($_POST['instructions'])); + $_POST['category_id'] = intval($_POST['category_id']); + + for ($i = 0 ; $i < 10; $i++) { + $_POST['question'][$i] = addslashes(trim($_POST['question'][$i])); + $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i]; + $_POST['answer'][$i] = addslashes(trim($_POST['answer'][$i])); + } + + if (!$_POST['question'][0] + || !$_POST['question'][1] + || !$_POST['answer'][0] + || !$_POST['answer'][1]) { + + $msg->addError('QUESTION_EMPTY'); + } + + if (!$msg->containsErrors()) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET + category_id=?, + feedback=?, + question=?, + choice_0=?, + choice_1=?, + choice_2=?, + choice_3=?, + choice_4=?, + choice_5=?, + choice_6=?, + choice_7=?, + choice_8=?, + choice_9=?, + answer_0=?, + answer_1=?, + answer_2=?, + answer_3=?, + answer_4=?, + answer_5=?, + answer_6=?, + answer_7=?, + answer_8=?, + answer_9=?, + option_0=?, + option_1=?, + + option_2=?, + option_3=?, + option_4=?, + option_5=?, + + option_6=?, + option_7=?, + option_8=?, + option_9=? + + WHERE question_id=?"; + $values = array($_POST['category_id'], + $_POST['feedback'], + $_POST['instructions'], + $_POST['question'][0], + $_POST['question'][1], + $_POST['question'][2], + $_POST['question'][3], + $_POST['question'][4], + $_POST['question'][5], + $_POST['question'][6], + $_POST['question'][7], + $_POST['question'][8], + $_POST['question'][9], + $_POST['question_answer'][0], + $_POST['question_answer'][1], + $_POST['question_answer'][2], + $_POST['question_answer'][3], + $_POST['question_answer'][4], + $_POST['question_answer'][5], + $_POST['question_answer'][6], + $_POST['question_answer'][7], + $_POST['question_answer'][8], + $_POST['question_answer'][9], + $_POST['answer'][0], + $_POST['answer'][1], + $_POST['answer'][2], + $_POST['answer'][3], + $_POST['answer'][4], + $_POST['answer'][5], + $_POST['answer'][6], + $_POST['answer'][7], + $_POST['answer'][8], + $_POST['answer'][9], + $_POST['qid'] + ); + $types = "issssssssssssiiiiiiiiiissssssssssi"; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; + } + } else + { + $msg->addError('INVALID_TOKEN'); + } + } +} else { + if (!($row = $testsQuestionsDAO->get($qid))){ + require_once(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + $_POST['feedback'] = $row['feedback']; + $_POST['instructions'] = $row['question']; + $_POST['category_id'] = $row['category_id']; + + for ($i=0; $i<10; $i++) { + $_POST['question'][$i] = $row['choice_'.$i]; + $_POST['question_answer'][$i] = $row['answer_'.$i]; + $_POST['answer'][$i] = $row['option_'.$i]; + } +} + +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('letters', $_letters); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_matching.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/edit_question_matchingdd.php b/tests/edit_question_matchingdd.php index be369f7c..602f0ca4 100644 --- a/tests/edit_question_matchingdd.php +++ b/tests/edit_question_matchingdd.php @@ -1,171 +1,171 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -//require_once(TR_INCLUDE_PATH.'../tests/lib/likert_presets.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); - -// for matching test questions -$_letters = array(_AT('a'), _AT('b'), _AT('c'), _AT('d'), _AT('e'), _AT('f'), _AT('g'), _AT('h'), _AT('i'), _AT('j')); - -$qid = intval($_GET['qid']); -if ($qid == 0){ - $qid = intval($_POST['qid']); -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - if (isset($_POST['tid'])) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; -} else if (isset($_POST['submit'])) { - $_POST['tid'] = intval($_POST['tid']); - $_POST['qid'] = intval($_POST['qid']); - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['instructions'] = trim($_POST['instructions']); - $_POST['category_id'] = intval($_POST['category_id']); - - for ($i = 0 ; $i < 10; $i++) { - $_POST['question'][$i] = trim($_POST['question'][$i]); - $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i]; - $_POST['answer'][$i] = trim($_POST['answer'][$i]); - } - - if (!$_POST['question'][0] - || !$_POST['question'][1] - || !$_POST['answer'][0] - || !$_POST['answer'][1]) { - - $msg->addError('QUESTION_EMPTY'); - } - - if (!$msg->containsErrors()) { - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET - category_id=?, - feedback=?, - question=?, - choice_0=?, - choice_1=?, - choice_2=?, - choice_3=?, - choice_4=?, - choice_5=?, - choice_6=?, - choice_7=?, - choice_8=?, - choice_9=?, - answer_0=?, - answer_1=?, - answer_2=?, - answer_3=?, - answer_4=?, - answer_5=?, - answer_6=?, - answer_7=?, - answer_8=?, - answer_9=?, - option_0=?, - option_1=?, - option_2=?, - option_3=?, - option_4=?, - option_5=?, - option_6=?, - option_7=?, - option_8=?, - option_9=? - WHERE question_id=?"; - $values = array($_POST['category_id'], - $_POST['feedback'], - $_POST['instructions'], - $_POST['question'][0], - $_POST['question'][1], - $_POST['question'][2], - $_POST['question'][3], - $_POST['question'][4], - $_POST['question'][5], - $_POST['question'][6], - $_POST['question'][7], - $_POST['question'][8], - $_POST['question'][9], - $_POST['question_answer'][0], - $_POST['question_answer'][1], - $_POST['question_answer'][2], - $_POST['question_answer'][3], - $_POST['question_answer'][4], - $_POST['question_answer'][5], - $_POST['question_answer'][6], - $_POST['question_answer'][7], - $_POST['question_answer'][8], - $_POST['question_answer'][9], - $_POST['answer'][0], - $_POST['answer'][1], - $_POST['answer'][2], - $_POST['answer'][3], - $_POST['answer'][4], - $_POST['answer'][5], - $_POST['answer'][6], - $_POST['answer'][7], - $_POST['answer'][8], - $_POST['answer'][9], - $_POST['qid'] - ); - $types = "issssssssssssiiiiiiiiiissssssssssi"; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; - } - } -} else { - if (!($row = $testsQuestionsDAO->get($qid))){ - require_once(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - $_POST['feedback'] = $row['feedback']; - $_POST['instructions'] = $row['question']; - $_POST['category_id'] = $row['category_id']; - - for ($i=0; $i<10; $i++) { - $_POST['question'][$i] = $row['choice_'.$i]; - $_POST['question_answer'][$i] = $row['answer_'.$i]; - $_POST['answer'][$i] = $row['option_'.$i]; - } - -} -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('letters', $_letters); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_matchingdd.tmpl.php'); - +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +//require_once(TR_INCLUDE_PATH.'../tests/lib/likert_presets.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); + +global $_course_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); + +// for matching test questions +$_letters = array(_AT('a'), _AT('b'), _AT('c'), _AT('d'), _AT('e'), _AT('f'), _AT('g'), _AT('h'), _AT('i'), _AT('j')); + +$qid = intval($_GET['qid']); +if ($qid == 0){ + $qid = intval($_POST['qid']); +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + if (isset($_POST['tid'])) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; +} else if (isset($_POST['submit'])) { + $_POST['tid'] = intval($_POST['tid']); + $_POST['qid'] = intval($_POST['qid']); + $_POST['feedback'] = trim($_POST['feedback']); + $_POST['instructions'] = trim($_POST['instructions']); + $_POST['category_id'] = intval($_POST['category_id']); + + for ($i = 0 ; $i < 10; $i++) { + $_POST['question'][$i] = trim($_POST['question'][$i]); + $_POST['question_answer'][$i] = (int) $_POST['question_answer'][$i]; + $_POST['answer'][$i] = trim($_POST['answer'][$i]); + } + + if (!$_POST['question'][0] + || !$_POST['question'][1] + || !$_POST['answer'][0] + || !$_POST['answer'][1]) { + + $msg->addError('QUESTION_EMPTY'); + } + + if (!$msg->containsErrors()) { + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET + category_id=?, + feedback=?, + question=?, + choice_0=?, + choice_1=?, + choice_2=?, + choice_3=?, + choice_4=?, + choice_5=?, + choice_6=?, + choice_7=?, + choice_8=?, + choice_9=?, + answer_0=?, + answer_1=?, + answer_2=?, + answer_3=?, + answer_4=?, + answer_5=?, + answer_6=?, + answer_7=?, + answer_8=?, + answer_9=?, + option_0=?, + option_1=?, + option_2=?, + option_3=?, + option_4=?, + option_5=?, + option_6=?, + option_7=?, + option_8=?, + option_9=? + WHERE question_id=?"; + $values = array($_POST['category_id'], + $_POST['feedback'], + $_POST['instructions'], + $_POST['question'][0], + $_POST['question'][1], + $_POST['question'][2], + $_POST['question'][3], + $_POST['question'][4], + $_POST['question'][5], + $_POST['question'][6], + $_POST['question'][7], + $_POST['question'][8], + $_POST['question'][9], + $_POST['question_answer'][0], + $_POST['question_answer'][1], + $_POST['question_answer'][2], + $_POST['question_answer'][3], + $_POST['question_answer'][4], + $_POST['question_answer'][5], + $_POST['question_answer'][6], + $_POST['question_answer'][7], + $_POST['question_answer'][8], + $_POST['question_answer'][9], + $_POST['answer'][0], + $_POST['answer'][1], + $_POST['answer'][2], + $_POST['answer'][3], + $_POST['answer'][4], + $_POST['answer'][5], + $_POST['answer'][6], + $_POST['answer'][7], + $_POST['answer'][8], + $_POST['answer'][9], + $_POST['qid'] + ); + $types = "issssssssssssiiiiiiiiiissssssssssi"; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; + } + } +} else { + if (!($row = $testsQuestionsDAO->get($qid))){ + require_once(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + $_POST['feedback'] = $row['feedback']; + $_POST['instructions'] = $row['question']; + $_POST['category_id'] = $row['category_id']; + + for ($i=0; $i<10; $i++) { + $_POST['question'][$i] = $row['choice_'.$i]; + $_POST['question_answer'][$i] = $row['answer_'.$i]; + $_POST['answer'][$i] = $row['option_'.$i]; + } + +} +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('letters', $_letters); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_matchingdd.tmpl.php'); + require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file diff --git a/tests/edit_question_multianswer.php b/tests/edit_question_multianswer.php index ab4ae0a0..6c42dfa9 100644 --- a/tests/edit_question_multianswer.php +++ b/tests/edit_question_multianswer.php @@ -1,169 +1,187 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); - -$qid = intval($_GET['qid']); -if ($qid == 0){ - $qid = intval($_POST['qid']); -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; -} else if (isset($_POST['submit'])) { - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['question'] = trim($_POST['question']); - $_POST['tid'] = intval($_POST['tid']); - $_POST['qid'] = intval($_POST['qid']); - $_POST['weight'] = intval($_POST['weight']); - - if ($_POST['question'] == ''){ - $msg->addError(array('EMPTY_FIELDS', _AT('question'))); - } - - if (!$msg->containsErrors()) { - $choice_new = array(); // stores the non-blank choices - $answer_new = array(); // stores the associated "answer" for the choices - - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = addslashes(trim($_POST['choice'][$i])); - /** - * Db defined it to be 255 length, chop strings off it it's less than that - * @harris - */ - $_POST['choice'][$i] = Utility::validateLength($_POST['choice'][$i], 255); - $_POST['answer'][$i] = intval($_POST['answer'][$i]); - - if ($_POST['choice'][$i] == '') { - /* an empty option can't be correct */ - $_POST['answer'][$i] = 0; - } else { - /* filter out empty choices/ remove gaps */ - $choice_new[] = $_POST['choice'][$i]; - $answer_new[] = $_POST['answer'][$i]; - } - } - - $_POST['answer'] = $answer_new; - $_POST['choice'] = $choice_new; - $_POST['answer'] = array_pad($_POST['answer'], 10, 0); - $_POST['choice'] = array_pad($_POST['choice'], 10, ''); - - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET - category_id=?, - feedback=?, - question=?, - choice_0=?, - choice_1=?, - choice_2=?, - choice_3=?, - choice_4=?, - choice_5=?, - choice_6=?, - choice_7=?, - choice_8=?, - choice_9=?, - answer_0=?, - answer_1=?, - answer_2=?, - answer_3=?, - answer_4=?, - answer_5=?, - answer_6=?, - answer_7=?, - answer_8=?, - answer_9=? - WHERE question_id=?"; - - $values = array($_POST['category_id'], - $_POST['feedback'], - $_POST['question'], - $_POST['choice'][0], - $_POST['choice'][1], - $_POST['choice'][2], - $_POST['choice'][3], - $_POST['choice'][4], - $_POST['choice'][5], - $_POST['choice'][6], - $_POST['choice'][7], - $_POST['choice'][8], - $_POST['choice'][9], - $_POST['answer'][0], - $_POST['answer'][1], - $_POST['answer'][2], - $_POST['answer'][3], - $_POST['answer'][4], - $_POST['answer'][5], - $_POST['answer'][6], - $_POST['answer'][7], - $_POST['answer'][8], - $_POST['answer'][9], - $_POST['qid']); - $types = "issssssssssssiiiiiiiiiii"; - - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('QUESTION_UPDATED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; - } - else - { - $msg->addError('DB_NOT_UPDATED'); - } - } -} - -if (!isset($_POST['submit'])) { - if (!($row = $testsQuestionsDAO->get($qid))){ - require_once(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - $_POST['category_id'] = $row['category_id']; - $_POST['feedback'] = $row['feedback']; - $_POST['weight'] = $row['weight']; - $_POST['question'] = $row['question']; - - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = $row['choice_'.$i]; - $_POST['answer'][$i] = $row['answer_'.$i]; - } -} - -$onload = 'document.form.category_id.focus();'; -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_multianswer.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +global $_course_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); + +$qid = intval($_GET['qid']); +if ($qid == 0){ + $qid = intval($_POST['qid']); +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; +} else if (isset($_POST['submit'])) { + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['tid'] = intval($_POST['tid']); + $_POST['qid'] = intval($_POST['qid']); + $_POST['weight'] = intval($_POST['weight']); + + if ($_POST['question'] == ''){ + $msg->addError(array('EMPTY_FIELDS', _AT('question'))); + } + + if (!$msg->containsErrors()) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $choice_new = array(); // stores the non-blank choices + $answer_new = array(); // stores the associated "answer" for the choices + + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = addslashes(trim($_POST['choice'][$i])); + /** + * Db defined it to be 255 length, chop strings off it it's less than that + * @harris + */ + $_POST['choice'][$i] = Utility::validateLength($_POST['choice'][$i], 255); + $_POST['answer'][$i] = intval($_POST['answer'][$i]); + + if ($_POST['choice'][$i] == '') { + /* an empty option can't be correct */ + $_POST['answer'][$i] = 0; + } else { + /* filter out empty choices/ remove gaps */ + $choice_new[] = $_POST['choice'][$i]; + $answer_new[] = $_POST['answer'][$i]; + } + } + + $_POST['answer'] = $answer_new; + $_POST['choice'] = $choice_new; + $_POST['answer'] = array_pad($_POST['answer'], 10, 0); + $_POST['choice'] = array_pad($_POST['choice'], 10, ''); + + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET + category_id=?, + feedback=?, + question=?, + choice_0=?, + choice_1=?, + choice_2=?, + choice_3=?, + choice_4=?, + choice_5=?, + choice_6=?, + + choice_7=?, + choice_8=?, + choice_9=?, + + answer_0=?, + answer_1=?, + + answer_2=?, + answer_3=?, + answer_4=?, + + answer_5=?, + answer_6=?, + answer_7=?, + answer_8=?, + + answer_9=? + WHERE question_id=?"; + + $values = array($_POST['category_id'], + $_POST['feedback'], + $_POST['question'], + $_POST['choice'][0], + $_POST['choice'][1], + $_POST['choice'][2], + $_POST['choice'][3], + $_POST['choice'][4], + $_POST['choice'][5], + $_POST['choice'][6], + $_POST['choice'][7], + $_POST['choice'][8], + $_POST['choice'][9], + $_POST['answer'][0], + $_POST['answer'][1], + $_POST['answer'][2], + $_POST['answer'][3], + $_POST['answer'][4], + $_POST['answer'][5], + $_POST['answer'][6], + $_POST['answer'][7], + $_POST['answer'][8], + $_POST['answer'][9], + $_POST['qid']); + $types = "issssssssssssiiiiiiiiiii"; + + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('QUESTION_UPDATED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; + } + else + { + $msg->addError('DB_NOT_UPDATED'); + } + } else + { + $msg->addError('INVALID_TOKEN'); + } + } +} + +if (!isset($_POST['submit'])) { + if (!($row = $testsQuestionsDAO->get($qid))){ + require_once(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + $_POST['category_id'] = $row['category_id']; + $_POST['feedback'] = $row['feedback']; + $_POST['weight'] = $row['weight']; + $_POST['question'] = $row['question']; + + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $row['choice_'.$i]; + $_POST['answer'][$i] = $row['answer_'.$i]; + } +} + +$onload = 'document.form.category_id.focus();'; +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_multianswer.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/edit_question_multichoice.php b/tests/edit_question_multichoice.php index 491d33f9..0d54b0ad 100644 --- a/tests/edit_question_multichoice.php +++ b/tests/edit_question_multichoice.php @@ -1,146 +1,164 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); - -$qid = intval($_GET['qid']); -if ($qid == 0){ - $qid = intval($_POST['qid']); -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; -} else if (isset($_POST['submit'])) { - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['question'] = trim($_POST['question']); - $_POST['tid'] = intval($_POST['tid']); - $_POST['qid'] = intval($_POST['qid']); - $_POST['weight'] = intval($_POST['weight']); - $_POST['answer'] = intval($_POST['answer']); - - if ($_POST['question'] == ''){ - $msg->addError(array('EMPTY_FIELDS', _AT('question'))); - } - - if (!$msg->containsErrors()) { - $answers = array_fill(0, 10, 0); - $answers[$_POST['answer']] = 1; - - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = trim($_POST['choice'][$i]); - } - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET - category_id=?, - feedback=?, - question=?, - choice_0=?, - choice_1=?, - choice_2=?, - choice_3=?, - choice_4=?, - choice_5=?, - choice_6=?, - choice_7=?, - choice_8=?, - choice_9=?, - answer_0=?, - answer_1=?, - answer_2=?, - answer_3=?, - answer_4=?, - answer_5=?, - answer_6=?, - answer_7=?, - answer_8=?, - answer_9=? - WHERE question_id=?"; - $values= array($_POST['category_id'], - $_POST['feedback'], - $_POST['question'], - $_POST['choice'][0], - $_POST['choice'][1], - $_POST['choice'][2], - $_POST['choice'][3], - $_POST['choice'][4], - $_POST['choice'][5], - $_POST['choice'][6], - $_POST['choice'][7], - $_POST['choice'][8], - $_POST['choice'][9], - $answers[0], - $answers[0], - $answers[0], - $answers[0], - $answers[0], - $answers[0], - $answers[0], - $answers[0], - $answers[0], - $answers[0], - $_POST['qid']); - $types = "issssssssssssiiiiiiiiiii"; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('QUESTION_UPDATED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; - } - else - $msg->addError('DB_NOT_UPDATED'); - } -} - -if (!isset($_POST['submit'])) { - if (!($row = $testsQuestionsDAO->get($qid))){ - require_once(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - $_POST['category_id'] = $row['category_id']; - $_POST['feedback'] = $row['feedback']; - $_POST['weight'] = $row['weight']; - $_POST['question'] = $row['question']; - - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = $row['choice_'.$i]; - $_POST['answer'][$i] = $row['answer_'.$i]; - } -} - -$onload = 'document.form.category_id.focus();'; -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_multichoice.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +global $_course_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); + +$qid = intval($_GET['qid']); +if ($qid == 0){ + $qid = intval($_POST['qid']); +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; +} else if (isset($_POST['submit'])) { + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['tid'] = intval($_POST['tid']); + $_POST['qid'] = intval($_POST['qid']); + $_POST['weight'] = intval($_POST['weight']); + $_POST['answer'] = intval($_POST['answer']); + + if ($_POST['question'] == ''){ + $msg->addError(array('EMPTY_FIELDS', _AT('question'))); + } + + if (!$msg->containsErrors()) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $answers = array_fill(0, 10, 0); + $answers[$_POST['answer']] = 1; + + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = trim($_POST['choice'][$i]); + } + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET + category_id=?, + feedback=?, + question=?, + choice_0=?, + choice_1=?, + + choice_2=?, + choice_3=?, + choice_4=?, + choice_5=?, + choice_6=?, + + choice_7=?, + choice_8=?, + choice_9=?, + answer_0=?, + answer_1=?, + + answer_2=?, + answer_3=?, + answer_4=?, + answer_5=?, + answer_6=?, + + answer_7=?, + answer_8=?, + answer_9=? + + WHERE question_id=?"; + $values= array($_POST['category_id'], + $_POST['feedback'], + $_POST['question'], + $_POST['choice'][0], + $_POST['choice'][1], + $_POST['choice'][2], + $_POST['choice'][3], + $_POST['choice'][4], + $_POST['choice'][5], + $_POST['choice'][6], + $_POST['choice'][7], + $_POST['choice'][8], + $_POST['choice'][9], + $answers[0], + $answers[0], + $answers[0], + $answers[0], + $answers[0], + $answers[0], + $answers[0], + $answers[0], + $answers[0], + $answers[0], + $_POST['qid']); + $types = "issssssssssssiiiiiiiiiii"; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('QUESTION_UPDATED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; + } else { + $msg->addError('DB_NOT_UPDATED'); + } + } else + { + $msg->addError('INVALID_TOKEN'); + } + } +} + +if (!isset($_POST['submit'])) { + if (!($row = $testsQuestionsDAO->get($qid))){ + require_once(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + $_POST['category_id'] = $row['category_id']; + $_POST['feedback'] = $row['feedback']; + $_POST['weight'] = $row['weight']; + $_POST['question'] = $row['question']; + + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $row['choice_'.$i]; + $_POST['answer'][$i] = $row['answer_'.$i]; + } +} + +$onload = 'document.form.category_id.focus();'; +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_multichoice.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); +?> diff --git a/tests/edit_question_ordering.php b/tests/edit_question_ordering.php index cce2c4ef..1004bc91 100644 --- a/tests/edit_question_ordering.php +++ b/tests/edit_question_ordering.php @@ -1,168 +1,190 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); - -$qid = intval($_GET['qid']); -if ($qid == 0){ - $qid = intval($_POST['qid']); -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; -} else if (isset($_POST['submit'])) { - $missing_fields = array(); - - $_POST['feedback'] = trim($_POST['feedback']); - $_POST['question'] = trim($_POST['question']); - $_POST['category_id'] = intval($_POST['category_id']); - - if ($_POST['question'] == ''){ - $missing_fields[] = _AT('question'); - } - - if (trim($_POST['choice'][0]) == '') { - $missing_fields[] = _AT('item').' 1'; - } - if (trim($_POST['choice'][1]) == '') { - $missing_fields[] = _AT('item').' 2'; - } - - if ($missing_fields) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } - if (!$msg->containsErrors()) { - $choice_new = array(); // stores the non-blank choices - $answer_new = array(); // stores the non-blank answers - $order = 0; // order count - for ($i=0; $i<10; $i++) { - /** - * Db defined it to be 255 length, chop strings off it it's less than that - * @harris - */ - $_POST['choice'][$i] = Utility::validateLength($_POST['choice'][$i], 255); - $_POST['choice'][$i] = trim($_POST['choice'][$i]); - - if ($_POST['choice'][$i] != '') { - /* filter out empty choices/ remove gaps */ - $choice_new[] = $_POST['choice'][$i]; - $answer_new[] = $order++; - } - } - - $_POST['choice'] = array_pad($choice_new, 10, ''); - $answer_new = array_pad($answer_new, 10, 0); - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET - category_id=?, - feedback=?, - question=?, - choice_0=?, - choice_1=?, - choice_2=?, - choice_3=?, - choice_4=?, - choice_5=?, - choice_6=?, - choice_7=?, - choice_8=?, - choice_9=?, - answer_0=?, - answer_0=?, - answer_0=?, - answer_0=?, - answer_0=?, - answer_0=?, - answer_0=?, - answer_0=?, - answer_0=?, - answer_0=? - WHERE question_id=?"; - - $values = array($_POST['category_id'], - $_POST['feedback'], - $_POST['question'], - $_POST['choice'][0], - $_POST['choice'][1], - $_POST['choice'][2], - $_POST['choice'][3], - $_POST['choice'][4], - $_POST['choice'][5], - $_POST['choice'][6], - $_POST['choice'][7], - $_POST['choice'][8], - $_POST['choice'][9], - $answer_new[0], - $answer_new[1], - $answer_new[2], - $answer_new[3], - $answer_new[4], - $answer_new[5], - $answer_new[6], - $answer_new[7], - $answer_new[8], - $answer_new[9], - $_POST['qid']); - $types = "issssssssssssiiiiiiiiiii"; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; - } - else - $msg->addError('DB_NOT_UPDATED'); - } -} else { - if (!($row = $testsQuestionsDAO->get($qid))){ - require_once(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - $_POST['required'] = $row['required']; - $_POST['question'] = $row['question']; - $_POST['category_id'] = $row['category_id']; - $_POST['feedback'] = $row['feedback']; - - for ($i=0; $i<10; $i++) { - $_POST['choice'][$i] = $row['choice_'.$i]; - } -} - -$onload = 'document.form.category_id.focus();'; -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_ordering.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +global $_course_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); + +$qid = intval($_GET['qid']); +if ($qid == 0){ + $qid = intval($_POST['qid']); +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; +} else if (isset($_POST['submit'])) { + $missing_fields = array(); + + $_POST['feedback'] = $purifier->purify(trim($_POST['feedback'])); + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + $_POST['category_id'] = intval($_POST['category_id']); + + if ($_POST['question'] == ''){ + $missing_fields[] = _AT('question'); + } + + if (trim($_POST['choice'][0]) == '') { + $missing_fields[] = _AT('item').' 1'; + } + if (trim($_POST['choice'][1]) == '') { + $missing_fields[] = _AT('item').' 2'; + } + + if ($missing_fields) { + $missing_fields = implode(', ', $missing_fields); + $msg->addError(array('EMPTY_FIELDS', $missing_fields)); + } + if (!$msg->containsErrors()) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $choice_new = array(); // stores the non-blank choices + $answer_new = array(); // stores the non-blank answers + $order = 0; // order count + for ($i=0; $i<10; $i++) { + /** + * Db defined it to be 255 length, chop strings off it it's less than that + * @harris + */ + $_POST['choice'][$i] = Utility::validateLength($_POST['choice'][$i], 255); + $_POST['choice'][$i] = trim($_POST['choice'][$i]); + + if ($_POST['choice'][$i] != '') { + /* filter out empty choices/ remove gaps */ + $choice_new[] = $_POST['choice'][$i]; + $answer_new[] = $order++; + } + } + + $_POST['choice'] = array_pad($choice_new, 10, ''); + $answer_new = array_pad($answer_new, 10, 0); + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET + category_id=?, + feedback=?, + + question=?, + choice_0=?, + + choice_1=?, + choice_2=?, + choice_3=?, + + choice_4=?, + choice_5=?, + choice_6=?, + + choice_7=?, + choice_8=?, + choice_9=?, + + answer_0=?, + answer_0=?, + answer_0=?, + + answer_0=?, + answer_0=?, + answer_0=?, + + answer_0=?, + answer_0=?, + answer_0=?, + + answer_0=? + WHERE question_id=?"; + + $values = array($_POST['category_id'], + $_POST['feedback'], + $_POST['question'], + $_POST['choice'][0], + $_POST['choice'][1], + $_POST['choice'][2], + $_POST['choice'][3], + $_POST['choice'][4], + $_POST['choice'][5], + $_POST['choice'][6], + $_POST['choice'][7], + $_POST['choice'][8], + $_POST['choice'][9], + $answer_new[0], + $answer_new[1], + $answer_new[2], + $answer_new[3], + $answer_new[4], + $answer_new[5], + $answer_new[6], + $answer_new[7], + $answer_new[8], + $answer_new[9], + $_POST['qid']); + $types = "issssssssssssiiiiiiiiiii"; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; + } + else { + $msg->addError('DB_NOT_UPDATED'); + } + } else + { + $msg->addError('INVALID_TOKEN'); + } + } +} else { + if (!($row = $testsQuestionsDAO->get($qid))){ + require_once(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + + $_POST['required'] = $row['required']; + $_POST['question'] = $row['question']; + $_POST['category_id'] = $row['category_id']; + $_POST['feedback'] = $row['feedback']; + + for ($i=0; $i<10; $i++) { + $_POST['choice'][$i] = $row['choice_'.$i]; + } +} + +$onload = 'document.form.category_id.focus();'; +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_ordering.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/edit_question_truefalse.php b/tests/edit_question_truefalse.php index 59e4b80d..0c5dd8fd 100644 --- a/tests/edit_question_truefalse.php +++ b/tests/edit_question_truefalse.php @@ -1,111 +1,125 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -$page = 'tests'; -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); - -$qid = intval($_GET['qid']); -if ($qid == 0){ - $qid = intval($_POST['qid']); -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; -} else if (isset($_POST['submit'])) { - - $_POST['question'] = trim($_POST['question']); - - if ($_POST['question'] == ''){ - $msg->addError(array('EMPTY_FIELDS', _AT('statement'))); - } - - if (!$msg->containsErrors()) { - $_POST['feedback'] = trim($_POST['feedback']); - $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET category_id=$_POST[category_id], - feedback='$_POST[feedback]', - question='$_POST[question]', - answer_0={$_POST[answer]} - WHERE question_id=$_POST[qid]"; - $values = array($_POST['category_id'], $_POST['feedback'], $_POST['question'], $_POST['answer'], $_POST['qid']); - $types = "isssi"; - if ($testsQuestionsDAO->execute($sql, $values, $types)) { - $msg->addFeedback('QUESTION_UPDATED'); - if ($_POST['tid']) { - header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); - } else { - header('Location: question_db.php?_course_id='.$_course_id); - } - exit; - } - else - $msg->addError('DB_NOT_UPDATED'); - } -} - -if (!$_POST['submit']) { - if (!($row = $testsQuestionsDAO->get($qid))){ - $msg->printErrors('ITEM_NOT_FOUND'); - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - $_POST = $row; -} - -if ($_POST['answer'] == '') { - if ($_POST['answer_0'] == 1) { - $ans_yes = ' checked="checked"'; - } else if ($_POST['answer_0'] == 2){ - $ans_no = ' checked="checked"'; - } else if ($_POST['answer_0'] == 3) { - $ans_yes1 = ' checked="checked"'; - } else { - $ans_no1 = ' checked="checked"'; - } -} else { - if ($_POST['answer'] == 1) { - $ans_yes = ' checked="checked"'; - } else if($_POST['answer'] == 2){ - $ans_no = ' checked="checked"'; - } else if ($_POST['answer'] == 3) { - $ans_yes1 = ' checked="checked"'; - } else { - $ans_no1 = ' checked="checked"'; - } -} - -$onload = 'document.form.category_id.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('qid', $qid); -$savant->assign('tid', $_REQUEST['tid']); -$savant->assign('ans_yes', $ans_yes); -$savant->assign('ans_no', $ans_no); -$savant->assign('course_id', $_course_id); -$savant->display('tests/create_edit_question_truefalse.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +$page = 'tests'; +define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +global $_course_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); + +$qid = intval($_GET['qid']); +if ($qid == 0){ + $qid = intval($_POST['qid']); +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; +} else if (isset($_POST['submit'])) { + + $_POST['question'] = $purifier->purify(trim($_POST['question'])); + + if ($_POST['question'] == ''){ + $msg->addError(array('EMPTY_FIELDS', _AT('statement'))); + } + + if (!$msg->containsErrors()) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + $_POST['feedback'] = trim($_POST['feedback']); + $sql = "UPDATE ".TABLE_PREFIX."tests_questions SET category_id=$_POST[category_id], + feedback='$_POST[feedback]', + question='$_POST[question]', + answer_0={$_POST[answer]} + WHERE question_id=$_POST[qid]"; + $values = array($_POST['category_id'], $_POST['feedback'], $_POST['question'], $_POST['answer'], $_POST['qid']); + $types = "isssi"; + if ($testsQuestionsDAO->execute($sql, $values, $types)) { + $msg->addFeedback('QUESTION_UPDATED'); + if ($_POST['tid']) { + header('Location: questions.php?tid='.$_POST['tid'].'&_course_id='.$_course_id); + } else { + header('Location: question_db.php?_course_id='.$_course_id); + } + exit; + } + else { + $msg->addError('DB_NOT_UPDATED'); + } + } else + { + $msg->addError('INVALID_TOKEN'); + } + } +} + +if (!$_POST['submit']) { + if (!($row = $testsQuestionsDAO->get($qid))){ + $msg->printErrors('ITEM_NOT_FOUND'); + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + + $_POST = $row; +} + +if ($_POST['answer'] == '') { + if ($_POST['answer_0'] == 1) { + $ans_yes = ' checked="checked"'; + } else if ($_POST['answer_0'] == 2){ + $ans_no = ' checked="checked"'; + } else if ($_POST['answer_0'] == 3) { + $ans_yes1 = ' checked="checked"'; + } else { + $ans_no1 = ' checked="checked"'; + } +} else { + if ($_POST['answer'] == 1) { + $ans_yes = ' checked="checked"'; + } else if($_POST['answer'] == 2){ + $ans_no = ' checked="checked"'; + } else if ($_POST['answer'] == 3) { + $ans_yes1 = ' checked="checked"'; + } else { + $ans_no1 = ' checked="checked"'; + } +} + +$onload = 'document.form.category_id.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('qid', $qid); +$savant->assign('tid', $_REQUEST['tid']); +$savant->assign('ans_yes', $ans_yes); +$savant->assign('ans_no', $ans_no); +$savant->assign('course_id', $_course_id); +$savant->display('tests/create_edit_question_truefalse.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); ?> diff --git a/tests/edit_test.php b/tests/edit_test.php index f1c07050..4d38a4b5 100644 --- a/tests/edit_test.php +++ b/tests/edit_test.php @@ -1,52 +1,60 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -$page = 'tests'; -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); - -$tid = intval($_REQUEST['tid']); -$testsDAO = new TestsDAO(); -$row = $testsDAO->get($tid); - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - header('Location: index.php?_course_id='.$_course_id); - exit; -} else if (isset($_POST['submit'])) { - if ($testsDAO->Update($_POST['tid'], $_POST['title'], $_POST['description'])) - { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: index.php?_course_id='.$_course_id); - exit; - } -} - -$onload = 'document.form.title.focus();'; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); -$msg->printErrors(); - -$savant->assign('course_id', $_course_id); -$savant->assign('tid', $tid); -$savant->assign('row', $row); - -$savant->display('tests/create_edit_test.tmpl.php'); - -require (TR_INCLUDE_PATH.'footer.inc.php'); - -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +$page = 'tests'; +define('TR_INCLUDE_PATH', '../include/'); +define('TR_ClassCSRF_PATH', '../protection/csrf/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_ClassCSRF_PATH.'class_csrf.php'); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); + +$tid = intval($_REQUEST['tid']); +$testsDAO = new TestsDAO(); +$row = $testsDAO->get($tid); + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + header('Location: index.php?_course_id='.$_course_id); + exit; +} else if (isset($_POST['submit'])) { + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) + { + if ($testsDAO->Update($_POST['tid'], $_POST['title'], $_POST['description'])) + { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: index.php?_course_id='.$_course_id); + exit; + } + } else + { + $msg->addError('INVALID_TOKEN'); + } +} + +$onload = 'document.form.title.focus();'; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); +$msg->printErrors(); + +$savant->assign('course_id', $_course_id); +$savant->assign('tid', $tid); +$savant->assign('row', $row); + +$savant->display('tests/create_edit_test.tmpl.php'); + +require (TR_INCLUDE_PATH.'footer.inc.php'); + +?> From 734939b16fd45467d494088dc2447c1fa0a01d1e Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sun, 16 Sep 2018 19:25:59 +0700 Subject: [PATCH 40/94] Add files via upload --- themes/default/tests/create_edit_question_likert.tmpl.php | 1 + 1 file changed, 1 insertion(+) diff --git a/themes/default/tests/create_edit_question_likert.tmpl.php b/themes/default/tests/create_edit_question_likert.tmpl.php index 19440aac..edb6b256 100644 --- a/themes/default/tests/create_edit_question_likert.tmpl.php +++ b/themes/default/tests/create_edit_question_likert.tmpl.php @@ -61,6 +61,7 @@ </div> <div class="row buttons"> + <?php echo CSRF_Token::display(); ?><br> <input type="submit" name="preset" value="<?php echo _AT('set_preset'); ?>" class="button" /> </div> </fieldset> From a61050ce4f2da9a1503eef357b2e92c0f9bfb102 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Sun, 16 Sep 2018 20:27:20 +0700 Subject: [PATCH 41/94] Add ' ' for TR_FORMAT_* --- include/lib/output.inc.php | 1074 ++++++++++++++++++------------------ 1 file changed, 537 insertions(+), 537 deletions(-) diff --git a/include/lib/output.inc.php b/include/lib/output.inc.php index 6ecf7e81..8a3bd751 100644 --- a/include/lib/output.inc.php +++ b/include/lib/output.inc.php @@ -1,537 +1,537 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -if (!defined('TR_INCLUDE_PATH')) { exit; } -require_once(TR_INCLUDE_PATH . 'classes/DAO/LanguageTextDAO.class.php'); -require_once(TR_INCLUDE_PATH . '../home/classes/ContentUtility.class.php'); - -/**********************************************************************************/ -/* Output functions found in this file, in order: -/* -/* - AC(term) -/* -/**********************************************************************************/ - -/** -* Converts language code to actual language message, caches them according to page url -* @access public -* @param args unlimited number of arguments allowed but first arg MUST be name of the language variable/term -* i.e $args[0] = the term to the format string $_template[term] -* $args[1..x] = optional arguments to the formatting string -* @return string|array full resulting message -* @see $db in include/vitals.inc.php -* @see cache() in include/phpCache/phpCache.inc.php -* @see cache_variable() in include/phpCache/phpCache.inc.php -* @author Joel Kronenberg -*/ -function _AT() { - global $_cache_template, $lang_et, $_rel_url; - static $_template; - - $args = func_get_args(); - - if ($args[0] == "") return ""; - - $languageTextDAO = new LanguageTextDAO(); - - // a feedback msg - if (!is_array($args[0])) { - /** - * Added functionality for translating language code String (TR_ERROR|TR_INFOS|TR_WARNING|TR_FEEDBACK).* - * to its text and returning the result. No caching needed. - * @author Jacek Materna - */ - - // Check for specific language prefix, extendible as needed - // 0002767: a substring+in_array test should be faster than a preg_match test. - // replaced the preg_match with a test of the substring. - $sub_arg = substr($args[0], 0, 7); // 7 is the shortest type of msg (TR_INFO) - if (in_array($sub_arg, array('TR_ERRO','TR_INFO','TR_WARN','TR_FEED','TR_CONF'))) { - global $_base_path; - - /* get $_msgs_new from the DB */ - $rows = $languageTextDAO->getMsgByTermAndLang($args[0], $_SESSION['lang']); - $msgs = ''; - - if (is_array($rows)) - { - $row = $rows[0]; - // do not cache key as a digit (no contstant(), use string) - $msgs = str_replace('SITE_URL/', $_base_path, $row['text']); - if (defined('TR_DEVEL') && TR_DEVEL) { - $msgs .= ' <small><small>('. $args[0] .')</small></small>'; - } - } - - return $msgs; - } - } - - // a template variable - if (!isset($_template)) { - $url_parts = parse_url(TR_BASE_HREF); - $name = substr($_SERVER['PHP_SELF'], strlen($url_parts['path'])-1); - - if ( !($lang_et = cache(120, 'lang', $_SESSION['lang'].'_'.$name)) ) { - /* get $_template from the DB */ - $rows = $languageTextDAO->getAllTemplateByLang($_SESSION['lang']); - - if (is_array($rows)) - { - foreach ($rows as $id => $row) - { - //Do not overwrite the variable that existed in the cache_template already. - //The edited terms (_c_template) will always be at the top of the resultset - //0003279 - if (isset($_cache_template[$row['term']])){ - continue; - } - - // saves us from doing an ORDER BY - if ($row['language_code'] == $_SESSION['lang']) { - $_cache_template[$row['term']] = stripslashes($row['text']); - } else if (!isset($_cache_template[$row['term']])) { - $_cache_template[$row['term']] = stripslashes($row['text']); - } - } - } - - cache_variable('_cache_template'); - endcache(true, false); - } - $_template = $_cache_template; - } - - $num_args = func_num_args(); - - if (is_array($args[0])) { - $args = $args[0]; - $num_args = count($args); - } - - $format = array_shift($args); - if (isset($_template[$format]) && $num_args > 0) { - $outString = @vsprintf($_template[$format], $args); - $str = ob_get_contents(); - } else { - $outString = ''; - } - - if ($outString === false) { - return ('[Error parsing language. Variable: <code>'.$format.'</code>. Language: <code>'.$_SESSION['lang'].'</code> ]'); - } - - if (empty($outString)) { - - $rows = $languageTextDAO->getByTermAndLang($format, $_SESSION['lang']); - if (is_array($rows)) - { - $row = $rows[0]; - $_template[$row['term']] = stripslashes($row['text']); - $outString = $_template[$row['term']]; - } - - if (empty($outString)) { - return ('[ '.$format.' ]'); - } - } - - return $outString; -} - -/* - The following options were added as language dependant: - %D: A textual representation of a week, three letters Mon through Sun - %F: A full textual representation of a month, such as January or March January through December - %l (lowercase 'L'): A full textual representation of the day of the week Sunday through Saturday - %M: A short textual representation of a month, three letters Jan through Dec - - Support for the following maybe added later: - ?? %S: English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with j - ?? %a: Lowercase Ante meridiem and Post meridiem am or pm - ?? %A: Uppercase Ante meridiem and Post meridiem AM or PM - - valid formTR_types: - TR_DATE_MYSQL_DATETIME: YYYY-MM-DD HH:MM:SS - TR_DATE_MYSQL_TIMESTAMP_14: YYYYMMDDHHMMSS - TR_DATE_UNIX_TIMESTAMP: seconds since epoch - TR_DATE_INDEX_VALUE: 0-x, index into a date array -*/ -function AT_date($format='%Y-%M-%d', $timestamp = '', $format_type=TR_DATE_MYSQL_DATETIME) { - static $day_name_ext, $day_name_con, $month_name_ext, $month_name_con; - global $_config; - - if (!isset($day_name_ext)) { - $day_name_ext = array( 'date_sunday', - 'date_monday', - 'date_tuesday', - 'date_wednesday', - 'date_thursday', - 'date_friday', - 'date_saturday'); - - $day_name_con = array( 'date_sun', - 'date_mon', - 'date_tue', - 'date_wed', - 'date_thu', - 'date_fri', - 'date_sat'); - - $month_name_ext = array('date_january', - 'date_february', - 'date_march', - 'date_april', - 'date_may', - 'date_june', - 'date_july', - 'date_august', - 'date_september', - 'date_october', - 'date_november', - 'date_december'); - - $month_name_con = array('date_jan', - 'date_feb', - 'date_mar', - 'date_apr', - 'date_may_short', - 'date_jun', - 'date_jul', - 'date_aug', - 'date_sep', - 'date_oct', - 'date_nov', - 'date_dec'); - } - - if ($format_type == TR_DATE_INDEX_VALUE) { - // apply timezone offset - apply_timezone($timestamp); - - if ($format == '%D') { - return _AT($day_name_con[$timestamp-1]); - } else if ($format == '%l') { - return _AT($day_name_ext[$timestamp-1]); - } else if ($format == '%F') { - return _AT($month_name_ext[$timestamp-1]); - } else if ($format == '%M') { - return _AT($month_name_con[$timestamp-1]); - } - } - - if ($timestamp == '') { - $timestamp = time(); - $format_type = TR_DATE_UNIX_TIMESTAMP; - } - - /* convert the date to a Unix timestamp before we do anything with it */ - if ($format_type == TR_DATE_MYSQL_DATETIME) { - $year = substr($timestamp,0,4); - $month = substr($timestamp,5,2); - $day = substr($timestamp,8,2); - $hour = substr($timestamp,11,2); - $min = substr($timestamp,14,2); - $sec = substr($timestamp,17,2); - $timestamp = mktime($hour, $min, $sec, $month, $day, $year); - - } else if ($format_type == TR_DATE_MYSQL_TIMESTAMP_14) { - $year = substr($timestamp,0,4); - $month = substr($timestamp,4,2); - $day = substr($timestamp,6,2); - $hour = substr($timestamp,8,2); - $minute = substr($timestamp,10,2); - $second = substr($timestamp,12,2); - $timestamp = mktime($hour, $minute, $second, $month, $day, $year); - } - - // apply timezone offset - apply_timezone($timestamp); - - /* pull out all the %X items from $format */ - $first_token = strpos($format, '%'); - if ($first_token === false) { - /* no tokens found */ - return $timestamp; - } else { - $tokened_format = substr($format, $first_token); - } - $tokens = explode('%', $tokened_format); - array_shift($tokens); - $num_tokens = count($tokens); - - $output = $format; - - for ($i=0; $i<$num_tokens; $i++) { - $tokens[$i] = substr($tokens[$i],0,1); - - if ($tokens[$i] == 'D') { - $output = str_replace('%D', _AT($day_name_con[date('w', $timestamp)]),$output); - - } else if ($tokens[$i] == 'l') { - $output = str_replace('%l', _AT($day_name_ext[date('w', $timestamp)]),$output); - - } else if ($tokens[$i] == 'F') { - $output = str_replace('%F', _AT($month_name_ext[date('n', $timestamp)-1]),$output); - - } else if ($tokens[$i] == 'M') { - $output = str_replace('%M', _AT($month_name_con[date('n', $timestamp)-1]),$output); - - } else { - /* this token doesn't need translating */ - $value = date($tokens[$i], $timestamp); - if ($value != $tokens[$i]) { - $output = str_replace('%'.$tokens[$i], $value, $output); - } /* else: this token isn't valid. so don't replace it. Eg. try %q */ - } - } - - return $output; -} - -/**********************************************************************************************************/ - /** - * Transforms text based on formatting preferences. Original $input is also changed (passed by reference). - * Can be called as: - * 1) $output = AT_print($input, $name); - * echo $output; - * - * 2) echo AT_print($input, $name); // prefered method - * - * @access public - * @param string $input text being transformed - * @param string $name the unique name of this field (convension: table_name.field_name) - * @param boolean $runtime_html forcefully disables html formatting for $input (only used by fields that - * have the 'formatting' option - * @return string transformed $input - * @see TR_FORMAT constants in include/lib/constants.inc.php - * @see query_bit() in include/vitals.inc.php - * @author Joel Kronenberg - */ - function AT_print($input, $name, $runtime_html = true) { - global $_field_formatting; - - if (!isset($_field_formatting[$name])) { - /* field not set, check if there's a global setting */ - $parts = explode('.', $name); - - /* check if wildcard is set: */ - if (isset($_field_formatting[$parts[0].'.*'])) { - $name = $parts[0].'.*'; - } else { - /* field not set, and there's no global setting */ - /* same as TR_FORMAT_NONE */ - return $input; - } - } - - if (query_bit($_field_formatting[$name], TR_FORMAT_QUOTES)) { - $input = str_replace('"', '"', $input); - } - - if (query_bit($_field_formatting[$name], TR_FORMAT_CONTENT_DIR)) { - $input = str_replace('CONTENT_DIR/', '', $input); - } - - if (query_bit($_field_formatting[$name], TR_FORMAT_HTML) && $runtime_html) { - /* what special things do we have to do if this is HTML ? remove unwanted HTML? validate? */ - } else { - $input = str_replace('<', '<', $input); - $input = nl2br($input); - } - - /* this has to be here, only because TR_FORMTR_HTML is the only check that has an else-block */ - if ($_field_formatting[$name] === TR_FORMAT_NONE) { - return $input; - } - - if (query_bit($_field_formatting[$name], TR_FORMAT_EMOTICONS)) { - $input = smile_replace($input); - } - - if (query_bit($_field_formatting[$name], TR_FORMAT_ATCODES)) { - $input = trim(ContentUtility::myCodes(' ' . $input . ' ')); - } - - if (query_bit($_field_formatting[$name], TR_FORMAT_LINKS)) { - $input = trim(ContentUtility::makeClickable(' ' . $input . ' ')); - } - - if (query_bit($_field_formatting[$name], TR_FORMAT_IMAGES)) { - $input = trim(ContentUtility::imageReplace(' ' . $input . ' ')); - } - if (query_bit($_field_formatting[$name], TR_FORMAT_DECODE)) { - $input = htmlspecialchars_decode($input, ENT_QUOTES); - } - - return $input; - } - -/********************************************************************************************/ -// Global variables for emoticons - -global $smile_pics; -global $smile_codes; -if (!isset($smile_pics)) { - $smile_pics[0] = $_base_path.'images/forum/smile.gif'; - $smile_pics[1] = $_base_path.'images/forum/wink.gif'; - $smile_pics[2] = $_base_path.'images/forum/frown.gif'; - $smile_pics[3] = $_base_path.'images/forum/ohwell.gif'; - $smile_pics[4] = $_base_path.'images/forum/tongue.gif'; - $smile_pics[5] = $_base_path.'images/forum/51.gif'; - $smile_pics[6] = $_base_path.'images/forum/52.gif'; - $smile_pics[7] = $_base_path.'images/forum/54.gif'; - $smile_pics[8] = $_base_path.'images/forum/27.gif'; - $smile_pics[9] = $_base_path.'images/forum/19.gif'; - $smile_pics[10] = $_base_path.'images/forum/3.gif'; - $smile_pics[11] = $_base_path.'images/forum/56.gif'; -} - -if (!isset($smile_codes)) { - $smile_codes[0] = ':)'; - $smile_codes[1] = ';)'; - $smile_codes[2] = ':('; - $smile_codes[3] = '::ohwell::'; - $smile_codes[4] = ':P'; - $smile_codes[5] = '::evil::'; - $smile_codes[6] = '::angry::'; - $smile_codes[7] = '::lol::'; - $smile_codes[8] = '::crazy::'; - $smile_codes[9] = '::tired::'; - $smile_codes[10] = '::confused::'; - $smile_codes[11] = '::muah::'; -} - -/** -* Replaces smile-code text into smilie image. -* @access public -* @param string $text smile text to be transformed -* @return string transformed $text -* @see $smile_pics in include/lib/output.inc.php (above) -* @see $smile_codes in include/lib/output.inc.php (above) -* @author Joel Kronenberg -*/ -function smile_replace($text) { - global $smile_pics; - global $smile_codes; - static $smiles; - - $smiles[0] = '<img src="'.$smile_pics[0].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_smile').'" />'; - $smiles[1] = '<img src="'.$smile_pics[1].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_wink').'" />'; - $smiles[2] = '<img src="'.$smile_pics[2].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_frown').'" />'; - $smiles[3]= '<img src="'.$smile_pics[3].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_oh_well').'" />'; - $smiles[4]= '<img src="'.$smile_pics[4].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_tongue').'" />'; - $smiles[5]= '<img src="'.$smile_pics[5].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_evil').'" />'; - $smiles[6]= '<img src="'.$smile_pics[6].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_angry').'" />'; - $smiles[7]= '<img src="'.$smile_pics[7].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_lol').'" />'; - $smiles[8]= '<img src="'.$smile_pics[8].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_crazy').'" />'; - $smiles[9]= '<img src="'.$smile_pics[9].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_tired').'" />'; - $smiles[10]= '<img src="'.$smile_pics[10].'" border="0" height="17" width="19" align="bottom" alt="'._AT('smile_confused').'" />'; - $smiles[11]= '<img src="'.$smile_pics[11].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_muah').'" />'; - - $text = str_replace($smile_codes[0],$smiles[0],$text); - $text = str_replace($smile_codes[1],$smiles[1],$text); - $text = str_replace($smile_codes[2],$smiles[2],$text); - $text = str_replace($smile_codes[3],$smiles[3],$text); - $text = str_replace($smile_codes[4],$smiles[4],$text); - $text = str_replace($smile_codes[5],$smiles[5],$text); - $text = str_replace($smile_codes[6],$smiles[6],$text); - $text = str_replace($smile_codes[7],$smiles[7],$text); - $text = str_replace($smile_codes[8],$smiles[8],$text); - $text = str_replace($smile_codes[9],$smiles[9],$text); - $text = str_replace($smile_codes[10],$smiles[10],$text); - $text = str_replace($smile_codes[11],$smiles[11],$text); - - return $text; -} - -function html_get_list($array) { - $list = ''; - foreach ($array as $value) { - $list .= '<li>'.$value.'</li>'; - } - return $list; -} - -/** - * print_paginator - * - * print out list of page links - */ -function print_paginator($current_page, $num_rows, $request_args, $rows_per_page = 50, $window = 5, $skippager='0') { - $num_pages = ceil($num_rows / $rows_per_page); - $request_args = '?'.$request_args; - - if ($num_pages == 1) return; - if ($num_rows) { - echo '<div><a href="'.$_SERVER['PHP_SELF'].'#skippager'.$skippager.'" class="hide_focus">'._AT('skip_pager').'</a></div>'; - echo '<div class="paging">'; - echo '<ul>'; - - $i=max($current_page-$window - max($window-$num_pages+$current_page,0), 1); - - if ($current_page > 1) - echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.($current_page-1).'">'._AT('prev').'</a>   </li>'; - - if ($i > 1) { - echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p=1">1</a></li>'; - if ($i > 2) { - echo '<li>…</li>'; - } - } - - for ($i; $i<= min($current_page+$window -min($current_page-$window,0),$num_pages); $i++) { - if ($current_page == $i) { - echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$i.'" class="current"><em>'.$current_page.'</em></a></li>'; - } else { - echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$i.'">'.$i.'</a></li>'; - } - } - if ($i <= $num_pages) { - if ($i < $num_pages) { - echo '<li>…</li>'; - } - echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$num_pages.'">'.$num_pages.'</a></li>'; - } - - if ($current_page < $num_pages) - echo '<li>   <a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.($current_page+1).'">'._AT('next').'</a></li>'; - - echo '</ul>'; - echo '</div><a name="skippager'.$skippager.'"></a>'; - } -} - -/** -* apply_timezone -* converts a unix timestamp into another UNIX timestamp with timezone offset added up. -* Adds the user's timezone offset, then converts back to a MYSQL timestamp -* Available both as a system config option, and a user preference, if both are set -* they are added together -* @param date MYSQL timestamp. -* @return date MYSQL timestamp plus user's and/or system's timezone offset. -* @author Greg Gay . -*/ -function apply_timezone($timestamp){ - global $_config; - - if($_config['time_zone']){ - $timestamp = ($timestamp + ($_config['time_zone']*3600)); - } - - if(isset($_SESSION['prefs']['PREF_TIMEZONE'])){ - $timestamp = ($timestamp + ($_SESSION['prefs']['PREF_TIMEZONE']*3600)); - } - - return $timestamp; -} -?> +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +if (!defined('TR_INCLUDE_PATH')) { exit; } +require_once(TR_INCLUDE_PATH . 'classes/DAO/LanguageTextDAO.class.php'); +require_once(TR_INCLUDE_PATH . '../home/classes/ContentUtility.class.php'); + +/**********************************************************************************/ +/* Output functions found in this file, in order: +/* +/* - AC(term) +/* +/**********************************************************************************/ + +/** +* Converts language code to actual language message, caches them according to page url +* @access public +* @param args unlimited number of arguments allowed but first arg MUST be name of the language variable/term +* i.e $args[0] = the term to the format string $_template[term] +* $args[1..x] = optional arguments to the formatting string +* @return string|array full resulting message +* @see $db in include/vitals.inc.php +* @see cache() in include/phpCache/phpCache.inc.php +* @see cache_variable() in include/phpCache/phpCache.inc.php +* @author Joel Kronenberg +*/ +function _AT() { + global $_cache_template, $lang_et, $_rel_url; + static $_template; + + $args = func_get_args(); + + if ($args[0] == "") return ""; + + $languageTextDAO = new LanguageTextDAO(); + + // a feedback msg + if (!is_array($args[0])) { + /** + * Added functionality for translating language code String (TR_ERROR|TR_INFOS|TR_WARNING|TR_FEEDBACK).* + * to its text and returning the result. No caching needed. + * @author Jacek Materna + */ + + // Check for specific language prefix, extendible as needed + // 0002767: a substring+in_array test should be faster than a preg_match test. + // replaced the preg_match with a test of the substring. + $sub_arg = substr($args[0], 0, 7); // 7 is the shortest type of msg (TR_INFO) + if (in_array($sub_arg, array('TR_ERRO','TR_INFO','TR_WARN','TR_FEED','TR_CONF'))) { + global $_base_path; + + /* get $_msgs_new from the DB */ + $rows = $languageTextDAO->getMsgByTermAndLang($args[0], $_SESSION['lang']); + $msgs = ''; + + if (is_array($rows)) + { + $row = $rows[0]; + // do not cache key as a digit (no contstant(), use string) + $msgs = str_replace('SITE_URL/', $_base_path, $row['text']); + if (defined('TR_DEVEL') && TR_DEVEL) { + $msgs .= ' <small><small>('. $args[0] .')</small></small>'; + } + } + + return $msgs; + } + } + + // a template variable + if (!isset($_template)) { + $url_parts = parse_url(TR_BASE_HREF); + $name = substr($_SERVER['PHP_SELF'], strlen($url_parts['path'])-1); + + if ( !($lang_et = cache(120, 'lang', $_SESSION['lang'].'_'.$name)) ) { + /* get $_template from the DB */ + $rows = $languageTextDAO->getAllTemplateByLang($_SESSION['lang']); + + if (is_array($rows)) + { + foreach ($rows as $id => $row) + { + //Do not overwrite the variable that existed in the cache_template already. + //The edited terms (_c_template) will always be at the top of the resultset + //0003279 + if (isset($_cache_template[$row['term']])){ + continue; + } + + // saves us from doing an ORDER BY + if ($row['language_code'] == $_SESSION['lang']) { + $_cache_template[$row['term']] = stripslashes($row['text']); + } else if (!isset($_cache_template[$row['term']])) { + $_cache_template[$row['term']] = stripslashes($row['text']); + } + } + } + + cache_variable('_cache_template'); + endcache(true, false); + } + $_template = $_cache_template; + } + + $num_args = func_num_args(); + + if (is_array($args[0])) { + $args = $args[0]; + $num_args = count($args); + } + + $format = array_shift($args); + if (isset($_template[$format]) && $num_args > 0) { + $outString = @vsprintf($_template[$format], $args); + $str = ob_get_contents(); + } else { + $outString = ''; + } + + if ($outString === false) { + return ('[Error parsing language. Variable: <code>'.$format.'</code>. Language: <code>'.$_SESSION['lang'].'</code> ]'); + } + + if (empty($outString)) { + + $rows = $languageTextDAO->getByTermAndLang($format, $_SESSION['lang']); + if (is_array($rows)) + { + $row = $rows[0]; + $_template[$row['term']] = stripslashes($row['text']); + $outString = $_template[$row['term']]; + } + + if (empty($outString)) { + return ('[ '.$format.' ]'); + } + } + + return $outString; +} + +/* + The following options were added as language dependant: + %D: A textual representation of a week, three letters Mon through Sun + %F: A full textual representation of a month, such as January or March January through December + %l (lowercase 'L'): A full textual representation of the day of the week Sunday through Saturday + %M: A short textual representation of a month, three letters Jan through Dec + + Support for the following maybe added later: + ?? %S: English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with j + ?? %a: Lowercase Ante meridiem and Post meridiem am or pm + ?? %A: Uppercase Ante meridiem and Post meridiem AM or PM + + valid formTR_types: + TR_DATE_MYSQL_DATETIME: YYYY-MM-DD HH:MM:SS + TR_DATE_MYSQL_TIMESTAMP_14: YYYYMMDDHHMMSS + TR_DATE_UNIX_TIMESTAMP: seconds since epoch + TR_DATE_INDEX_VALUE: 0-x, index into a date array +*/ +function AT_date($format='%Y-%M-%d', $timestamp = '', $format_type=TR_DATE_MYSQL_DATETIME) { + static $day_name_ext, $day_name_con, $month_name_ext, $month_name_con; + global $_config; + + if (!isset($day_name_ext)) { + $day_name_ext = array( 'date_sunday', + 'date_monday', + 'date_tuesday', + 'date_wednesday', + 'date_thursday', + 'date_friday', + 'date_saturday'); + + $day_name_con = array( 'date_sun', + 'date_mon', + 'date_tue', + 'date_wed', + 'date_thu', + 'date_fri', + 'date_sat'); + + $month_name_ext = array('date_january', + 'date_february', + 'date_march', + 'date_april', + 'date_may', + 'date_june', + 'date_july', + 'date_august', + 'date_september', + 'date_october', + 'date_november', + 'date_december'); + + $month_name_con = array('date_jan', + 'date_feb', + 'date_mar', + 'date_apr', + 'date_may_short', + 'date_jun', + 'date_jul', + 'date_aug', + 'date_sep', + 'date_oct', + 'date_nov', + 'date_dec'); + } + + if ($format_type == TR_DATE_INDEX_VALUE) { + // apply timezone offset + apply_timezone($timestamp); + + if ($format == '%D') { + return _AT($day_name_con[$timestamp-1]); + } else if ($format == '%l') { + return _AT($day_name_ext[$timestamp-1]); + } else if ($format == '%F') { + return _AT($month_name_ext[$timestamp-1]); + } else if ($format == '%M') { + return _AT($month_name_con[$timestamp-1]); + } + } + + if ($timestamp == '') { + $timestamp = time(); + $format_type = TR_DATE_UNIX_TIMESTAMP; + } + + /* convert the date to a Unix timestamp before we do anything with it */ + if ($format_type == TR_DATE_MYSQL_DATETIME) { + $year = substr($timestamp,0,4); + $month = substr($timestamp,5,2); + $day = substr($timestamp,8,2); + $hour = substr($timestamp,11,2); + $min = substr($timestamp,14,2); + $sec = substr($timestamp,17,2); + $timestamp = mktime($hour, $min, $sec, $month, $day, $year); + + } else if ($format_type == TR_DATE_MYSQL_TIMESTAMP_14) { + $year = substr($timestamp,0,4); + $month = substr($timestamp,4,2); + $day = substr($timestamp,6,2); + $hour = substr($timestamp,8,2); + $minute = substr($timestamp,10,2); + $second = substr($timestamp,12,2); + $timestamp = mktime($hour, $minute, $second, $month, $day, $year); + } + + // apply timezone offset + apply_timezone($timestamp); + + /* pull out all the %X items from $format */ + $first_token = strpos($format, '%'); + if ($first_token === false) { + /* no tokens found */ + return $timestamp; + } else { + $tokened_format = substr($format, $first_token); + } + $tokens = explode('%', $tokened_format); + array_shift($tokens); + $num_tokens = count($tokens); + + $output = $format; + + for ($i=0; $i<$num_tokens; $i++) { + $tokens[$i] = substr($tokens[$i],0,1); + + if ($tokens[$i] == 'D') { + $output = str_replace('%D', _AT($day_name_con[date('w', $timestamp)]),$output); + + } else if ($tokens[$i] == 'l') { + $output = str_replace('%l', _AT($day_name_ext[date('w', $timestamp)]),$output); + + } else if ($tokens[$i] == 'F') { + $output = str_replace('%F', _AT($month_name_ext[date('n', $timestamp)-1]),$output); + + } else if ($tokens[$i] == 'M') { + $output = str_replace('%M', _AT($month_name_con[date('n', $timestamp)-1]),$output); + + } else { + /* this token doesn't need translating */ + $value = date($tokens[$i], $timestamp); + if ($value != $tokens[$i]) { + $output = str_replace('%'.$tokens[$i], $value, $output); + } /* else: this token isn't valid. so don't replace it. Eg. try %q */ + } + } + + return $output; +} + +/**********************************************************************************************************/ + /** + * Transforms text based on formatting preferences. Original $input is also changed (passed by reference). + * Can be called as: + * 1) $output = AT_print($input, $name); + * echo $output; + * + * 2) echo AT_print($input, $name); // prefered method + * + * @access public + * @param string $input text being transformed + * @param string $name the unique name of this field (convension: table_name.field_name) + * @param boolean $runtime_html forcefully disables html formatting for $input (only used by fields that + * have the 'formatting' option + * @return string transformed $input + * @see TR_FORMAT constants in include/lib/constants.inc.php + * @see query_bit() in include/vitals.inc.php + * @author Joel Kronenberg + */ + function AT_print($input, $name, $runtime_html = true) { + global $_field_formatting; + + if (!isset($_field_formatting[$name])) { + /* field not set, check if there's a global setting */ + $parts = explode('.', $name); + + /* check if wildcard is set: */ + if (isset($_field_formatting[$parts[0].'.*'])) { + $name = $parts[0].'.*'; + } else { + /* field not set, and there's no global setting */ + /* same as TR_FORMAT_NONE */ + return $input; + } + } + + if (query_bit($_field_formatting[$name], 'TR_FORMAT_QUOTES')) { + $input = str_replace('"', '"', $input); + } + + if (query_bit($_field_formatting[$name], 'TR_FORMAT_CONTENT_DIR')) { + $input = str_replace('CONTENT_DIR/', '', $input); + } + + if (query_bit($_field_formatting[$name], 'TR_FORMAT_HTML') && $runtime_html) { + /* what special things do we have to do if this is HTML ? remove unwanted HTML? validate? */ + } else { + $input = str_replace('<', '<', $input); + $input = nl2br($input); + } + + /* this has to be here, only because TR_FORMTR_HTML is the only check that has an else-block */ + if ($_field_formatting[$name] === 'TR_FORMAT_NONE') { + return $input; + } + + if (query_bit($_field_formatting[$name], 'TR_FORMAT_EMOTICONS')) { + $input = smile_replace($input); + } + + if (query_bit($_field_formatting[$name], 'TR_FORMAT_ATCODES')) { + $input = trim(ContentUtility::myCodes(' ' . $input . ' ')); + } + + if (query_bit($_field_formatting[$name], 'TR_FORMAT_LINKS')) { + $input = trim(ContentUtility::makeClickable(' ' . $input . ' ')); + } + + if (query_bit($_field_formatting[$name], 'TR_FORMAT_IMAGES')) { + $input = trim(ContentUtility::imageReplace(' ' . $input . ' ')); + } + if (query_bit($_field_formatting[$name], 'TR_FORMAT_DECODE')) { + $input = htmlspecialchars_decode($input, ENT_QUOTES); + } + + return $input; + } + +/********************************************************************************************/ +// Global variables for emoticons + +global $smile_pics; +global $smile_codes; +if (!isset($smile_pics)) { + $smile_pics[0] = $_base_path.'images/forum/smile.gif'; + $smile_pics[1] = $_base_path.'images/forum/wink.gif'; + $smile_pics[2] = $_base_path.'images/forum/frown.gif'; + $smile_pics[3] = $_base_path.'images/forum/ohwell.gif'; + $smile_pics[4] = $_base_path.'images/forum/tongue.gif'; + $smile_pics[5] = $_base_path.'images/forum/51.gif'; + $smile_pics[6] = $_base_path.'images/forum/52.gif'; + $smile_pics[7] = $_base_path.'images/forum/54.gif'; + $smile_pics[8] = $_base_path.'images/forum/27.gif'; + $smile_pics[9] = $_base_path.'images/forum/19.gif'; + $smile_pics[10] = $_base_path.'images/forum/3.gif'; + $smile_pics[11] = $_base_path.'images/forum/56.gif'; +} + +if (!isset($smile_codes)) { + $smile_codes[0] = ':)'; + $smile_codes[1] = ';)'; + $smile_codes[2] = ':('; + $smile_codes[3] = '::ohwell::'; + $smile_codes[4] = ':P'; + $smile_codes[5] = '::evil::'; + $smile_codes[6] = '::angry::'; + $smile_codes[7] = '::lol::'; + $smile_codes[8] = '::crazy::'; + $smile_codes[9] = '::tired::'; + $smile_codes[10] = '::confused::'; + $smile_codes[11] = '::muah::'; +} + +/** +* Replaces smile-code text into smilie image. +* @access public +* @param string $text smile text to be transformed +* @return string transformed $text +* @see $smile_pics in include/lib/output.inc.php (above) +* @see $smile_codes in include/lib/output.inc.php (above) +* @author Joel Kronenberg +*/ +function smile_replace($text) { + global $smile_pics; + global $smile_codes; + static $smiles; + + $smiles[0] = '<img src="'.$smile_pics[0].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_smile').'" />'; + $smiles[1] = '<img src="'.$smile_pics[1].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_wink').'" />'; + $smiles[2] = '<img src="'.$smile_pics[2].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_frown').'" />'; + $smiles[3]= '<img src="'.$smile_pics[3].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_oh_well').'" />'; + $smiles[4]= '<img src="'.$smile_pics[4].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_tongue').'" />'; + $smiles[5]= '<img src="'.$smile_pics[5].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_evil').'" />'; + $smiles[6]= '<img src="'.$smile_pics[6].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_angry').'" />'; + $smiles[7]= '<img src="'.$smile_pics[7].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_lol').'" />'; + $smiles[8]= '<img src="'.$smile_pics[8].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_crazy').'" />'; + $smiles[9]= '<img src="'.$smile_pics[9].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_tired').'" />'; + $smiles[10]= '<img src="'.$smile_pics[10].'" border="0" height="17" width="19" align="bottom" alt="'._AT('smile_confused').'" />'; + $smiles[11]= '<img src="'.$smile_pics[11].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_muah').'" />'; + + $text = str_replace($smile_codes[0],$smiles[0],$text); + $text = str_replace($smile_codes[1],$smiles[1],$text); + $text = str_replace($smile_codes[2],$smiles[2],$text); + $text = str_replace($smile_codes[3],$smiles[3],$text); + $text = str_replace($smile_codes[4],$smiles[4],$text); + $text = str_replace($smile_codes[5],$smiles[5],$text); + $text = str_replace($smile_codes[6],$smiles[6],$text); + $text = str_replace($smile_codes[7],$smiles[7],$text); + $text = str_replace($smile_codes[8],$smiles[8],$text); + $text = str_replace($smile_codes[9],$smiles[9],$text); + $text = str_replace($smile_codes[10],$smiles[10],$text); + $text = str_replace($smile_codes[11],$smiles[11],$text); + + return $text; +} + +function html_get_list($array) { + $list = ''; + foreach ($array as $value) { + $list .= '<li>'.$value.'</li>'; + } + return $list; +} + +/** + * print_paginator + * + * print out list of page links + */ +function print_paginator($current_page, $num_rows, $request_args, $rows_per_page = 50, $window = 5, $skippager='0') { + $num_pages = ceil($num_rows / $rows_per_page); + $request_args = '?'.$request_args; + + if ($num_pages == 1) return; + if ($num_rows) { + echo '<div><a href="'.$_SERVER['PHP_SELF'].'#skippager'.$skippager.'" class="hide_focus">'._AT('skip_pager').'</a></div>'; + echo '<div class="paging">'; + echo '<ul>'; + + $i=max($current_page-$window - max($window-$num_pages+$current_page,0), 1); + + if ($current_page > 1) + echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.($current_page-1).'">'._AT('prev').'</a>   </li>'; + + if ($i > 1) { + echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p=1">1</a></li>'; + if ($i > 2) { + echo '<li>…</li>'; + } + } + + for ($i; $i<= min($current_page+$window -min($current_page-$window,0),$num_pages); $i++) { + if ($current_page == $i) { + echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$i.'" class="current"><em>'.$current_page.'</em></a></li>'; + } else { + echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$i.'">'.$i.'</a></li>'; + } + } + if ($i <= $num_pages) { + if ($i < $num_pages) { + echo '<li>…</li>'; + } + echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$num_pages.'">'.$num_pages.'</a></li>'; + } + + if ($current_page < $num_pages) + echo '<li>   <a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.($current_page+1).'">'._AT('next').'</a></li>'; + + echo '</ul>'; + echo '</div><a name="skippager'.$skippager.'"></a>'; + } +} + +/** +* apply_timezone +* converts a unix timestamp into another UNIX timestamp with timezone offset added up. +* Adds the user's timezone offset, then converts back to a MYSQL timestamp +* Available both as a system config option, and a user preference, if both are set +* they are added together +* @param date MYSQL timestamp. +* @return date MYSQL timestamp plus user's and/or system's timezone offset. +* @author Greg Gay . +*/ +function apply_timezone($timestamp){ + global $_config; + + if($_config['time_zone']){ + $timestamp = ($timestamp + ($_config['time_zone']*3600)); + } + + if(isset($_SESSION['prefs']['PREF_TIMEZONE'])){ + $timestamp = ($timestamp + ($_SESSION['prefs']['PREF_TIMEZONE']*3600)); + } + + return $timestamp; +} +?> From 9ffec362bc81ad7b827011aea165210ce401edea Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 06:58:16 +0700 Subject: [PATCH 42/94] Fix HTMLPurifier Path from ../ to ../../ --- include/sidemenus/my_courses.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sidemenus/my_courses.inc.php b/include/sidemenus/my_courses.inc.php index 80799bef..b39e3017 100644 --- a/include/sidemenus/my_courses.inc.php +++ b/include/sidemenus/my_courses.inc.php @@ -11,7 +11,7 @@ /************************************************************************/ if (!defined('TR_INCLUDE_PATH')) { exit; } -define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/UserCoursesDAO.class.php'); require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); From 1d00788e0ae6e1ccc4586200c137fcc7af9c9226 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 07:05:18 +0700 Subject: [PATCH 43/94] Add HTMLPurifier Path --- tests/index.php | 113 ++++++++++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/tests/index.php b/tests/index.php index 2793a57c..450a8707 100644 --- a/tests/index.php +++ b/tests/index.php @@ -1,56 +1,57 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2013 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -$page = 'tests'; -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsDAO.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); - -if (isset($_GET['edit'], $_GET['id'])) { - header('Location: edit_test.php?tid='.$_GET['id'].'&_course_id='.$_course_id); - exit; -} else if (isset($_GET['preview'], $_GET['id'])) { - header('Location: preview.php?tid='.$_GET['id'].'&_course_id='.$_course_id); - exit; -} else if (isset($_GET['questions'], $_GET['id'])) { - header('Location: questions.php?tid='.$_GET['id'].'&_course_id='.$_course_id); - exit; -} else if (isset($_GET['delete'], $_GET['id'])) { - header('Location: delete_test.php?tid='.$_GET['id'].'&_course_id='.$_course_id); - exit; -} else if (isset($_GET['export'], $_GET['id'])){ - header('Location: export_test.php?tid='.$_GET['id'].'&_course_id='.$_course_id); -} else if (isset($_GET['edit']) - || isset($_GET['preview']) - || isset($_GET['questions']) - || isset($_GET['delete']) - || isset($_GET['export'])) { - - $msg->addError('NO_ITEM_SELECTED'); -} - -$testsDAO = new TestsDAO(); -/* get a list of all the tests we have, and links to create, edit, delete, preview */ -$rows = $testsDAO->getByCourseID($_course_id); - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('course_id', $_course_id); -$savant->assign('rows', $rows); - -$savant->display('tests/index.tmpl.php'); - -require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2013 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +$page = 'tests'; +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsDAO.class.php'); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); + +if (isset($_GET['edit'], $_GET['id'])) { + header('Location: edit_test.php?tid='.$_GET['id'].'&_course_id='.$_course_id); + exit; +} else if (isset($_GET['preview'], $_GET['id'])) { + header('Location: preview.php?tid='.$_GET['id'].'&_course_id='.$_course_id); + exit; +} else if (isset($_GET['questions'], $_GET['id'])) { + header('Location: questions.php?tid='.$_GET['id'].'&_course_id='.$_course_id); + exit; +} else if (isset($_GET['delete'], $_GET['id'])) { + header('Location: delete_test.php?tid='.$_GET['id'].'&_course_id='.$_course_id); + exit; +} else if (isset($_GET['export'], $_GET['id'])){ + header('Location: export_test.php?tid='.$_GET['id'].'&_course_id='.$_course_id); +} else if (isset($_GET['edit']) + || isset($_GET['preview']) + || isset($_GET['questions']) + || isset($_GET['delete']) + || isset($_GET['export'])) { + + $msg->addError('NO_ITEM_SELECTED'); +} + +$testsDAO = new TestsDAO(); +/* get a list of all the tests we have, and links to create, edit, delete, preview */ +$rows = $testsDAO->getByCourseID($_course_id); + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('course_id', $_course_id); +$savant->assign('rows', $rows); + +$savant->display('tests/index.tmpl.php'); + +require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> From 67cf6914e0e6c722c6e5b082022cf3b8a74edb88 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 07:11:21 +0700 Subject: [PATCH 44/94] Add HTMLPurifier Path --- tests/question_db.php | 213 +++++++++++++++++++++--------------------- 1 file changed, 107 insertions(+), 106 deletions(-) diff --git a/tests/question_db.php b/tests/question_db.php index 0cec69da..3b3d8635 100644 --- a/tests/question_db.php +++ b/tests/question_db.php @@ -1,106 +1,107 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/testQuestions.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); - -// converts array entries to ints -function intval_array ( & $value, $key) { $value = (int) $value; } - -if ( (isset($_GET['edit']) || isset($_GET['delete']) || isset($_GET['export']) || isset($_GET['preview']) || isset($_GET['add'])) && !isset($_GET['questions'])){ - $msg->addError('NO_ITEM_SELECTED'); -} else if (isset($_GET['submit_create'], $_GET['question_type'])) { - header('Location: '.TR_BASE_HREF.'tests/create_question_'.addslashes($_GET['question_type']).'.php?_course_id='.$_course_id); - exit; -} else if (isset($_GET['edit'])) { - $id = current($_GET['questions']); - $num_selected = count($id); - - if ($num_selected == 1) { - $ids = explode('|', $id[0], 2); - $o = TestQuestions::getQuestion($ids[1]); - if ($name = $o->getPrefix()) { - header('Location: '.TR_BASE_HREF.'tests/edit_question_'.$name.'.php?qid='.intval($ids[0]).'&_course_id='.$_course_id); - exit; - } else { - header('Location: '.TR_BASE_HREF.'tests/index.php?_course_id='.$_course_id); - exit; - } - } else { - $msg->addError('SELECT_ONE_ITEM'); - } - -} else if (isset($_GET['delete'])) { - $id = current($_GET['questions']); - $ids = array(); - foreach ($_GET['questions'] as $category_questions) { - $ids = array_merge($ids, $category_questions); - } - - array_walk($ids, 'intval_array'); - $ids = implode(',',$ids); - - header('Location: '.TR_BASE_HREF.'tests/delete_question.php?qid='.$ids.'&_course_id='.$_course_id); - exit; -} else if (isset($_GET['preview'])) { - $ids = array(); - foreach ($_GET['questions'] as $category_questions) { - $ids = array_merge($ids, $category_questions); - } - - array_walk($ids, 'intval_array'); - $ids = implode(',',$ids); - - header('Location: '.TR_BASE_HREF.'tests/preview_question.php?qid='.$ids.'&_course_id='.$_course_id); - exit; -} else if (isset($_GET['add'])) { - $id = current($_GET['questions']); - $ids = explode('|', $id[0], 2); -} else if (isset($_GET['export'])) { - $ids = array(); - foreach ($_GET['questions'] as $category_questions) { - $ids = array_merge($ids, $category_questions); - } - - array_walk($ids, 'intval_array'); - - if ($_GET['qti_export_version']=='2.1'){ - test_question_qti_export_v2p1($ids); - } else { - test_question_qti_export($ids); - } - - exit; -} - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->assign('course_id', $_course_id); -$savant->assign('tid', $tid); -$savant->assign('questions', TestQuestions::getQuestionPrefixNames()); - -$savant->display('tests/question_db_top.tmpl.php'); - -$tid = 0; - -require_once(TR_INCLUDE_PATH.'../tests/html/tests_questions.inc.php'); -?> -<br style="clear:both;" /> - - -<?php require_once(TR_INCLUDE_PATH.'footer.inc.php');?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/testQuestions.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); + +global $_course_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); + +// converts array entries to ints +function intval_array ( & $value, $key) { $value = (int) $value; } + +if ( (isset($_GET['edit']) || isset($_GET['delete']) || isset($_GET['export']) || isset($_GET['preview']) || isset($_GET['add'])) && !isset($_GET['questions'])){ + $msg->addError('NO_ITEM_SELECTED'); +} else if (isset($_GET['submit_create'], $_GET['question_type'])) { + header('Location: '.TR_BASE_HREF.'tests/create_question_'.addslashes($_GET['question_type']).'.php?_course_id='.$_course_id); + exit; +} else if (isset($_GET['edit'])) { + $id = current($_GET['questions']); + $num_selected = count($id); + + if ($num_selected == 1) { + $ids = explode('|', $id[0], 2); + $o = TestQuestions::getQuestion($ids[1]); + if ($name = $o->getPrefix()) { + header('Location: '.TR_BASE_HREF.'tests/edit_question_'.$name.'.php?qid='.intval($ids[0]).'&_course_id='.$_course_id); + exit; + } else { + header('Location: '.TR_BASE_HREF.'tests/index.php?_course_id='.$_course_id); + exit; + } + } else { + $msg->addError('SELECT_ONE_ITEM'); + } + +} else if (isset($_GET['delete'])) { + $id = current($_GET['questions']); + $ids = array(); + foreach ($_GET['questions'] as $category_questions) { + $ids = array_merge($ids, $category_questions); + } + + array_walk($ids, 'intval_array'); + $ids = implode(',',$ids); + + header('Location: '.TR_BASE_HREF.'tests/delete_question.php?qid='.$ids.'&_course_id='.$_course_id); + exit; +} else if (isset($_GET['preview'])) { + $ids = array(); + foreach ($_GET['questions'] as $category_questions) { + $ids = array_merge($ids, $category_questions); + } + + array_walk($ids, 'intval_array'); + $ids = implode(',',$ids); + + header('Location: '.TR_BASE_HREF.'tests/preview_question.php?qid='.$ids.'&_course_id='.$_course_id); + exit; +} else if (isset($_GET['add'])) { + $id = current($_GET['questions']); + $ids = explode('|', $id[0], 2); +} else if (isset($_GET['export'])) { + $ids = array(); + foreach ($_GET['questions'] as $category_questions) { + $ids = array_merge($ids, $category_questions); + } + + array_walk($ids, 'intval_array'); + + if ($_GET['qti_export_version']=='2.1'){ + test_question_qti_export_v2p1($ids); + } else { + test_question_qti_export($ids); + } + + exit; +} + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->assign('course_id', $_course_id); +$savant->assign('tid', $tid); +$savant->assign('questions', TestQuestions::getQuestionPrefixNames()); + +$savant->display('tests/question_db_top.tmpl.php'); + +$tid = 0; + +require_once(TR_INCLUDE_PATH.'../tests/html/tests_questions.inc.php'); +?> +<br style="clear:both;" /> + + +<?php require_once(TR_INCLUDE_PATH.'footer.inc.php');?> From a72a1f6e3130eae42947280869d82dfcea4a4322 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 07:14:33 +0700 Subject: [PATCH 45/94] Add HTMLPurifier Path --- tests/preview_question.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/preview_question.php b/tests/preview_question.php index 29dd71e3..abac0c73 100644 --- a/tests/preview_question.php +++ b/tests/preview_question.php @@ -11,6 +11,7 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/testQuestions.class.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); @@ -60,4 +61,4 @@ function iframeSetHeight(id, height) { } //--> </script> -<?php require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> From 47cb110b95a33118b8dcabfb4f2636861dc559e4 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 07:24:12 +0700 Subject: [PATCH 46/94] Add ' ' for TR_FILESIZE_* --- file_manager/top.php | 366 +++++++++++++++++++++---------------------- 1 file changed, 183 insertions(+), 183 deletions(-) diff --git a/file_manager/top.php b/file_manager/top.php index ff1e5859..b2f96e68 100644 --- a/file_manager/top.php +++ b/file_manager/top.php @@ -1,183 +1,183 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -if (!defined('TR_INCLUDE_PATH')) { exit; } -require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php'); - -if (!$_GET['f']) { - $_SESSION['done'] = 0; -} - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$coursesDAO = new CoursesDAO(); - -$current_path = TR_CONTENT_DIR.$_course_id.'/'; - - -if (isset($_POST['rename'])) { - if (!is_array($_POST['check'])) { - // error: you must select a file/dir to rename - $msg->addError('NO_ITEM_SELECTED'); - } else if (count($_POST['check']) < 1) { - // error: you must select one file/dir to rename - $msg->addError('NO_ITEM_SELECTED'); - } else if (count($_POST['check']) > 1) { - // error: you must select ONLY one file/dir to rename - $msg->addError('SELECT_ONE_ITEM'); - } else { - header('Location: rename.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'oldname='.urlencode($_POST['check'][0]).SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - exit; - } -} else if (isset($_POST['delete'])) { - - if (!is_array($_POST['check'])) { - $msg->addError('NO_ITEM_SELECTED'); - } else { - - $list = implode(',', $_POST['check']); - header('Location: delete.php?pathext=' . urlencode($_POST['pathext']) . SEP . 'framed=' . $framed . SEP . 'popup=' . $popup . SEP . 'list=' . urlencode($list).SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - exit; - } -} else if (isset($_POST['move'])) { - - if (!is_array($_POST['check'])) { - $msg->addError('NO_ITEM_SELECTED'); - } else { - - $list = implode(',', $_POST['check']); - header('Location: move.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'list='.urlencode($list).SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - exit; - } -} - -$MakeDirOn = true; - -/* get this courses MaxQuota and MaxFileSize: */ -$row = $coursesDAO->get($_course_id); -$my_MaxCourseSize = $row['max_quota']; -$my_MaxFileSize = $row['max_file_size']; - -if ($my_MaxCourseSize == TR_COURSESIZE_DEFAULT) { - $my_MaxCourseSize = $MaxCourseSize; -} -if ($my_MaxFileSize == TR_FILESIZE_DEFAULT) { - $my_MaxFileSize = $MaxFileSize; -} else if ($my_MaxFileSize == TR_FILESIZE_SYSTEM_MAX) { - $my_MaxFileSize = megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1)); -} - -$MaxSubDirs = 5; -$MaxDirDepth = 10; - -if ($_GET['pathext'] != '') { - $pathext = urldecode($_GET['pathext']); -} else if ($_POST['pathext'] != '') { - $pathext = $_POST['pathext']; -} - -if (strpos($pathext, '..') !== false) { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('UNKNOWN'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} -if($_GET['back'] == 1) { - $pathext = substr($pathext, 0, -1); - $slashpos = strrpos($pathext, '/'); - if($slashpos == 0) { - $pathext = ''; - } else { - $pathext = substr($pathext, 0, ($slashpos+1)); - } - -} - -$start_at = 2; -/* remove the forward or backwards slash from the path */ -$newpath = $current_path; -$depth = substr_count($pathext, '/'); - -if ($pathext != '') { - $bits = explode('/', $pathext); - foreach ($bits as $bit) { - if ($bit != '') { - $bit_path .= $bit; - - $_section[$start_at][0] = $bit; - $_section[$start_at][1] = '../file_manager/index.php?pathext=' . urlencode($bit_path) . SEP . 'popup=' . $popup . SEP . 'framed=' . $framed.SEP.'_course_id='.$_course_id; - - $start_at++; - } - } - $bit_path = ""; - $bit = ""; -} - -/* if upload successful, close the window */ -if ($f) { - $onload = 'closeWindow(\'progWin\');'; -} - -/* make new directory */ -if ($_POST['mkdir_value'] && ($depth < $MaxDirDepth) ) { - $_POST['dirname'] = trim($_POST['dirname']); - - /* anything else should be okay, since we're on *nix..hopefully */ - $_POST['dirname'] = preg_replace('/[^a-zA-Z0-9._]/', '', $_POST['dirname']); - - if ($_POST['dirname'] == '') { - $msg->addError(array('FOLDER_NOT_CREATED', $_POST['dirname'] )); - } - else if (strpos($_POST['dirname'], '..') !== false) { - $msg->addError('BAD_FOLDER_NAME'); - } - else { - $result = @mkdir($current_path.$pathext.$_POST['dirname'], 0700); - if($result == 0) { - $msg->addError(array('FOLDER_NOT_CREATED', $_POST['dirname'] )); - } - else { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - } - } -} - -$newpath = substr($current_path.$pathext, 0, -1); - -/* open the directory */ -if (!($dir = @opendir($newpath))) { - if (isset($_GET['create']) && ($newpath.'/' == $current_path)) { - @mkdir($newpath); - if (!($dir = @opendir($newpath))) { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('CANNOT_CREATE_DIR'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } else { - $msg->addFeedback('CONTENT_DIR_CREATED'); - } - } else { - require(TR_INCLUDE_PATH.'header.inc.php'); - - $msg->printErrors('CANNOT_OPEN_DIR'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); -} - -require(TR_INCLUDE_PATH.'header.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +if (!defined('TR_INCLUDE_PATH')) { exit; } +require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php'); + +if (!$_GET['f']) { + $_SESSION['done'] = 0; +} + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$coursesDAO = new CoursesDAO(); + +$current_path = TR_CONTENT_DIR.$_course_id.'/'; + + +if (isset($_POST['rename'])) { + if (!is_array($_POST['check'])) { + // error: you must select a file/dir to rename + $msg->addError('NO_ITEM_SELECTED'); + } else if (count($_POST['check']) < 1) { + // error: you must select one file/dir to rename + $msg->addError('NO_ITEM_SELECTED'); + } else if (count($_POST['check']) > 1) { + // error: you must select ONLY one file/dir to rename + $msg->addError('SELECT_ONE_ITEM'); + } else { + header('Location: rename.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'oldname='.urlencode($_POST['check'][0]).SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + exit; + } +} else if (isset($_POST['delete'])) { + + if (!is_array($_POST['check'])) { + $msg->addError('NO_ITEM_SELECTED'); + } else { + + $list = implode(',', $_POST['check']); + header('Location: delete.php?pathext=' . urlencode($_POST['pathext']) . SEP . 'framed=' . $framed . SEP . 'popup=' . $popup . SEP . 'list=' . urlencode($list).SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + exit; + } +} else if (isset($_POST['move'])) { + + if (!is_array($_POST['check'])) { + $msg->addError('NO_ITEM_SELECTED'); + } else { + + $list = implode(',', $_POST['check']); + header('Location: move.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'list='.urlencode($list).SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + exit; + } +} + +$MakeDirOn = true; + +/* get this courses MaxQuota and MaxFileSize: */ +$row = $coursesDAO->get($_course_id); +$my_MaxCourseSize = $row['max_quota']; +$my_MaxFileSize = $row['max_file_size']; + +if ($my_MaxCourseSize == 'TR_COURSESIZE_DEFAULT') { + $my_MaxCourseSize = $MaxCourseSize; +} +if ($my_MaxFileSize == 'TR_FILESIZE_DEFAULT') { + $my_MaxFileSize = $MaxFileSize; +} else if ($my_MaxFileSize == 'TR_FILESIZE_SYSTEM_MAX') { + $my_MaxFileSize = megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1)); +} + +$MaxSubDirs = 5; +$MaxDirDepth = 10; + +if ($_GET['pathext'] != '') { + $pathext = urldecode($_GET['pathext']); +} else if ($_POST['pathext'] != '') { + $pathext = $_POST['pathext']; +} + +if (strpos($pathext, '..') !== false) { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('UNKNOWN'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} +if($_GET['back'] == 1) { + $pathext = substr($pathext, 0, -1); + $slashpos = strrpos($pathext, '/'); + if($slashpos == 0) { + $pathext = ''; + } else { + $pathext = substr($pathext, 0, ($slashpos+1)); + } + +} + +$start_at = 2; +/* remove the forward or backwards slash from the path */ +$newpath = $current_path; +$depth = substr_count($pathext, '/'); + +if ($pathext != '') { + $bits = explode('/', $pathext); + foreach ($bits as $bit) { + if ($bit != '') { + $bit_path .= $bit; + + $_section[$start_at][0] = $bit; + $_section[$start_at][1] = '../file_manager/index.php?pathext=' . urlencode($bit_path) . SEP . 'popup=' . $popup . SEP . 'framed=' . $framed.SEP.'_course_id='.$_course_id; + + $start_at++; + } + } + $bit_path = ""; + $bit = ""; +} + +/* if upload successful, close the window */ +if ($f) { + $onload = 'closeWindow(\'progWin\');'; +} + +/* make new directory */ +if ($_POST['mkdir_value'] && ($depth < $MaxDirDepth) ) { + $_POST['dirname'] = trim($_POST['dirname']); + + /* anything else should be okay, since we're on *nix..hopefully */ + $_POST['dirname'] = preg_replace('/[^a-zA-Z0-9._]/', '', $_POST['dirname']); + + if ($_POST['dirname'] == '') { + $msg->addError(array('FOLDER_NOT_CREATED', $_POST['dirname'] )); + } + else if (strpos($_POST['dirname'], '..') !== false) { + $msg->addError('BAD_FOLDER_NAME'); + } + else { + $result = @mkdir($current_path.$pathext.$_POST['dirname'], 0700); + if($result == 0) { + $msg->addError(array('FOLDER_NOT_CREATED', $_POST['dirname'] )); + } + else { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + } + } +} + +$newpath = substr($current_path.$pathext, 0, -1); + +/* open the directory */ +if (!($dir = @opendir($newpath))) { + if (isset($_GET['create']) && ($newpath.'/' == $current_path)) { + @mkdir($newpath); + if (!($dir = @opendir($newpath))) { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('CANNOT_CREATE_DIR'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } else { + $msg->addFeedback('CONTENT_DIR_CREATED'); + } + } else { + require(TR_INCLUDE_PATH.'header.inc.php'); + + $msg->printErrors('CANNOT_OPEN_DIR'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); +} + +require(TR_INCLUDE_PATH.'header.inc.php'); +?> From 9e08e60df77b46328f1c53f898f26e0eb9663fd5 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 07:51:23 +0700 Subject: [PATCH 47/94] Protect against xss --- home/course/content.php | 499 ++++++++++++++++++++-------------------- 1 file changed, 252 insertions(+), 247 deletions(-) diff --git a/home/course/content.php b/home/course/content.php index 2887c628..24b7a406 100644 --- a/home/course/content.php +++ b/home/course/content.php @@ -1,247 +1,252 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2013 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/ContentForumsAssocDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/ContentDAO.class.php'); - -global $_current_user, $_course_id, $_content_id, $contentManager; - -$cid = $_content_id; -$courseid = $_course_id; - - -if ($cid == 0) { - header('Location: '.$_base_href.'index.php'); - exit; -} -if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { - $_SESSION['course_id'] = $_course_id; // used by get.php -} - -/* show the content page */ -if (isset($contentManager)) $content_row = $contentManager->getContentPage($cid); - -if (!$content_row || !isset($contentManager)) { - $_pages['home/course/content.php']['title_var'] = 'missing_content'; - $_pages['home/course/content.php']['parent'] = 'home/index.php'; - $_pages['home/course/content.php']['ignore'] = true; - - - require(TR_INCLUDE_PATH.'header.inc.php'); - - $msg->addError('MISSING_CONTENT'); - $msg->printAll(); - - require (TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} /* else: */ - -if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { - $course_base_href = 'get.php/'; -} else { - $course_base_href = 'content/' . $_course_id . '/'; -} - -/* the "heading navigation": */ -$path = $contentManager->getContentPath($cid); - -if ($content_row['content_path']) { - $content_base_href = $content_row['content_path'].'/'; -} - -$parent_headings = ''; -$num_in_path = count($path); - -/* the page title: */ -$page_title = ''; -$page_title .= $content_row['title']; - -$parent = 0; - -foreach ($path as $i=>$page) { - // When login is a student, remove content folder from breadcrumb path as content folders are - // just toggles for students. Keep content folder in breadcrumb path for instructors as they - // can edit content folder title. - if ((!isset($_current_user) || (!$_current_user->isAuthor($_course_id)|| $_current_user->isAdmin())) && - $contentManager->_menu_info[$page['content_id']]['content_type'] == CONTENT_TYPE_FOLDER) { - unset($path[$i]); - continue; - } - - if ($contentManager->_menu_info[$page['content_id']]['content_type'] == CONTENT_TYPE_FOLDER) - $content_url = 'home/editor/edit_content_folder.php?_cid='.$page['content_id']; - else - $content_url = 'home/course/content.php?_cid='.$page['content_id']; - - if (!$parent) { - $_pages[$content_url]['title'] = $page['content_number'] . $page['title']; - $_pages[$content_url]['parent'] = 'home/index.php'; - } else { - $_pages[$content_url]['title'] = $page['content_number'] . $page['title']; - if (isset($_pages['home/editor/edit_content_folder.php?_cid='.$parent])) { - $_pages[$content_url]['parent'] = 'home/editor/edit_content_folder.php?_cid='.$parent; - } else { - $_pages[$content_url]['parent'] = 'home/course/content.php?_cid='.$parent; - } - } - - $_pages[$content_url]['ignore'] = true; - $parent = $page['content_id']; -} - -$last_page = array_pop($_pages); -$_pages['home/course/content.php'] = $last_page; - -reset($path); -$first_page = current($path); - -/* the tests associated with the content */ -$content_test_ids = array(); //the html -$content_test_rows = $contentManager->getContentTestsAssoc($cid); -if (is_array($content_test_rows)) -{ - foreach ($content_test_rows as $content_test_row){ - $content_test_ids[] = $content_test_row; - } -} - -/* the forums associated with the content */ -$contentForumsAssocDAO = new ContentForumsAssocDAO(); -$content_forum_ids = $contentForumsAssocDAO->getByContent($cid); -//$content_test_rows = $contentManager->getContentTestsAssoc($cid); -//if (is_array($content_test_rows)) -//{ -// foreach ($content_test_rows as $content_test_row){ -// $content_test_ids[] = $content_test_row; -// } -//} - -/*TODO***************BOLOGNA***************REMOVE ME**********/ -/* the content forums extension page*/ -//$content_forum_ids = array(); //the html -//$content_forum_rows = $contentManager->getContentForumsAssoc($cid); -//if (is_array($content_forum_rows)) -//{ -// foreach ($content_forum_rows as $content_forum_row){ -// $content_forum_ids[] = $content_forum_row; -// } -//} - -// use any styles that were part of the imported document -// $_custom_css = $_base_href.'headstuff.php?cid='.$cid.SEP.'path='.urlEncode($_base_href.$course_base_href.$content_base_href); - -if ($content_row['use_customized_head'] && strlen($content_row['head']) > 0) -{ - $_custom_head .= $content_row['head']; -} - -global $_custom_head; -$_custom_head .= ' - <script type="text/javascript"> - //<!-- - jQuery(function() { - jQuery(\'a.tooltip\').tooltip( { showBody: ": ", showURL: false } ); - } ); - //--> - </script> -'; - -if (isset($_SESSION['user_id'])) ContentUtility::saveLastCid($cid); - -if (isset($top_num) && $top_num != (int) $top_num) { - $top_num = substr($top_num, 0, strpos($top_num, '.')); -} - -$_tool_shortcuts = ContentUtility::getToolShortcuts($content_row); - -//if it has test and forum associated with it, still display it even if the content is empty -if ($content_row['text'] == '' && empty($content_test_ids)){ - $msg->addInfo('NO_PAGE_CONTENT'); - $savant->assign('body', ''); -} else { - // find whether the body has alternatives defined - list($has_text_alternative, $has_audio_alternative, $has_visual_alternative, $has_sign_lang_alternative) - = ContentUtility::applyAlternatives($cid, $content_row['text'], true); - - // apply alternatives - if (intval($_GET['alternative']) > 0) { - $content = ContentUtility::applyAlternatives($cid, $content_row['text'], false, intval($_GET['alternative'])); - } else { - - $content = ContentUtility::applyAlternatives($cid, $content_row['text']); - /* if($content == 'null') { - if(isset($_current_user) && $_current_user->isAuthor($course_id)) { - - //$coursesDAO = new CoursesDAO(); - $contentDAO = new ContentDAO(); - $row = $contentDAO->get($cid); - - if($row['structure']!='') - $content = '<script language="javascript" type="text/javascript">$(\'#activate_page_template\').prop(\'checked\', true).trigger("change");</script>'; - - - - } else { - $content = ''; - $msg->addInfo('NO_PAGE_CONTENT'); - } - }*/ - - - - } - - $content = ContentUtility::formatContent($content, $content_row['formatting']); - $content_array = ContentUtility::getContentTable($content, $content_row['formatting']); - - $savant->assign('content_table', $content_array[0]); - $savant->assign('body', htmlspecialchars_decode($content_array[1])); - $savant->assign('has_text_alternative', $has_text_alternative); - $savant->assign('has_audio_alternative', $has_audio_alternative); - $savant->assign('has_visual_alternative', $has_visual_alternative); - $savant->assign('has_sign_lang_alternative', $has_sign_lang_alternative); - $savant->assign('cid', $cid); - - //assign test pages if there are tests associated with this content page - if (!empty($content_test_ids)){ - $savant->assign('test_message', $content_row['test_message']); - $savant->assign('test_ids', $content_test_ids); - } else { - $savant->assign('test_message', ''); - $savant->assign('test_ids', array()); - } - - if (is_array($content_forum_ids)){ - $savant->assign('forum_ids', $content_forum_ids); - } -} - - - -$savant->assign('content_info', _AT('page_info', AT_date(_AT('page_info_date_format'), $content_row['last_modified'], TR_DATE_MYSQL_DATETIME), $content_row['revision'], AT_date(_AT('inbox_date_format'), $content_row['release_date'], TR_DATE_MYSQL_DATETIME))); -$savant->assign('course_id', $_course_id); -if ($_current_user) { - $savant->assign('isAdmin', $_current_user->isAdmin()); -} - -require(TR_INCLUDE_PATH.'header.inc.php'); - -$savant->display('home/course/content.tmpl.php'); - -//save last visit page. -$_SESSION['last_visited_page'] = $server_protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; - -require (TR_INCLUDE_PATH.'footer.inc.php'); -?> +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2013 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../../include/'); +define('TR_HTMLPurifier_PATH', '../../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/ContentForumsAssocDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/ContentDAO.class.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); + +global $_current_user, $_course_id, $_content_id, $contentManager; + +$cid = $_content_id; +$courseid = $_course_id; + + +if ($cid == 0) { + header('Location: '.$_base_href.'index.php'); + exit; +} +if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { + $_SESSION['course_id'] = $_course_id; // used by get.php +} + +/* show the content page */ +if (isset($contentManager)) $content_row = $contentManager->getContentPage($cid); + +if (!$content_row || !isset($contentManager)) { + $_pages['home/course/content.php']['title_var'] = 'missing_content'; + $_pages['home/course/content.php']['parent'] = 'home/index.php'; + $_pages['home/course/content.php']['ignore'] = true; + + + require(TR_INCLUDE_PATH.'header.inc.php'); + + $msg->addError('MISSING_CONTENT'); + $msg->printAll(); + + require (TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} /* else: */ + +if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) { + $course_base_href = 'get.php/'; +} else { + $course_base_href = 'content/' . $_course_id . '/'; +} + +/* the "heading navigation": */ +$path = $contentManager->getContentPath($cid); + +if ($content_row['content_path']) { + $content_base_href = $content_row['content_path'].'/'; +} + +$parent_headings = ''; +$num_in_path = count($path); + +/* the page title: */ +$page_title = ''; +$page_title .= $content_row['title']; + +$parent = 0; + +foreach ($path as $i=>$page) { + // When login is a student, remove content folder from breadcrumb path as content folders are + // just toggles for students. Keep content folder in breadcrumb path for instructors as they + // can edit content folder title. + if ((!isset($_current_user) || (!$_current_user->isAuthor($_course_id)|| $_current_user->isAdmin())) && + $contentManager->_menu_info[$page['content_id']]['content_type'] == CONTENT_TYPE_FOLDER) { + unset($path[$i]); + continue; + } + + if ($contentManager->_menu_info[$page['content_id']]['content_type'] == CONTENT_TYPE_FOLDER) + $content_url = 'home/editor/edit_content_folder.php?_cid='.$page['content_id']; + else + $content_url = 'home/course/content.php?_cid='.$page['content_id']; + + if (!$parent) { + $_pages[$content_url]['title'] = $page['content_number'] . $page['title']; + $_pages[$content_url]['parent'] = 'home/index.php'; + } else { + $_pages[$content_url]['title'] = $page['content_number'] . $page['title']; + if (isset($_pages['home/editor/edit_content_folder.php?_cid='.$parent])) { + $_pages[$content_url]['parent'] = 'home/editor/edit_content_folder.php?_cid='.$parent; + } else { + $_pages[$content_url]['parent'] = 'home/course/content.php?_cid='.$parent; + } + } + + $_pages[$content_url]['ignore'] = true; + $parent = $page['content_id']; +} + +$last_page = array_pop($_pages); +$_pages['home/course/content.php'] = $last_page; + +reset($path); +$first_page = current($path); + +/* the tests associated with the content */ +$content_test_ids = array(); //the html +$content_test_rows = $contentManager->getContentTestsAssoc($cid); +if (is_array($content_test_rows)) +{ + foreach ($content_test_rows as $content_test_row){ + $content_test_ids[] = $content_test_row; + } +} + +/* the forums associated with the content */ +$contentForumsAssocDAO = new ContentForumsAssocDAO(); +$content_forum_ids = $contentForumsAssocDAO->getByContent($cid); +//$content_test_rows = $contentManager->getContentTestsAssoc($cid); +//if (is_array($content_test_rows)) +//{ +// foreach ($content_test_rows as $content_test_row){ +// $content_test_ids[] = $content_test_row; +// } +//} + +/*TODO***************BOLOGNA***************REMOVE ME**********/ +/* the content forums extension page*/ +//$content_forum_ids = array(); //the html +//$content_forum_rows = $contentManager->getContentForumsAssoc($cid); +//if (is_array($content_forum_rows)) +//{ +// foreach ($content_forum_rows as $content_forum_row){ +// $content_forum_ids[] = $content_forum_row; +// } +//} + +// use any styles that were part of the imported document +// $_custom_css = $_base_href.'headstuff.php?cid='.$cid.SEP.'path='.urlEncode($_base_href.$course_base_href.$content_base_href); + +if ($content_row['use_customized_head'] && strlen($content_row['head']) > 0) +{ + $_custom_head .= $content_row['head']; +} + +global $_custom_head; +$_custom_head .= ' + <script type="text/javascript"> + //<!-- + jQuery(function() { + jQuery(\'a.tooltip\').tooltip( { showBody: ": ", showURL: false } ); + } ); + //--> + </script> +'; + +if (isset($_SESSION['user_id'])) ContentUtility::saveLastCid($cid); + +if (isset($top_num) && $top_num != (int) $top_num) { + $top_num = substr($top_num, 0, strpos($top_num, '.')); +} + +$_tool_shortcuts = ContentUtility::getToolShortcuts($content_row); + +//if it has test and forum associated with it, still display it even if the content is empty +if ($content_row['text'] == '' && empty($content_test_ids)){ + $msg->addInfo('NO_PAGE_CONTENT'); + $savant->assign('body', ''); +} else { + // find whether the body has alternatives defined + list($has_text_alternative, $has_audio_alternative, $has_visual_alternative, $has_sign_lang_alternative) + = ContentUtility::applyAlternatives($cid, $content_row['text'], true); + + // apply alternatives + if (intval($_GET['alternative']) > 0) { + $content = ContentUtility::applyAlternatives($cid, $content_row['text'], false, intval($_GET['alternative'])); + } else { + + $content = ContentUtility::applyAlternatives($cid, $content_row['text']); + /* if($content == 'null') { + if(isset($_current_user) && $_current_user->isAuthor($course_id)) { + + //$coursesDAO = new CoursesDAO(); + $contentDAO = new ContentDAO(); + $row = $contentDAO->get($cid); + + if($row['structure']!='') + $content = '<script language="javascript" type="text/javascript">$(\'#activate_page_template\').prop(\'checked\', true).trigger("change");</script>'; + + + + } else { + $content = ''; + $msg->addInfo('NO_PAGE_CONTENT'); + } + }*/ + + + + } + + $content = ContentUtility::formatContent($content, $content_row['formatting']); + $content_array = ContentUtility::getContentTable($content, $content_row['formatting']); + + $savant->assign('content_table', $purifier->purify($content_array[0])); + $savant->assign('body', $purifier->purify(htmlspecialchars_decode($content_array[1]))); + $savant->assign('has_text_alternative', $has_text_alternative); + $savant->assign('has_audio_alternative', $has_audio_alternative); + $savant->assign('has_visual_alternative', $has_visual_alternative); + $savant->assign('has_sign_lang_alternative', $has_sign_lang_alternative); + $savant->assign('cid', $cid); + + //assign test pages if there are tests associated with this content page + if (!empty($content_test_ids)){ + $savant->assign('test_message', $content_row['test_message']); + $savant->assign('test_ids', $content_test_ids); + } else { + $savant->assign('test_message', ''); + $savant->assign('test_ids', array()); + } + + if (is_array($content_forum_ids)){ + $savant->assign('forum_ids', $content_forum_ids); + } +} + + + +$savant->assign('content_info', _AT('page_info', AT_date(_AT('page_info_date_format'), $content_row['last_modified'], TR_DATE_MYSQL_DATETIME), $content_row['revision'], AT_date(_AT('inbox_date_format'), $content_row['release_date'], TR_DATE_MYSQL_DATETIME))); +$savant->assign('course_id', $_course_id); +if ($_current_user) { + $savant->assign('isAdmin', $_current_user->isAdmin()); +} + +require(TR_INCLUDE_PATH.'header.inc.php'); + +$savant->display('home/course/content.tmpl.php'); + +//save last visit page. +$_SESSION['last_visited_page'] = $server_protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + +require (TR_INCLUDE_PATH.'footer.inc.php'); +?> From d219fe462a162b6240a594c1b342631a05307933 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 08:13:08 +0700 Subject: [PATCH 48/94] Protect against XSS --- home/editor/edit_content.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/home/editor/edit_content.php b/home/editor/edit_content.php index d992501e..b2f3b013 100644 --- a/home/editor/edit_content.php +++ b/home/editor/edit_content.php @@ -20,6 +20,10 @@ require_once(TR_INCLUDE_PATH.'lib/tinymce.inc.php'); require_once(TR_INCLUDE_PATH.'classes/FileUtility.class.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php'); +require_once(TR_HTMLPurifier_PATH.'HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); +$purifier = new HTMLPurifier($config); Utility::authenticate(TR_PRIV_ISAUTHOR); @@ -212,17 +216,17 @@ echo '<input type="hidden" name="_course_id" value="'.$_course_id.'" />'; echo '<input type="hidden" name="_cid" value="'.$cid.'" />'; - echo '<input type="hidden" name="title" value="'.htmlspecialchars(stripslashes($_POST['title'])).'" />'; + echo '<input type="hidden" name="title" value="'.$purifier->purify(htmlspecialchars(stripslashes($_POST['title']))).'" />'; if ($_REQUEST['sub'] == 1) { echo '<input type="hidden" name="sub" value="1" />'; - echo '<input type="hidden" name="folder_title" value="'.htmlspecialchars(stripslashes($_POST['folder_title'])).'" />'; + echo '<input type="hidden" name="folder_title" value="'.$purifier->purify(htmlspecialchars(stripslashes($_POST['folder_title']))).'" />'; } echo '<input type="submit" name="submit" style="display:none;"/>'; if (($current_tab != 0) && (($_current_tab != 2))) { - echo '<input type="hidden" name="body_text" value="'.htmlspecialchars(stripslashes($_POST['body_text'])).'" />'; - echo '<input type="hidden" name="weblink_text" value="'.htmlspecialchars(stripslashes($_POST['weblink_text'])).'" />'; - echo '<input type="hidden" name="head" value="'.htmlspecialchars(stripslashes($_POST['head'])).'" />'; + echo '<input type="hidden" name="body_text" value="'.$purifier->purify(htmlspecialchars(stripslashes($_POST['body_text']))).'" />'; + echo '<input type="hidden" name="weblink_text" value="'.$purifier->purify(htmlspecialchars(stripslashes($_POST['weblink_text']))).'" />'; + echo '<input type="hidden" name="head" value="'.$purifier->purify(htmlspecialchars(stripslashes($_POST['head']))).'" />'; echo '<input type="hidden" name="use_customized_head" value="'.(($_POST['use_customized_head']=="") ? 0 : $_POST['use_customized_head']).'" />'; echo '<input type="hidden" name="displayhead" id="displayhead" value="'.AT_print($_POST['displayhead'], 'input.hidden').'" />'; echo '<input type="hidden" name="complexeditor" id="complexeditor" value="'.AT_print($_POST['complexeditor'], 'input.hidden').'" />'; @@ -239,7 +243,7 @@ echo '<input type="hidden" name="current_tab" value="'.$current_tab.'" />'; - echo '<input type="hidden" name="keywords" value="'.htmlspecialchars(stripslashes($_POST['keywords'])).'" />'; + echo '<input type="hidden" name="keywords" value="'.$purifier->purify(htmlspecialchars(stripslashes($_POST['keywords']))).'" />'; //content test association echo '<input type="hidden" name="test_message" value="'.AT_print($_POST['test_message'], 'input.hidden').'" />'; @@ -317,7 +321,7 @@ <?php else: ?> <div class="saved"> - <?php //if ($cid) { echo _AT('save_changes_saved'); } ?> <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" title="<?php echo _AT('save_changes'); ?> alt-s" accesskey="s" class="button"/> <input type="submit" name="close" value="<?php echo _AT('close'); ?>" class="button"/> <input type="checkbox" style="border:0px;" id="close" name="save_n_close" value="1" <?php if ($_SESSION['save_n_close']) { echo 'checked="checked"'; } ?>/><label for="close"><?php echo _AT('close_after_saving'); ?></label> + <?php if ($cid) { echo _AT('save_changes_saved'); } ?> <input type="submit" name="submit" value="<?php echo _AT('save'); ?>" title="<?php echo _AT('save_changes'); ?> alt-s" accesskey="s" class="button"/> <input type="submit" name="close" value="<?php echo _AT('close'); ?>" class="button"/> <input type="checkbox" style="border:0px;" id="close" name="save_n_close" value="1" <?php if ($_SESSION['save_n_close']) { echo 'checked="checked"'; } ?>/><label for="close"><?php echo _AT('close_after_saving'); ?></label> </div> <?php endif; ?> From ed91d90e452b38c9d0a0647f681455346d49b9b3 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 08:46:36 +0700 Subject: [PATCH 49/94] Add HTMLPurifier Path --- tests/question_cats.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/question_cats.php b/tests/question_cats.php index 95f99041..464c5f31 100644 --- a/tests/question_cats.php +++ b/tests/question_cats.php @@ -12,6 +12,7 @@ $page = 'tests'; define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsCategoriesDAO.class.php'); require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); @@ -42,4 +43,4 @@ $savant->display('tests/question_cats.tmpl.php'); -require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> From 18a1b589669ac8e56ef027a307d4819bb9b759f2 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 08:54:36 +0700 Subject: [PATCH 50/94] Change Token to CSRF_Token --- tests/question_cats_manage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/question_cats_manage.php b/tests/question_cats_manage.php index d30f4e0c..861b215c 100644 --- a/tests/question_cats_manage.php +++ b/tests/question_cats_manage.php @@ -34,7 +34,7 @@ header('Location: question_cats.php'); exit; } else if (isset($_POST['submit'])) { - if (Token::isValid() AND Token::isRecent()) + if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) { $_POST['title'] = $purifier->purify(trim($_POST['title'])); From c7ab14bcd3c6ee8b4ddeb5e2a78b94da75612407 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 09:34:45 +0700 Subject: [PATCH 51/94] Add HTMLPurifier Path --- login.php | 143 +++++++++++++++++++++++++++--------------------------- 1 file changed, 72 insertions(+), 71 deletions(-) diff --git a/login.php b/login.php index 12c69642..8ef9cfa0 100644 --- a/login.php +++ b/login.php @@ -1,71 +1,72 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', 'include/'); -require (TR_INCLUDE_PATH.'vitals.inc.php'); - -require_once(TR_INCLUDE_PATH. 'classes/DAO/UsersDAO.class.php'); - -$usersDAO = new UsersDAO(); - -// For security reasons the token has to be generated anew before each login attempt. -// The entropy of SHA-1 input should be comparable to that of its output; in other words, the more randomness you feed it the better. -/*** -* Remove comments below and add comments to the 2 lines in the following block to enable a remote login form. -*/ -//if (isset($_POST['token'])) -//{ -// $_SESSION['token'] = $_POST['token']; -//} -//else -//{ -// if (!isset($_SESSION['token'])) -// $_SESSION['token'] = sha1(mt_rand() . microtime(TRUE)); -//} - -/*** -* Add comments 2 lines below to enable a remote login form. -*/ -if (!isset($_SESSION['token'])) - $_SESSION['token'] = sha1(mt_rand() . microtime(TRUE)); - -if (isset($_POST['submit'])) -{ - $user_id = $usersDAO->Validate($_POST['form_login'], $_POST['form_password_hidden']); - if (!$user_id) - { - $msg->addError('INVALID_LOGIN'); - } - else - { - if ($usersDAO->getStatus($user_id) == TR_STATUS_DISABLED) - { - $msg->addError('ACCOUNT_DISABLED'); - } - else - { - $usersDAO->setLastLogin($user_id); - $_SESSION['user_id'] = $user_id; - $msg->addFeedback('LOGIN_SUCCESS'); - header('Location: index.php'); - exit; - } - } - -} - -global $onload; -$onload = 'document.form.form_login.focus();'; - -//header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"'); -$savant->display('login.tmpl.php'); -?> +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', 'include/'); +define('TR_HTMLPurifier_PATH', 'protection/xss/htmlpurifier/library/'); +require (TR_INCLUDE_PATH.'vitals.inc.php'); + +require_once(TR_INCLUDE_PATH. 'classes/DAO/UsersDAO.class.php'); + +$usersDAO = new UsersDAO(); + +// For security reasons the token has to be generated anew before each login attempt. +// The entropy of SHA-1 input should be comparable to that of its output; in other words, the more randomness you feed it the better. +/*** +* Remove comments below and add comments to the 2 lines in the following block to enable a remote login form. +*/ +//if (isset($_POST['token'])) +//{ +// $_SESSION['token'] = $_POST['token']; +//} +//else +//{ +// if (!isset($_SESSION['token'])) +// $_SESSION['token'] = sha1(mt_rand() . microtime(TRUE)); +//} + +/*** +* Add comments 2 lines below to enable a remote login form. +*/ +if (!isset($_SESSION['token'])) + $_SESSION['token'] = sha1(mt_rand() . microtime(TRUE)); + +if (isset($_POST['submit'])) +{ + $user_id = $usersDAO->Validate($_POST['form_login'], $_POST['form_password_hidden']); + if (!$user_id) + { + $msg->addError('INVALID_LOGIN'); + } + else + { + if ($usersDAO->getStatus($user_id) == TR_STATUS_DISABLED) + { + $msg->addError('ACCOUNT_DISABLED'); + } + else + { + $usersDAO->setLastLogin($user_id); + $_SESSION['user_id'] = $user_id; + $msg->addFeedback('LOGIN_SUCCESS'); + header('Location: index.php'); + exit; + } + } + +} + +global $onload; +$onload = 'document.form.form_login.focus();'; + +//header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"'); +$savant->display('login.tmpl.php'); +?> From c5bdb85426b58f06c102c008f2cc6dfc4cd425c3 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 09:35:26 +0700 Subject: [PATCH 52/94] Add HTMLPurifer Path --- home/index.php | 185 +++++++++++++++++++++++++------------------------ 1 file changed, 93 insertions(+), 92 deletions(-) diff --git a/home/index.php b/home/index.php index 84aa49e7..fd116141 100644 --- a/home/index.php +++ b/home/index.php @@ -1,92 +1,93 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2013 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/UserCoursesDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/CourseCategoriesDAO.class.php'); -$_custom_head .= '<script type="text/javascript" src="home/js/misc.js"></script>'; - -global $_current_user; - -// clean up the session vars from the previous course -unset($_SESSION['course_id']); - -$userCoursesDAO = new UserCoursesDAO(); -$coursesDAO = new CoursesDAO(); -$courseCategoriesDAO = new CourseCategoriesDAO(); - -$catid = $_GET['catid']; -$name_struct = $_GET['stuid']; -$session_user_id = $_SESSION['user_id']; -$action = $_GET['action']; - -$catid = (isset($catid) && trim($catid) <> '') ? intval($catid) : NULL; - -if (isset($action, $_GET['cid']) && $session_user_id > 0) { - $cid = intval($_GET['cid']); - - if ($action == 'remove') { - $userCoursesDAO->Delete($session_user_id, $cid); - } else if ($action == 'add') { - $userCoursesDAO->Create($session_user_id, $cid, TR_USERROLE_VIEWER, 0); - } - - $msg->addFeedback(ACTION_COMPLETED_SUCCESSFULLY); -} - -unset($courses); -$courses = isset($catid) && $catid != 0 ? $coursesDAO->getByCategory($catid) : $coursesDAO->getByMostRecent(); - -// If the user is not an admin then we better filter out courses with empty content -if (!$session_user_id || ($session_user_id && $_current_user->isAdmin($session_user_id) != 1) && !empty($courses)) { - foreach ($courses as $i => $course) { - $course_user_id = $course['user_id']; - $course_id = $course['course_id']; - - $user_role = isset($session_user_id) ? $userCoursesDAO->get($session_user_id, $course_id) : NULL; - $user_role = isset($user_role) ? $user_role['role'] : NULL; - - // If the user is not the owner of the course or owner but not an author - if ($course_user_id != $session_user_id || ($course_user_id == $session_user_id && $user_role != TR_USERROLE_AUTHOR)) { - // Do the check that course should not be empty - if (!$userCoursesDAO->hasContent($course_id)) { - // unset($courses[$i]); - } - } - } - $courses = array_values($courses); -} - -// 22/11/2012 -if(isset($name_struct)){ - $courses = $coursesDAO->getByStructure($name_struct); -} - - -require(TR_INCLUDE_PATH.'header.inc.php'); - -$curr_page_num = intval($_GET['p']); -if (!$curr_page_num) { - $curr_page_num = 1; -} - -$savant->assign('courses', $courses); -$savant->assign('categories', $courseCategoriesDAO->getAll()); -$savant->assign('curr_page_num', $curr_page_num); -$savant->assign('title', isset($catid) ? _AT('search_results') : _AT('most_recent_courses')); - -$savant->display('home/index_course.tmpl.php'); -//debug(MYSQLI_ENABLED); -require(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2013 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/UserCoursesDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/CourseCategoriesDAO.class.php'); +$_custom_head .= '<script type="text/javascript" src="home/js/misc.js"></script>'; + +global $_current_user; + +// clean up the session vars from the previous course +unset($_SESSION['course_id']); + +$userCoursesDAO = new UserCoursesDAO(); +$coursesDAO = new CoursesDAO(); +$courseCategoriesDAO = new CourseCategoriesDAO(); + +$catid = $_GET['catid']; +$name_struct = $_GET['stuid']; +$session_user_id = $_SESSION['user_id']; +$action = $_GET['action']; + +$catid = (isset($catid) && trim($catid) <> '') ? intval($catid) : NULL; + +if (isset($action, $_GET['cid']) && $session_user_id > 0) { + $cid = intval($_GET['cid']); + + if ($action == 'remove') { + $userCoursesDAO->Delete($session_user_id, $cid); + } else if ($action == 'add') { + $userCoursesDAO->Create($session_user_id, $cid, TR_USERROLE_VIEWER, 0); + } + + $msg->addFeedback(ACTION_COMPLETED_SUCCESSFULLY); +} + +unset($courses); +$courses = isset($catid) && $catid != 0 ? $coursesDAO->getByCategory($catid) : $coursesDAO->getByMostRecent(); + +// If the user is not an admin then we better filter out courses with empty content +if (!$session_user_id || ($session_user_id && $_current_user->isAdmin($session_user_id) != 1) && !empty($courses)) { + foreach ($courses as $i => $course) { + $course_user_id = $course['user_id']; + $course_id = $course['course_id']; + + $user_role = isset($session_user_id) ? $userCoursesDAO->get($session_user_id, $course_id) : NULL; + $user_role = isset($user_role) ? $user_role['role'] : NULL; + + // If the user is not the owner of the course or owner but not an author + if ($course_user_id != $session_user_id || ($course_user_id == $session_user_id && $user_role != TR_USERROLE_AUTHOR)) { + // Do the check that course should not be empty + if (!$userCoursesDAO->hasContent($course_id)) { + // unset($courses[$i]); + } + } + } + $courses = array_values($courses); +} + +// 22/11/2012 +if(isset($name_struct)){ + $courses = $coursesDAO->getByStructure($name_struct); +} + + +require(TR_INCLUDE_PATH.'header.inc.php'); + +$curr_page_num = intval($_GET['p']); +if (!$curr_page_num) { + $curr_page_num = 1; +} + +$savant->assign('courses', $courses); +$savant->assign('categories', $courseCategoriesDAO->getAll()); +$savant->assign('curr_page_num', $curr_page_num); +$savant->assign('title', isset($catid) ? _AT('search_results') : _AT('most_recent_courses')); + +$savant->display('home/index_course.tmpl.php'); +//debug(MYSQLI_ENABLED); +require(TR_INCLUDE_PATH.'footer.inc.php'); +?> From 0b7ddc1c48b927cb59abcaa94180d5d5a247eb11 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 09:39:03 +0700 Subject: [PATCH 53/94] Add HTMLPurifier Path --- tests/question_cats_delete.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/question_cats_delete.php b/tests/question_cats_delete.php index dea9e756..43fe3527 100644 --- a/tests/question_cats_delete.php +++ b/tests/question_cats_delete.php @@ -12,6 +12,7 @@ $page = 'tests'; define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsCategoriesDAO.class.php'); require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); @@ -62,4 +63,4 @@ $msg->printConfirm(); require_once(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +?> From c7262d4f73112b4d9da11ced545a55619285006b Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 09:40:15 +0700 Subject: [PATCH 54/94] Add HTMLPurifier Path --- home/create_course.php | 63 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/home/create_course.php b/home/create_course.php index 17183616..d6f8bb4f 100644 --- a/home/create_course.php +++ b/home/create_course.php @@ -1,31 +1,32 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2013 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); -include(TR_INCLUDE_PATH.'classes/DAO/UserGroupsDAO.class.php'); -$dao = new DAO(); -// make sure the user has author privilege -Utility::authenticate(TR_PRIV_ISAUTHOR); - -// get a list of authors if admin is creating a lesson -if($_current_user->isAdmin()){ - $sql = "SELECT user_id, login, first_name, last_name FROM ".TABLE_PREFIX."users WHERE is_author = '1'"; - $user_rows = $dao->execute($sql);; -} - -require(TR_INCLUDE_PATH.'header.inc.php'); -$savant->assign('isauthor', $user_rows); -$savant->display('home/create_course.tmpl.php'); -require(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2013 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +include(TR_INCLUDE_PATH.'classes/DAO/UserGroupsDAO.class.php'); +$dao = new DAO(); +// make sure the user has author privilege +Utility::authenticate(TR_PRIV_ISAUTHOR); + +// get a list of authors if admin is creating a lesson +if($_current_user->isAdmin()){ + $sql = "SELECT user_id, login, first_name, last_name FROM ".TABLE_PREFIX."users WHERE is_author = '1'"; + $user_rows = $dao->execute($sql);; +} + +require(TR_INCLUDE_PATH.'header.inc.php'); +$savant->assign('isauthor', $user_rows); +$savant->display('home/create_course.tmpl.php'); +require(TR_INCLUDE_PATH.'footer.inc.php'); +?> From b9ca74870aa58300c8fc12c95f9a76418bfac933 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 10:18:32 +0700 Subject: [PATCH 55/94] Add HTMLPurifier Path --- tests/delete_question.php | 125 +++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/tests/delete_question.php b/tests/delete_question.php index f7353149..bbf73000 100644 --- a/tests/delete_question.php +++ b/tests/delete_question.php @@ -1,62 +1,63 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsAssocDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); -$testsQuestionsAssocDAO = new TestsQuestionsAssocDAO(); - -$tid = intval($_REQUEST['tid']); - -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} else if (isset($_POST['submit_yes'])) { - $_POST['qid'] = explode(',', $_POST['qid']); - - foreach ($_POST['qid'] as $id) { - $id = intval($id); - - if ($testsQuestionsDAO->Delete($id)) $testsQuestionsAssocDAO->DeleteByQuestionID($id); - } - - $msg->addFeedback('QUESTION_DELETED'); - header('Location: question_db.php?_course_id='.$_course_id); - exit; -} /* else: */ - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$these_questions= explode(",", $_REQUEST['qid']); - -foreach($these_questions as $this_question){ - $this_question = intval($this_question); - $row = $testsQuestionsDAO->get($this_question); - $confirm .= "<li>".$row['question']."</li>"; -} - -$confirm = array('DELETE', $confirm); -$hidden_vars['qid'] = $_REQUEST['qid']; -$hidden_vars['_course_id'] = $_course_id; - -$msg->addConfirm($confirm, $hidden_vars); -$msg->printConfirm(); - -require_once(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsAssocDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); +$testsQuestionsAssocDAO = new TestsQuestionsAssocDAO(); + +$tid = intval($_REQUEST['tid']); + +if (isset($_POST['submit_no'])) { + $msg->addFeedback('CANCELLED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} else if (isset($_POST['submit_yes'])) { + $_POST['qid'] = explode(',', $_POST['qid']); + + foreach ($_POST['qid'] as $id) { + $id = intval($id); + + if ($testsQuestionsDAO->Delete($id)) $testsQuestionsAssocDAO->DeleteByQuestionID($id); + } + + $msg->addFeedback('QUESTION_DELETED'); + header('Location: question_db.php?_course_id='.$_course_id); + exit; +} /* else: */ + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$these_questions= explode(",", $_REQUEST['qid']); + +foreach($these_questions as $this_question){ + $this_question = intval($this_question); + $row = $testsQuestionsDAO->get($this_question); + $confirm .= "<li>".$row['question']."</li>"; +} + +$confirm = array('DELETE', $confirm); +$hidden_vars['qid'] = $_REQUEST['qid']; +$hidden_vars['_course_id'] = $_course_id; + +$msg->addConfirm($confirm, $hidden_vars); +$msg->printConfirm(); + +require_once(TR_INCLUDE_PATH.'footer.inc.php'); +?> From 150d7dc26e6aa2cbc9b8bc16e0ccf720cc6bae01 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 10:41:07 +0700 Subject: [PATCH 56/94] Add HTMLPurifier Path --- tests/questions.php | 189 ++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 94 deletions(-) diff --git a/tests/questions.php b/tests/questions.php index 58b674b1..3ae9f04b 100644 --- a/tests/questions.php +++ b/tests/questions.php @@ -1,94 +1,95 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -$page = 'tests'; -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/testQuestions.class.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsCategoriesDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsAssocDAO.class.php'); - -global $_course_id; - -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsDAO = new TestsDAO(); -$testsQuestionsCategoriesDAO = new TestsQuestionsCategoriesDAO(); -$testsQuestionsAssocDAO = new TestsQuestionsAssocDAO(); - -$_pages['tests/questions.php']['title_var'] = 'questions'; -$_pages['tests/questions.php']['parent'] = 'tests/index.php'; -$_pages['tests/questions.php']['children'] = array('tests/add_test_questions.php?tid='.$_GET['tid'].'&_course_id='.$_course_id); - -$_pages['tests/add_test_questions.php?tid='.$_GET['tid'].'&_course_id='.$_course_id]['title_var'] = 'add_questions'; -$_pages['tests/add_test_questions.php?tid='.$_GET['tid'].'&_course_id='.$_course_id]['parent'] = 'tests/questions.php?tid='.$_GET['tid'].'&_course_id='.$_course_id; - -$_pages['tests/questions.php']['guide'] = 'instructor/?p=add_questions.php'; - -$tid = intval($_REQUEST['tid']); - -if (isset($_POST['submit'])) { - $count = 1; - foreach ($_POST['weight'] as $qid => $weight) { - $qid = intval($qid); - $weight = intval($weight); - - $orders = $_POST['ordering']; - asort($orders); - $orders = array_keys($orders); - - foreach ($orders as $k => $id) - $orders[$k] = intval($id); - - $orders = array_flip($orders); - - $testsQuestionsAssocDAO->Update($tid, $qid, $weight, $orders[$qid]+1); - $count++; - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: '.$_SERVER['PHP_SELF'] .'?tid='.$tid.'&_course_id='.$_course_id); - exit; -} - -$cats = array(); -$cats[0] = _AT('cats_uncategorized'); -$cat_rows = $testsQuestionsCategoriesDAO->getByCourseID($_course_id); -if (is_array($cat_rows)) { - foreach ($cat_rows as $cat_row) { - $cats[$cat_row['category_id']] = $cat_row['title']; - } -} - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -$row = $testsDAO->get($tid); -echo '<div class="input-form">'; -echo '<h3>'._AT('questions_for').' '.AT_print($row['title'], 'tests.title').'</h3>'; - -$rows = $testsQuestionsAssocDAO->getZeroWeightRowsByTestID($tid); -if (is_array($rows)) { - $msg->printWarnings('QUESTION_WEIGHT'); -} - -$msg->printAll(); - -$rows = $testsQuestionsAssocDAO->getByTestID($tid); - -$savant->assign('cats', $cats); -$savant->assign('rows', $rows); -$savant->assign('tid', $tid); -$savant->assign('course_id', $_course_id); -$savant->display('tests/questions.tmpl.php'); -echo '</div>'; -require_once(TR_INCLUDE_PATH.'footer.inc.php');?> +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +$page = 'tests'; +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/testQuestions.class.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsCategoriesDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsAssocDAO.class.php'); + +global $_course_id; + +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsDAO = new TestsDAO(); +$testsQuestionsCategoriesDAO = new TestsQuestionsCategoriesDAO(); +$testsQuestionsAssocDAO = new TestsQuestionsAssocDAO(); + +$_pages['tests/questions.php']['title_var'] = 'questions'; +$_pages['tests/questions.php']['parent'] = 'tests/index.php'; +$_pages['tests/questions.php']['children'] = array('tests/add_test_questions.php?tid='.$_GET['tid'].'&_course_id='.$_course_id); + +$_pages['tests/add_test_questions.php?tid='.$_GET['tid'].'&_course_id='.$_course_id]['title_var'] = 'add_questions'; +$_pages['tests/add_test_questions.php?tid='.$_GET['tid'].'&_course_id='.$_course_id]['parent'] = 'tests/questions.php?tid='.$_GET['tid'].'&_course_id='.$_course_id; + +$_pages['tests/questions.php']['guide'] = 'instructor/?p=add_questions.php'; + +$tid = intval($_REQUEST['tid']); + +if (isset($_POST['submit'])) { + $count = 1; + foreach ($_POST['weight'] as $qid => $weight) { + $qid = intval($qid); + $weight = intval($weight); + + $orders = $_POST['ordering']; + asort($orders); + $orders = array_keys($orders); + + foreach ($orders as $k => $id) + $orders[$k] = intval($id); + + $orders = array_flip($orders); + + $testsQuestionsAssocDAO->Update($tid, $qid, $weight, $orders[$qid]+1); + $count++; + } + + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: '.$_SERVER['PHP_SELF'] .'?tid='.$tid.'&_course_id='.$_course_id); + exit; +} + +$cats = array(); +$cats[0] = _AT('cats_uncategorized'); +$cat_rows = $testsQuestionsCategoriesDAO->getByCourseID($_course_id); +if (is_array($cat_rows)) { + foreach ($cat_rows as $cat_row) { + $cats[$cat_row['category_id']] = $cat_row['title']; + } +} + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +$row = $testsDAO->get($tid); +echo '<div class="input-form">'; +echo '<h3>'._AT('questions_for').' '.AT_print($row['title'], 'tests.title').'</h3>'; + +$rows = $testsQuestionsAssocDAO->getZeroWeightRowsByTestID($tid); +if (is_array($rows)) { + $msg->printWarnings('QUESTION_WEIGHT'); +} + +$msg->printAll(); + +$rows = $testsQuestionsAssocDAO->getByTestID($tid); + +$savant->assign('cats', $cats); +$savant->assign('rows', $rows); +$savant->assign('tid', $tid); +$savant->assign('course_id', $_course_id); +$savant->display('tests/questions.tmpl.php'); +echo '</div>'; +require_once(TR_INCLUDE_PATH.'footer.inc.php');?> From be686249962618af4d78e1729991f337f23d5345 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 10:44:02 +0700 Subject: [PATCH 57/94] Add HTMLPurifier Path --- tests/add_test_questions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/add_test_questions.php b/tests/add_test_questions.php index 75ff109d..61a27498 100644 --- a/tests/add_test_questions.php +++ b/tests/add_test_questions.php @@ -11,6 +11,7 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/testQuestions.class.php'); require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); @@ -56,4 +57,4 @@ </div> <?php require_once(TR_INCLUDE_PATH.'../tests/html/tests_questions.inc.php'); ?> -<?php require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file +<?php require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> From c726bbb5270b7b03f022b899f6508ac318ef9281 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 10:45:22 +0700 Subject: [PATCH 58/94] Add HTMLPurifier Path --- tests/add_test_questions_confirm.php | 207 ++++++++++++++------------- 1 file changed, 104 insertions(+), 103 deletions(-) diff --git a/tests/add_test_questions_confirm.php b/tests/add_test_questions_confirm.php index be994638..06057f8c 100644 --- a/tests/add_test_questions_confirm.php +++ b/tests/add_test_questions_confirm.php @@ -1,103 +1,104 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -$page = 'tests'; -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsAssocDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); -$testsQuestionsDAO = new TestsQuestionsDAO(); -$testsQuestionsAssocDAO = new TestsQuestionsAssocDAO(); - -$tid = intval($_POST['tid']); - -$_pages['tests/questions.php?tid='.$tid.'&_course_id='.$_course_id]['title_var'] = 'questions'; -$_pages['tests/questions.php?tid='.$tid.'&_course_id='.$_course_id]['parent'] = 'tests/index.php'; -$_pages['tests/questions.php?tid='.$tid.'&_course_id='.$_course_id]['children'] = array('tests/add_test_questions.php'); - -$_pages['tests/add_test_questions.php']['title_var'] = 'add_questions'; -$_pages['tests/add_test_questions.php']['parent'] = 'tests/questions.php?tid='.$tid.'&_course_id='.$_course_id; - -$_pages['tests/add_test_questions_confirm.php']['title_var'] = 'add_questions'; -$_pages['tests/add_test_questions_confirm.php']['parent'] = 'tests/questions.php?tid='.$tid.'&_course_id='.$_course_id; - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - header('Location: questions.php?tid='.$tid.'&_course_id='.$_course_id); - exit; -} else if (isset($_POST['submit_yes'])) { - //get order - $order = $testsQuestionsAssocDAO->getMaxOrderByTestID($tid); - - $sql = "REPLACE INTO ".TABLE_PREFIX."tests_questions_assoc VALUES "; - $values = array(); - foreach ($_POST['questions'] as $question) { - $order++; - $question = intval($question); - //$sql .= '('.$tid.', '.$question.', 0, '.$order.'),'; - $sql .= '(?, ?, 0, ?),'; - $values = array_merge($values, array($tid, $question, $order)); - $types .= "iii"; - } - $sql = substr($sql, 0, -1); - - if ($testsQuestionsAssocDAO->execute($sql, $values, $types)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: questions.php?tid='.$tid.'&_course_id='.$_course_id); - exit; - } - else { - $msg->addError('DB_NOT_UPDATED'); - } -} else if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: add_test_questions.php?tid='.$tid.'&_course_id='.$_course_id); - exit; -} - -if (!is_array($_POST['questions']) || !count($_POST['questions'])) { - $msg->addError('NO_QUESTIONS_SELECTED'); - header('Location: add_test_questions.php?tid='.$tid.'&_course_id='.$_course_id); - require_once(TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -foreach ($_POST['questions'] as $id => $cat_array) { - foreach ($cat_array as $idx => $q) { - $_POST['questions'][$id][$idx] = intval($q); - $questions[] = intval($q); - } -} - -$rows = $testsQuestionsDAO->getByQuestionIDs($questions); - -$questions = ''; -if (is_array($rows)) { - foreach ($rows as $row) { - $questions .= '<li>'.htmlspecialchars($row['question']).'</li>'; - $questions_array['questions['.$row['question_id'].']'] = $row['question_id']; - } -} -$questions_array['tid'] = $_POST['tid']; -$questions_array['_course_id'] = $_course_id; -$msg->addConfirm(array('ADD_TEST_QUESTIONS', $questions), $questions_array); - -$msg->printConfirm(); -?> - -<?php require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +$page = 'tests'; +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsAssocDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsDAO.class.php'); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); +$testsQuestionsDAO = new TestsQuestionsDAO(); +$testsQuestionsAssocDAO = new TestsQuestionsAssocDAO(); + +$tid = intval($_POST['tid']); + +$_pages['tests/questions.php?tid='.$tid.'&_course_id='.$_course_id]['title_var'] = 'questions'; +$_pages['tests/questions.php?tid='.$tid.'&_course_id='.$_course_id]['parent'] = 'tests/index.php'; +$_pages['tests/questions.php?tid='.$tid.'&_course_id='.$_course_id]['children'] = array('tests/add_test_questions.php'); + +$_pages['tests/add_test_questions.php']['title_var'] = 'add_questions'; +$_pages['tests/add_test_questions.php']['parent'] = 'tests/questions.php?tid='.$tid.'&_course_id='.$_course_id; + +$_pages['tests/add_test_questions_confirm.php']['title_var'] = 'add_questions'; +$_pages['tests/add_test_questions_confirm.php']['parent'] = 'tests/questions.php?tid='.$tid.'&_course_id='.$_course_id; + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + header('Location: questions.php?tid='.$tid.'&_course_id='.$_course_id); + exit; +} else if (isset($_POST['submit_yes'])) { + //get order + $order = $testsQuestionsAssocDAO->getMaxOrderByTestID($tid); + + $sql = "REPLACE INTO ".TABLE_PREFIX."tests_questions_assoc VALUES "; + $values = array(); + foreach ($_POST['questions'] as $question) { + $order++; + $question = intval($question); + //$sql .= '('.$tid.', '.$question.', 0, '.$order.'),'; + $sql .= '(?, ?, 0, ?),'; + $values = array_merge($values, array($tid, $question, $order)); + $types .= "iii"; + } + $sql = substr($sql, 0, -1); + + if ($testsQuestionsAssocDAO->execute($sql, $values, $types)) { + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: questions.php?tid='.$tid.'&_course_id='.$_course_id); + exit; + } + else { + $msg->addError('DB_NOT_UPDATED'); + } +} else if (isset($_POST['submit_no'])) { + $msg->addFeedback('CANCELLED'); + header('Location: add_test_questions.php?tid='.$tid.'&_course_id='.$_course_id); + exit; +} + +if (!is_array($_POST['questions']) || !count($_POST['questions'])) { + $msg->addError('NO_QUESTIONS_SELECTED'); + header('Location: add_test_questions.php?tid='.$tid.'&_course_id='.$_course_id); + require_once(TR_INCLUDE_PATH.'footer.inc.php'); + exit; +} + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +foreach ($_POST['questions'] as $id => $cat_array) { + foreach ($cat_array as $idx => $q) { + $_POST['questions'][$id][$idx] = intval($q); + $questions[] = intval($q); + } +} + +$rows = $testsQuestionsDAO->getByQuestionIDs($questions); + +$questions = ''; +if (is_array($rows)) { + foreach ($rows as $row) { + $questions .= '<li>'.htmlspecialchars($row['question']).'</li>'; + $questions_array['questions['.$row['question_id'].']'] = $row['question_id']; + } +} +$questions_array['tid'] = $_POST['tid']; +$questions_array['_course_id'] = $_course_id; +$msg->addConfirm(array('ADD_TEST_QUESTIONS', $questions), $questions_array); + +$msg->printConfirm(); +?> + +<?php require_once(TR_INCLUDE_PATH.'footer.inc.php'); ?> From 95c7a52ac95b571b864cbbbe81f73698a16a16ed Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 10:47:21 +0700 Subject: [PATCH 59/94] Add HTMLPurifier Path --- tests/question_remove.php | 119 +++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/tests/question_remove.php b/tests/question_remove.php index d374d853..5ea2fdbe 100644 --- a/tests/question_remove.php +++ b/tests/question_remove.php @@ -1,59 +1,60 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -$page = 'tests'; -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsAssocDAO.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); - -$tid = intval($_REQUEST['tid']); -$qid = intval($_REQUEST['qid']); - -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: questions.php?tid=' . $tid.SEP.'_course_id='.$_course_id); - exit; -} else if (isset($_POST['submit_yes'])) { - $testsQuestionsAssocDAO = new TestsQuestionsAssocDAO(); - $testsQuestionsAssocDAO->Delete($tid, $qid); - $msg->addFeedback('QUESTION_REMOVED'); - header('Location: questions.php?tid=' . $tid.SEP.'_course_id='.$_course_id); - exit; - -} /* else: */ - -$_pages['tests/questions.php?tid='.$_GET['tid']]['title_var'] = 'questions'; -$_pages['tests/questions.php?tid='.$_GET['tid']]['parent'] = 'tests/index.php'; -$_pages['tests/questions.php?tid='.$_GET['tid']]['children'] = array('tests/add_test_questions.php?tid='.$_GET['tid']); - -$_pages['tests/add_test_questions.php?tid='.$_GET['tid']]['title_var'] = 'add_questions'; -$_pages['tests/add_test_questions.php?tid='.$_GET['tid']]['parent'] = 'tests/questions.php?tid='.$_GET['tid']; - -$_pages['tests/question_remove.php']['title_var'] = 'remove_question'; -$_pages['tests/question_remove.php']['parent'] = 'tests/questions.php?tid='.$_GET['tid']; - -require_once(TR_INCLUDE_PATH.'header.inc.php'); - -unset($hidden_vars); -$hidden_vars['qid'] = $_GET['qid']; -$hidden_vars['tid'] = $_GET['tid']; -$hidden_vars['_course_id'] = $_course_id; -$msg->addConfirm('REMOVE_TEST_QUESTION', $hidden_vars); - -$msg->printConfirm(); - -require_once(TR_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +$page = 'tests'; +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/Utility.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/TestsQuestionsAssocDAO.class.php'); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); + +$tid = intval($_REQUEST['tid']); +$qid = intval($_REQUEST['qid']); + +if (isset($_POST['submit_no'])) { + $msg->addFeedback('CANCELLED'); + header('Location: questions.php?tid=' . $tid.SEP.'_course_id='.$_course_id); + exit; +} else if (isset($_POST['submit_yes'])) { + $testsQuestionsAssocDAO = new TestsQuestionsAssocDAO(); + $testsQuestionsAssocDAO->Delete($tid, $qid); + $msg->addFeedback('QUESTION_REMOVED'); + header('Location: questions.php?tid=' . $tid.SEP.'_course_id='.$_course_id); + exit; + +} /* else: */ + +$_pages['tests/questions.php?tid='.$_GET['tid']]['title_var'] = 'questions'; +$_pages['tests/questions.php?tid='.$_GET['tid']]['parent'] = 'tests/index.php'; +$_pages['tests/questions.php?tid='.$_GET['tid']]['children'] = array('tests/add_test_questions.php?tid='.$_GET['tid']); + +$_pages['tests/add_test_questions.php?tid='.$_GET['tid']]['title_var'] = 'add_questions'; +$_pages['tests/add_test_questions.php?tid='.$_GET['tid']]['parent'] = 'tests/questions.php?tid='.$_GET['tid']; + +$_pages['tests/question_remove.php']['title_var'] = 'remove_question'; +$_pages['tests/question_remove.php']['parent'] = 'tests/questions.php?tid='.$_GET['tid']; + +require_once(TR_INCLUDE_PATH.'header.inc.php'); + +unset($hidden_vars); +$hidden_vars['qid'] = $_GET['qid']; +$hidden_vars['tid'] = $_GET['tid']; +$hidden_vars['_course_id'] = $_course_id; +$msg->addConfirm('REMOVE_TEST_QUESTION', $hidden_vars); + +$msg->printConfirm(); + +require_once(TR_INCLUDE_PATH.'footer.inc.php'); +?> From 2d3626a70f7b0d44445efcc252d4aac48f086cbc Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 10:53:35 +0700 Subject: [PATCH 60/94] Add HTMLPurifier Path --- file_manager/delete.php | 345 ++++++++++----------- file_manager/edit.php | 1 + file_manager/move.php | 413 ++++++++++++------------- file_manager/new.php | 403 ++++++++++++------------ file_manager/preview.php | 3 +- file_manager/preview_top.php | 3 +- file_manager/rename.php | 199 ++++++------ file_manager/top.php | 1 + file_manager/upload.php | 353 ++++++++++----------- file_manager/zip.php | 581 ++++++++++++++++++----------------- 10 files changed, 1156 insertions(+), 1146 deletions(-) diff --git a/file_manager/delete.php b/file_manager/delete.php index 1feea3d9..758f6fad 100644 --- a/file_manager/delete.php +++ b/file_manager/delete.php @@ -1,172 +1,173 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require_once(TR_INCLUDE_PATH.'vitals.inc.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/PrimaryResourcesDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/PrimaryResourcesTypesDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/SecondaryResourcesDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/DAO/SecondaryResourcesTypesDAO.class.php'); -require_once(TR_INCLUDE_PATH.'classes/FileUtility.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); - -$current_path = TR_CONTENT_DIR.$_course_id.'/'; - -$popup = $_REQUEST['popup']; -$framed = $_REQUEST['framed']; - -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; -} - -if (isset($_POST['submit_yes'])) { - /* delete files and directories */ - /* delete the file */ - $pathext = $_POST['pathext']; - if (isset($_POST['listoffiles'])) { - $checkbox = explode(',',$_POST['listoffiles']); - $count = count($checkbox); - $result=true; - for ($i=0; $i<$count; $i++) { - $filename=$checkbox[$i]; - - if (FileUtility::course_realpath($current_path . $pathext . $filename) == FALSE) { - $msg->addError('FILE_NOT_DELETED'); - $result=false; - break; - } else if (!(@unlink($current_path.$pathext.$filename))) { - $msg->addError('FILE_NOT_DELETED'); - $result=false; - break; - } - } - if ($result) - { - // delete according definition of primary resources and alternatives for adapted content - $filename = '../'.$pathext.$filename; - - // 1. delete secondary resources types - $secondaryResourcesTypesDAO = new SecondaryResourcesTypesDAO(); - $secondaryResourcesTypesDAO->DeleteByResourceName($filename); - - // 2. delete secondary resources - $secondaryResourcesDAO = new SecondaryResourcesDAO(); - $secondaryResourcesDAO->DeleteByResourceName($filename); - - // 3. delete primary resources types - $primaryResourcesTypesDAO = new PrimaryResourcesTypesDAO(); - $primaryResourcesTypesDAO->DeleteByResourceName($filename); - - // 4. delete primary resources - $primaryResourcesDAO = new PrimaryResourcesDAO(); - $primaryResourcesDAO->DeleteByResourceName($filename); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - } - } - /* delete directory */ - if (isset($_POST['listofdirs'])) { - - $checkbox = explode(',',$_POST['listofdirs']); - $count = count($checkbox); - $result=true; - for ($i=0; $i<$count; $i++) { - $filename=$checkbox[$i]; - - if (strpos($filename, '..') !== false) { - $msg->addError('UNKNOWN'); - $result=false; - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } else if (!is_dir($current_path.$pathext.$filename)) { - $msg->addError(array('DIR_NOT_DELETED',$filename)); - $result=false; - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } else if (!($result = FileUtility::clr_dir($current_path.$pathext.$filename))) { - $msg->addError('DIR_NO_PERMISSION'); - $result=false; - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - } - if ($result) - $msg->addFeedback('DIR_DELETED'); - } - - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; -} - - require(TR_INCLUDE_PATH.'header.inc.php'); - // find the files and directories to be deleted - $total_list = explode(',', $_GET['list']); - $pathext = $_GET['pathext']; - $popup = $_GET['popup']; - $framed = $_GET['framed']; - $cp = $_GET['cp']; - $cid = $_GET['cid']; - $pid = $_GET['pid']; - $a_type = $_GET['a_type']; - - $count = count($total_list); - $countd = 0; - $countf = 0; - - foreach ($total_list as $list_item) { - if (is_dir($current_path.$pathext.$list_item)) { - $_dirs[$countd] = $list_item; - $countd++; - } else { - $_files[$countf] = $list_item; - $countf++; - } - } - - $hidden_vars['pathext'] = $pathext; - $hidden_vars['popup'] = $popup; - $hidden_vars['framed'] = $framed; - $hidden_vars['cp'] = $cp; - $hidden_vars['cid'] = $cid; - $hidden_vars['pid'] = $pid; - $hidden_vars['a_type'] = $a_type; - $hidden_vars['_course_id'] = $_course_id; - - if (isset($_files)) { - $list_of_files = implode(',', $_files); - $hidden_vars['listoffiles'] = $list_of_files; - - foreach ($_files as $file) { - $file_list_to_print .= '<li>'.$file.'</li>'; - } - $msg->addConfirm(array('FILE_DELETE', $file_list_to_print), $hidden_vars); - } - - if (isset($_dirs)) { - $list_of_dirs = implode(',', $_dirs); - $hidden_vars['listofdirs'] = $list_of_dirs; - - foreach ($_dirs as $dir) { - $dir_list_to_print .= '<li>'.$dir.'</li>'; - } - - $msg->addConfirm(array('DIR_DELETE',$dir_list_to_print), $hidden_vars); - } - - $msg->printConfirm(); - - require(TR_INCLUDE_PATH.'footer.inc.php'); -?> +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require_once(TR_INCLUDE_PATH.'vitals.inc.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/PrimaryResourcesDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/PrimaryResourcesTypesDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/SecondaryResourcesDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/DAO/SecondaryResourcesTypesDAO.class.php'); +require_once(TR_INCLUDE_PATH.'classes/FileUtility.class.php'); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); + +$current_path = TR_CONTENT_DIR.$_course_id.'/'; + +$popup = $_REQUEST['popup']; +$framed = $_REQUEST['framed']; + +if (isset($_POST['submit_no'])) { + $msg->addFeedback('CANCELLED'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; +} + +if (isset($_POST['submit_yes'])) { + /* delete files and directories */ + /* delete the file */ + $pathext = $_POST['pathext']; + if (isset($_POST['listoffiles'])) { + $checkbox = explode(',',$_POST['listoffiles']); + $count = count($checkbox); + $result=true; + for ($i=0; $i<$count; $i++) { + $filename=$checkbox[$i]; + + if (FileUtility::course_realpath($current_path . $pathext . $filename) == FALSE) { + $msg->addError('FILE_NOT_DELETED'); + $result=false; + break; + } else if (!(@unlink($current_path.$pathext.$filename))) { + $msg->addError('FILE_NOT_DELETED'); + $result=false; + break; + } + } + if ($result) + { + // delete according definition of primary resources and alternatives for adapted content + $filename = '../'.$pathext.$filename; + + // 1. delete secondary resources types + $secondaryResourcesTypesDAO = new SecondaryResourcesTypesDAO(); + $secondaryResourcesTypesDAO->DeleteByResourceName($filename); + + // 2. delete secondary resources + $secondaryResourcesDAO = new SecondaryResourcesDAO(); + $secondaryResourcesDAO->DeleteByResourceName($filename); + + // 3. delete primary resources types + $primaryResourcesTypesDAO = new PrimaryResourcesTypesDAO(); + $primaryResourcesTypesDAO->DeleteByResourceName($filename); + + // 4. delete primary resources + $primaryResourcesDAO = new PrimaryResourcesDAO(); + $primaryResourcesDAO->DeleteByResourceName($filename); + + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + } + } + /* delete directory */ + if (isset($_POST['listofdirs'])) { + + $checkbox = explode(',',$_POST['listofdirs']); + $count = count($checkbox); + $result=true; + for ($i=0; $i<$count; $i++) { + $filename=$checkbox[$i]; + + if (strpos($filename, '..') !== false) { + $msg->addError('UNKNOWN'); + $result=false; + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } else if (!is_dir($current_path.$pathext.$filename)) { + $msg->addError(array('DIR_NOT_DELETED',$filename)); + $result=false; + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } else if (!($result = FileUtility::clr_dir($current_path.$pathext.$filename))) { + $msg->addError('DIR_NO_PERMISSION'); + $result=false; + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + } + if ($result) + $msg->addFeedback('DIR_DELETED'); + } + + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; +} + + require(TR_INCLUDE_PATH.'header.inc.php'); + // find the files and directories to be deleted + $total_list = explode(',', $_GET['list']); + $pathext = $_GET['pathext']; + $popup = $_GET['popup']; + $framed = $_GET['framed']; + $cp = $_GET['cp']; + $cid = $_GET['cid']; + $pid = $_GET['pid']; + $a_type = $_GET['a_type']; + + $count = count($total_list); + $countd = 0; + $countf = 0; + + foreach ($total_list as $list_item) { + if (is_dir($current_path.$pathext.$list_item)) { + $_dirs[$countd] = $list_item; + $countd++; + } else { + $_files[$countf] = $list_item; + $countf++; + } + } + + $hidden_vars['pathext'] = $pathext; + $hidden_vars['popup'] = $popup; + $hidden_vars['framed'] = $framed; + $hidden_vars['cp'] = $cp; + $hidden_vars['cid'] = $cid; + $hidden_vars['pid'] = $pid; + $hidden_vars['a_type'] = $a_type; + $hidden_vars['_course_id'] = $_course_id; + + if (isset($_files)) { + $list_of_files = implode(',', $_files); + $hidden_vars['listoffiles'] = $list_of_files; + + foreach ($_files as $file) { + $file_list_to_print .= '<li>'.$file.'</li>'; + } + $msg->addConfirm(array('FILE_DELETE', $file_list_to_print), $hidden_vars); + } + + if (isset($_dirs)) { + $list_of_dirs = implode(',', $_dirs); + $hidden_vars['listofdirs'] = $list_of_dirs; + + foreach ($_dirs as $dir) { + $dir_list_to_print .= '<li>'.$dir.'</li>'; + } + + $msg->addConfirm(array('DIR_DELETE',$dir_list_to_print), $hidden_vars); + } + + $msg->printConfirm(); + + require(TR_INCLUDE_PATH.'footer.inc.php'); +?> diff --git a/file_manager/edit.php b/file_manager/edit.php index 76cd9631..cd5ba4e6 100644 --- a/file_manager/edit.php +++ b/file_manager/edit.php @@ -11,6 +11,7 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'vitals.inc.php'); require_once(TR_INCLUDE_PATH.'classes/FileUtility.class.php'); diff --git a/file_manager/move.php b/file_manager/move.php index 8ce3ca85..867953a5 100644 --- a/file_manager/move.php +++ b/file_manager/move.php @@ -1,206 +1,207 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require(TR_INCLUDE_PATH.'vitals.inc.php'); -require(TR_INCLUDE_PATH.'classes/FileUtility.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); - -$current_path = TR_CONTENT_DIR.$_course_id.'/'; - -$popup = $_REQUEST['popup']; -$framed = $_REQUEST['framed']; - -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_REQUEST['framed'].SEP.'popup='.$_REQUEST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; -} - -if (isset($_POST['submit_yes'])) { - $dest = $_POST['dest'] .'/'; - $pathext = $_POST['pathext']; - - if (isset($_POST['listofdirs'])) { - - $_dirs = explode(',',$_POST['listofdirs']); - $count = count($_dirs); - - for ($i = 0; $i < $count; $i++) { - $source = $_dirs[$i]; - - if (FileUtility::course_realpath($current_path . $pathext . $source) == FALSE) { - // error: File does not exist - $msg->addError('DIR_NOT_EXIST'); - header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - else if (FileUtility::course_realpath($current_path . $dest) == FALSE) { - // error: File does not exist - $msg->addError('UNKNOWN'); - header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - else if (strpos($source, '..') !== false) { - $msg->addError('UNKNOWN'); - header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - else { - @rename($current_path.$pathext.$source, $current_path.$dest.$source); - } - } - $msg->addFeedback('DIRS_MOVED'); - } - if (isset($_POST['listoffiles'])) { - - $_files = explode(',',$_POST['listoffiles']); - $count = count($_files); - - for ($i = 0; $i < $count; $i++) { - $source = $_files[$i]; - - if (FileUtility::course_realpath($current_path . $pathext . $source) == FALSE) { - // error: File does not exist - $msg->addError('FILE_NOT_EXIST'); - header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - else if (FileUtility::course_realpath($current_path . $dest) == FALSE) { - // error: File does not exist - $msg->addError('UNKNOWN'); - header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - else if (strpos($source, '..') !== false) { - $msg->addError('UNKNOWN'); - header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - else { - @rename($current_path.$pathext.$source, $current_path.$dest.$source); - } - } - $msg->addFeedback('MOVED_FILES'); - } - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; -} - -if (isset($_POST['dir_chosen'])) { - $hidden_vars['framed'] = $_REQUEST['framed']; - $hidden_vars['popup'] = $_REQUEST['popup']; - $hidden_vars['pathext'] = $_REQUEST['pathext']; - $hidden_vars['dest'] = $_REQUEST['dir_name']; - $hidden_vars['cp'] = $_REQUEST['cp']; - $hidden_vars['cid'] = $_REQUEST['cid']; - $hidden_vars['pid'] = $_REQUEST['pid']; - $hidden_vars['a_type'] = $_REQUEST['a_type']; - $hidden_vars['_course_id'] = $_course_id; - - if (isset($_POST['files'])) { - $list_of_files = implode(',', $_POST['files']); - $hidden_vars['listoffiles'] = $list_of_files; - $msg->addConfirm(array('FILE_MOVE', $list_of_files, $_POST['dir_name']), $hidden_vars); - } - if (isset($_POST['dirs'])) { - $list_of_dirs = implode(',', $_POST['dirs']); - $hidden_vars['listoffiles'] = $list_of_dirs; - $msg->addConfirm(array('DIR_MOVE', $list_of_dirs, $_POST['dir_name']), $hidden_vars); - } - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printConfirm(); - require(TR_INCLUDE_PATH.'footer.inc.php'); -} -else { - require(TR_INCLUDE_PATH.'header.inc.php'); - - $tree = TR_CONTENT_DIR.$_course_id.'/'; - $file = $_GET['file']; - $pathext = $_GET['pathext']; - $popup = $_GET['popup']; - $framed = $_GET['framed']; - $cp = $_GET['cp']; - $cid = $_GET['cid']; - $pid = $_GET['pid']; - $a_type = $_GET['a_type']; - - /* find the files and directories to be copied */ - $total_list = explode(',', $_GET['list']); - - $count = count($total_list); - $countd = 0; - $countf = 0; - for ($i=0; $i<$count; $i++) { - if (is_dir($current_path.$pathext.$total_list[$i])) { - $_dirs[$countd] = $total_list[$i]; - $hidden_dirs .= '<input type="hidden" name="dirs['.$countd.']" value="'.$_dirs[$countd].'" />'; - $countd++; - } else { - $_files[$countf] = $total_list[$i]; - $hidden_files .= '<input type="hidden" name="files['.$countf.']" value="'.$_files[$countf].'" />'; - $countf++; - } - } -?> - -<form name="move_form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>"> -<div class="input-form"> - <div class="row"> - <p><?php echo _AT('select_directory'); ?></p> - </div> - - <div class="row"> - <ul> - <li class="folders"><label><input type="radio" name="dir_name" value=""<?php - if ($pathext == '') { - echo ' checked="checked"'; - $here = ' ' . _AT('current_location'); - } - echo '/>Home ' .$here.'</label>'; - - echo FileUtility::display_tree($current_path, '', $pathext); - ?></li> - </ul> - </div> - - <div class="row buttons"> - <input type="submit" name="dir_chosen" value="<?php echo _AT('move'); ?>" accesskey="s" /> - <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" /> - </div> -</div> - -<input type="hidden" name="pathext" value="<?php echo AT_print($pathext, 'input.hidden'); ?>" /> -<input type="hidden" name="framed" value="<?php echo AT_print($framed, 'input.hidden'); ?>" /> -<input type="hidden" name="popup" value="<?php echo AT_print($popup, 'input.hidden'); ?>" /> -<input type="hidden" name="cp" value="<?php echo AT_print($cp, 'input.hidden'); ?>" /> -<input type="hidden" name="cid" value="<?php echo AT_print($cid, 'input.hidden'); ?>" /> -<input type="hidden" name="pid" value="<?php echo AT_print($pid, 'input.hidden'); ?>" /> -<input type="hidden" name="a_type" value="<?php echo AT_print($a_type, 'input.hidden'); ?>" /> -<input type="hidden" name="_course_id" value="<?php echo AT_print($_course_id, 'input.hidden'); ?>" /> -<?php - echo $hidden_dirs; - echo $hidden_files; -?> -</form> - -<?php require(TR_INCLUDE_PATH.'footer.inc.php'); -} -?> \ No newline at end of file +<?php +/************************************************************************/ +/* AContent */ +/************************************************************************/ +/* Copyright (c) 2010 */ +/* Inclusive Design Institute */ +/* */ +/* This program is free software. You can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation. */ +/************************************************************************/ + +define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); +require(TR_INCLUDE_PATH.'vitals.inc.php'); +require(TR_INCLUDE_PATH.'classes/FileUtility.class.php'); + +global $_course_id; +Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); + +$current_path = TR_CONTENT_DIR.$_course_id.'/'; + +$popup = $_REQUEST['popup']; +$framed = $_REQUEST['framed']; + +if (isset($_POST['submit_no'])) { + $msg->addFeedback('CANCELLED'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; +} + +if (isset($_POST['cancel'])) { + $msg->addFeedback('CANCELLED'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_REQUEST['framed'].SEP.'popup='.$_REQUEST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; +} + +if (isset($_POST['submit_yes'])) { + $dest = $_POST['dest'] .'/'; + $pathext = $_POST['pathext']; + + if (isset($_POST['listofdirs'])) { + + $_dirs = explode(',',$_POST['listofdirs']); + $count = count($_dirs); + + for ($i = 0; $i < $count; $i++) { + $source = $_dirs[$i]; + + if (FileUtility::course_realpath($current_path . $pathext . $source) == FALSE) { + // error: File does not exist + $msg->addError('DIR_NOT_EXIST'); + header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + else if (FileUtility::course_realpath($current_path . $dest) == FALSE) { + // error: File does not exist + $msg->addError('UNKNOWN'); + header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + else if (strpos($source, '..') !== false) { + $msg->addError('UNKNOWN'); + header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + else { + @rename($current_path.$pathext.$source, $current_path.$dest.$source); + } + } + $msg->addFeedback('DIRS_MOVED'); + } + if (isset($_POST['listoffiles'])) { + + $_files = explode(',',$_POST['listoffiles']); + $count = count($_files); + + for ($i = 0; $i < $count; $i++) { + $source = $_files[$i]; + + if (FileUtility::course_realpath($current_path . $pathext . $source) == FALSE) { + // error: File does not exist + $msg->addError('FILE_NOT_EXIST'); + header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + else if (FileUtility::course_realpath($current_path . $dest) == FALSE) { + // error: File does not exist + $msg->addError('UNKNOWN'); + header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + else if (strpos($source, '..') !== false) { + $msg->addError('UNKNOWN'); + header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + else { + @rename($current_path.$pathext.$source, $current_path.$dest.$source); + } + } + $msg->addFeedback('MOVED_FILES'); + } + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; +} + +if (isset($_POST['dir_chosen'])) { + $hidden_vars['framed'] = $_REQUEST['framed']; + $hidden_vars['popup'] = $_REQUEST['popup']; + $hidden_vars['pathext'] = $_REQUEST['pathext']; + $hidden_vars['dest'] = $_REQUEST['dir_name']; + $hidden_vars['cp'] = $_REQUEST['cp']; + $hidden_vars['cid'] = $_REQUEST['cid']; + $hidden_vars['pid'] = $_REQUEST['pid']; + $hidden_vars['a_type'] = $_REQUEST['a_type']; + $hidden_vars['_course_id'] = $_course_id; + + if (isset($_POST['files'])) { + $list_of_files = implode(',', $_POST['files']); + $hidden_vars['listoffiles'] = $list_of_files; + $msg->addConfirm(array('FILE_MOVE', $list_of_files, $_POST['dir_name']), $hidden_vars); + } + if (isset($_POST['dirs'])) { + $list_of_dirs = implode(',', $_POST['dirs']); + $hidden_vars['listoffiles'] = $list_of_dirs; + $msg->addConfirm(array('DIR_MOVE', $list_of_dirs, $_POST['dir_name']), $hidden_vars); + } + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printConfirm(); + require(TR_INCLUDE_PATH.'footer.inc.php'); +} +else { + require(TR_INCLUDE_PATH.'header.inc.php'); + + $tree = TR_CONTENT_DIR.$_course_id.'/'; + $file = $_GET['file']; + $pathext = $_GET['pathext']; + $popup = $_GET['popup']; + $framed = $_GET['framed']; + $cp = $_GET['cp']; + $cid = $_GET['cid']; + $pid = $_GET['pid']; + $a_type = $_GET['a_type']; + + /* find the files and directories to be copied */ + $total_list = explode(',', $_GET['list']); + + $count = count($total_list); + $countd = 0; + $countf = 0; + for ($i=0; $i<$count; $i++) { + if (is_dir($current_path.$pathext.$total_list[$i])) { + $_dirs[$countd] = $total_list[$i]; + $hidden_dirs .= '<input type="hidden" name="dirs['.$countd.']" value="'.$_dirs[$countd].'" />'; + $countd++; + } else { + $_files[$countf] = $total_list[$i]; + $hidden_files .= '<input type="hidden" name="files['.$countf.']" value="'.$_files[$countf].'" />'; + $countf++; + } + } +?> + +<form name="move_form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>"> +<div class="input-form"> + <div class="row"> + <p><?php echo _AT('select_directory'); ?></p> + </div> + + <div class="row"> + <ul> + <li class="folders"><label><input type="radio" name="dir_name" value=""<?php + if ($pathext == '') { + echo ' checked="checked"'; + $here = ' ' . _AT('current_location'); + } + echo '/>Home ' .$here.'</label>'; + + echo FileUtility::display_tree($current_path, '', $pathext); + ?></li> + </ul> + </div> + + <div class="row buttons"> + <input type="submit" name="dir_chosen" value="<?php echo _AT('move'); ?>" accesskey="s" /> + <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" /> + </div> +</div> + +<input type="hidden" name="pathext" value="<?php echo AT_print($pathext, 'input.hidden'); ?>" /> +<input type="hidden" name="framed" value="<?php echo AT_print($framed, 'input.hidden'); ?>" /> +<input type="hidden" name="popup" value="<?php echo AT_print($popup, 'input.hidden'); ?>" /> +<input type="hidden" name="cp" value="<?php echo AT_print($cp, 'input.hidden'); ?>" /> +<input type="hidden" name="cid" value="<?php echo AT_print($cid, 'input.hidden'); ?>" /> +<input type="hidden" name="pid" value="<?php echo AT_print($pid, 'input.hidden'); ?>" /> +<input type="hidden" name="a_type" value="<?php echo AT_print($a_type, 'input.hidden'); ?>" /> +<input type="hidden" name="_course_id" value="<?php echo AT_print($_course_id, 'input.hidden'); ?>" /> +<?php + echo $hidden_dirs; + echo $hidden_files; +?> +</form> + +<?php require(TR_INCLUDE_PATH.'footer.inc.php'); +} +?> diff --git a/file_manager/new.php b/file_manager/new.php index 9051d0b5..ba0301af 100644 --- a/file_manager/new.php +++ b/file_manager/new.php @@ -1,201 +1,202 @@ -<?php -/************************************************************************/ -/* AContent */ -/************************************************************************/ -/* Copyright (c) 2010 */ -/* Inclusive Design Institute */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/************************************************************************/ - -define('TR_INCLUDE_PATH', '../include/'); -require(TR_INCLUDE_PATH.'vitals.inc.php'); -require(TR_INCLUDE_PATH.'classes/FileUtility.class.php'); - -global $_course_id; -Utility::authenticate(TR_PRIV_ISAUTHOR_OF_CURRENT_COURSE); - -$current_path = TR_CONTENT_DIR.$_course_id.'/'; - -$popup = $_REQUEST['popup']; -$framed = $_REQUEST['framed']; - - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'_course_id='.$_course_id); - exit; -} - -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'_course_id='.$_course_id); - exit; -} - -if (isset($_POST['submit_yes'])) { - $filename = preg_replace("{[^a-zA-Z0-9_]}","_", trim($_POST['filename'])); - $pathext = $_POST['pathext']; - - /* only html or txt extensions allowed */ - if ($_POST['extension'] == 'html') { - $extension = 'html'; - } else { - $extension = 'txt'; - } - - if (FileUtility::course_realpath($current_path . $pathext . $filename.'.'.$extension) == FALSE) { - $msg->addError('FILE_NOT_SAVED'); - /* take user to home page to avoid unspecified error warning */ - header('Location: index.php?pathext='.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'_course_id='.$_course_id); - exit; - } - - if (($f = @fopen($current_path.$pathext.$filename.'.'.$extension,'w')) && @fwrite($f, stripslashes($_POST['body_text'])) !== FALSE && @fclose($f)){ - $msg->addFeedback('FILE_OVERWRITE'); - } else { - $msg->addError('CANNOT_OVERWRITE_FILE'); - } - unset($_POST['newfile']); - header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'_course_id='.$_course_id); - exit; -} - -if (isset($_POST['savenewfile'])) { - - if (isset($_POST['filename']) && ($_POST['filename'] != "")) { - $filename = preg_replace("{[^a-zA-Z0-9_]}","_", trim($_POST['filename'])); - $pathext = $_POST['pathext']; - $current_path = TR_CONTENT_DIR.$_course_id.'/'; - - /* only html or txt extensions allowed */ - if ($_POST['extension'] == 'html') { - $extension = 'html'; - $head_html = "<html>\n<head>\n<title>".$_POST['filename']."\n\n"; - $foot_html ="\n\n"; - } else { - $extension = 'txt'; - } - - if (!@file_exists($current_path.$pathext.$filename.'.'.$extension)) { - $content = str_replace("\r\n", "\n", $head_html.$_POST['body_text'].$foot_html); - - if (FileUtility::course_realpath($current_path . $pathext . $filename.'.'.$extension) == FALSE) { - $msg->addError('FILE_NOT_SAVED'); - /* take user to home page to avoid unspecified error warning */ - header('Location: index.php?pathext='.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'_course_id='.$_course_id); - exit; - } - - if (($f = fopen($current_path.$pathext.$filename.'.'.$extension, 'w')) && (@fwrite($f, stripslashes($content)) !== false) && (@fclose($f))) { - $msg->addFeedback(array('FILE_SAVED', $filename.'.'.$extension)); - header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'popup='.$_POST['popup'].SEP.'_course_id='.$_course_id); - exit; - } else { - $msg->addError('FILE_NOT_SAVED'); - header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'_course_id='.$_course_id); - exit; - } - } - else { - require(TR_INCLUDE_PATH.'header.inc.php'); - $pathext = $_POST['pathext']; - $popup = $_POST['popup']; - - $_POST['newfile'] = "new"; - - $hidden_vars['pathext'] = $pathext; - $hidden_vars['filename'] = $filename; - $hidden_vars['extension'] = $extension; - $hidden_vars['_course_id'] = $_course_id; - $hidden_vars['body_text'] = $_POST['body_text']; - - $hidden_vars['popup'] = $popup; - $hidden_vars['framed'] = $framed; - - $msg->addConfirm(array('FILE_EXISTS', $filename.'.'.$extension), $hidden_vars); - $msg->printConfirm(); - - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - } else { - $msg->addError(array('EMPTY_FIELDS', _AT('file_name'))); - } -} - -$onload="on_load()"; - -require(TR_INCLUDE_PATH.'header.inc.php'); -require_once(TR_INCLUDE_PATH.'lib/tinymce.inc.php'); - -// set default body editor to tinymce editor -if (!isset($_POST['extension'])) $_POST['extension'] = 'html'; - -// load tinymce library -load_editor(true, false, "none"); - -$pathext = $_GET['pathext']; -$popup = $_GET['popup']; - -$msg->printAll(); - -?> -
    - - - -
    -
    -
    - *
    - /> -
    - -
    - *
    - onclick="trans.editor.switch_content_type(this.value);" /> - - - , onclick="trans.editor.switch_content_type(this.value);" /> - -
    - -
    -
    - -
    - -
    - - -
    -
    -
    -
    - - - - \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'_course_id='.$_course_id); + exit; +} + +if (isset($_POST['submit_no'])) { + $msg->addFeedback('CANCELLED'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'_course_id='.$_course_id); + exit; +} + +if (isset($_POST['submit_yes'])) { + $filename = preg_replace("{[^a-zA-Z0-9_]}","_", trim($_POST['filename'])); + $pathext = $_POST['pathext']; + + /* only html or txt extensions allowed */ + if ($_POST['extension'] == 'html') { + $extension = 'html'; + } else { + $extension = 'txt'; + } + + if (FileUtility::course_realpath($current_path . $pathext . $filename.'.'.$extension) == FALSE) { + $msg->addError('FILE_NOT_SAVED'); + /* take user to home page to avoid unspecified error warning */ + header('Location: index.php?pathext='.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'_course_id='.$_course_id); + exit; + } + + if (($f = @fopen($current_path.$pathext.$filename.'.'.$extension,'w')) && @fwrite($f, stripslashes($_POST['body_text'])) !== FALSE && @fclose($f)){ + $msg->addFeedback('FILE_OVERWRITE'); + } else { + $msg->addError('CANNOT_OVERWRITE_FILE'); + } + unset($_POST['newfile']); + header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'_course_id='.$_course_id); + exit; +} + +if (isset($_POST['savenewfile'])) { + + if (isset($_POST['filename']) && ($_POST['filename'] != "")) { + $filename = preg_replace("{[^a-zA-Z0-9_]}","_", trim($_POST['filename'])); + $pathext = $_POST['pathext']; + $current_path = TR_CONTENT_DIR.$_course_id.'/'; + + /* only html or txt extensions allowed */ + if ($_POST['extension'] == 'html') { + $extension = 'html'; + $head_html = "\n\n".$_POST['filename']."\n\n"; + $foot_html ="\n\n"; + } else { + $extension = 'txt'; + } + + if (!@file_exists($current_path.$pathext.$filename.'.'.$extension)) { + $content = str_replace("\r\n", "\n", $head_html.$_POST['body_text'].$foot_html); + + if (FileUtility::course_realpath($current_path . $pathext . $filename.'.'.$extension) == FALSE) { + $msg->addError('FILE_NOT_SAVED'); + /* take user to home page to avoid unspecified error warning */ + header('Location: index.php?pathext='.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'_course_id='.$_course_id); + exit; + } + + if (($f = fopen($current_path.$pathext.$filename.'.'.$extension, 'w')) && (@fwrite($f, stripslashes($content)) !== false) && (@fclose($f))) { + $msg->addFeedback(array('FILE_SAVED', $filename.'.'.$extension)); + header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'popup='.$_POST['popup'].SEP.'_course_id='.$_course_id); + exit; + } else { + $msg->addError('FILE_NOT_SAVED'); + header('Location: index.php?pathext='.$pathext.SEP.'framed='.$framed.SEP.'popup='.$popup.SEP.'_course_id='.$_course_id); + exit; + } + } + else { + require(TR_INCLUDE_PATH.'header.inc.php'); + $pathext = $_POST['pathext']; + $popup = $_POST['popup']; + + $_POST['newfile'] = "new"; + + $hidden_vars['pathext'] = $pathext; + $hidden_vars['filename'] = $filename; + $hidden_vars['extension'] = $extension; + $hidden_vars['_course_id'] = $_course_id; + $hidden_vars['body_text'] = $_POST['body_text']; + + $hidden_vars['popup'] = $popup; + $hidden_vars['framed'] = $framed; + + $msg->addConfirm(array('FILE_EXISTS', $filename.'.'.$extension), $hidden_vars); + $msg->printConfirm(); + + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + } else { + $msg->addError(array('EMPTY_FIELDS', _AT('file_name'))); + } +} + +$onload="on_load()"; + +require(TR_INCLUDE_PATH.'header.inc.php'); +require_once(TR_INCLUDE_PATH.'lib/tinymce.inc.php'); + +// set default body editor to tinymce editor +if (!isset($_POST['extension'])) $_POST['extension'] = 'html'; + +// load tinymce library +load_editor(true, false, "none"); + +$pathext = $_GET['pathext']; +$popup = $_GET['popup']; + +$msg->printAll(); + +?> +
    + + + +
    +
    +
    + *
    + /> +
    + +
    + *
    + onclick="trans.editor.switch_content_type(this.value);" /> + + + , onclick="trans.editor.switch_content_type(this.value);" /> + +
    + +
    +
    + +
    + +
    + + +
    +
    +
    +
    + + + + diff --git a/file_manager/preview.php b/file_manager/preview.php index f85986f2..e6fdcd1b 100644 --- a/file_manager/preview.php +++ b/file_manager/preview.php @@ -11,6 +11,7 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require(TR_INCLUDE_PATH.'vitals.inc.php'); global $_course_id; @@ -42,4 +43,4 @@ - \ No newline at end of file + diff --git a/file_manager/preview_top.php b/file_manager/preview_top.php index 1c586da0..bdde7843 100644 --- a/file_manager/preview_top.php +++ b/file_manager/preview_top.php @@ -11,6 +11,7 @@ /************************************************************************/ define('TR_INCLUDE_PATH', '../include/'); +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require(TR_INCLUDE_PATH.'vitals.inc.php'); global $_course_id; @@ -40,4 +41,4 @@

    - \ No newline at end of file + diff --git a/file_manager/rename.php b/file_manager/rename.php index ae403b79..33b37088 100644 --- a/file_manager/rename.php +++ b/file_manager/rename.php @@ -1,99 +1,100 @@ -addFeedback('CANCELLED'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; -} - -if (isset($_POST['rename_action'])) { - - $_POST['new_name'] = trim($_POST['new_name']); - $_POST['new_name'] = str_replace(' ', '_', $_POST['new_name']); - $_POST['new_name'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_POST['new_name']); - - $_POST['oldname'] = trim($_POST['oldname']); - $_POST['oldname'] = str_replace(' ', '_', $_POST['oldname']); - $_POST['oldname'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_POST['oldname']); - - $path_parts_new = pathinfo($_POST['new_name']); - $ext_new = $path_parts_new['extension']; - $pathext = $_POST['pathext']; - - /* check if this file extension is allowed: */ - /* $IllegalExtentions is defined in ./include/config.inc.php */ - if (in_array($ext_new, $IllegalExtentions)) { - $errors = array('FILE_ILLEGAL', $ext_new); - $msg->addError($errors); - } - else if ($current_path.$pathext.$_POST['new_name'] == $current_path.$pathext.$_POST['oldname']) { - //do nothing - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - - //make sure new file is inside content directory - else if (FileUtility::course_realpath($current_path . $pathext . $_POST['new_name']) == FALSE) { - $msg->addError('CANNOT_RENAME'); - } - else if (FileUtility::course_realpath($current_path . $pathext . $_POST['oldname']) == FALSE) { - $msg->addError('CANNOT_RENAME'); - } - else if (file_exists($current_path . $pathext . $_POST['new_name'])) { - $msg->addError('CANNOT_RENAME'); - } - else { - @rename($current_path.$pathext.$_POST['oldname'], $current_path.$pathext.$_POST['new_name']); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); - exit; - } -} - -require(TR_INCLUDE_PATH.'header.inc.php'); -?> -
    - - - - - - -
    -
    - * -
    - -
    - -
    - - -
    -
    -
    - - \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; +} + +if (isset($_POST['rename_action'])) { + + $_POST['new_name'] = trim($_POST['new_name']); + $_POST['new_name'] = str_replace(' ', '_', $_POST['new_name']); + $_POST['new_name'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_POST['new_name']); + + $_POST['oldname'] = trim($_POST['oldname']); + $_POST['oldname'] = str_replace(' ', '_', $_POST['oldname']); + $_POST['oldname'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_POST['oldname']); + + $path_parts_new = pathinfo($_POST['new_name']); + $ext_new = $path_parts_new['extension']; + $pathext = $_POST['pathext']; + + /* check if this file extension is allowed: */ + /* $IllegalExtentions is defined in ./include/config.inc.php */ + if (in_array($ext_new, $IllegalExtentions)) { + $errors = array('FILE_ILLEGAL', $ext_new); + $msg->addError($errors); + } + else if ($current_path.$pathext.$_POST['new_name'] == $current_path.$pathext.$_POST['oldname']) { + //do nothing + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + + //make sure new file is inside content directory + else if (FileUtility::course_realpath($current_path . $pathext . $_POST['new_name']) == FALSE) { + $msg->addError('CANNOT_RENAME'); + } + else if (FileUtility::course_realpath($current_path . $pathext . $_POST['oldname']) == FALSE) { + $msg->addError('CANNOT_RENAME'); + } + else if (file_exists($current_path . $pathext . $_POST['new_name'])) { + $msg->addError('CANNOT_RENAME'); + } + else { + @rename($current_path.$pathext.$_POST['oldname'], $current_path.$pathext.$_POST['new_name']); + $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); + header('Location: index.php?pathext='.urlencode($_POST['pathext']).SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'cp='.$_POST['cp'].SEP.'cid='.$_POST['cid'].SEP.'pid='.$_POST['pid'].SEP.'a_type='.$_POST['a_type'].SEP.'_course_id='.$_course_id); + exit; + } +} + +require(TR_INCLUDE_PATH.'header.inc.php'); +?> +
    + + + + + + +
    +
    + * +
    + +
    + +
    + + +
    +
    +
    + + diff --git a/file_manager/top.php b/file_manager/top.php index b2f96e68..d08b7aa0 100644 --- a/file_manager/top.php +++ b/file_manager/top.php @@ -11,6 +11,7 @@ /************************************************************************/ if (!defined('TR_INCLUDE_PATH')) { exit; } +define('TR_HTMLPurifier_PATH', '../protection/xss/htmlpurifier/library/'); require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php'); if (!$_GET['f']) { diff --git a/file_manager/upload.php b/file_manager/upload.php index 2b44f689..1579feef 100644 --- a/file_manager/upload.php +++ b/file_manager/upload.php @@ -1,176 +1,177 @@ -get($_course_id); -$my_MaxCourseSize = $row['max_quota']; -$my_MaxFileSize = $row['max_file_size']; - -if ($my_MaxCourseSize != TR_COURSESIZE_UNLIMITED) $my_MaxCourseSize = $MaxCourseSize; -$my_MaxFileSize = FileUtility::megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1)); - -// if ($my_MaxCourseSize == TR_COURSESIZE_DEFAULT) { -// $my_MaxCourseSize = $MaxCourseSize; -// } -// if ($my_MaxFileSize == TR_FILESIZE_DEFAULT) { -// $my_MaxFileSize = $MaxFileSize; -// } else if ($my_MaxFileSize == TR_FILESIZE_SYSTEM_MAX) { -// $my_MaxFileSize = megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1)); -// } - -$path = TR_CONTENT_DIR . $_course_id.'/'.$_POST['pathext']; - -if (isset($_POST['submit'])) { - if($_FILES['file']) { - $_FILES['uploadedfile'] = $_FILES['file']; - } - if($_FILES['uploadedfile']['name']) { - $_FILES['uploadedfile']['name'] = trim($_FILES['uploadedfile']['name']); - $_FILES['uploadedfile']['name'] = str_replace(' ', '_', $_FILES['uploadedfile']['name']); - - $path_parts = pathinfo($_FILES['uploadedfile']['name']); - $ext = $path_parts['extension']; - /* check if this file extension is allowed: */ - /* $IllegalExtentions is defined in ./include/config.inc.php */ - if (in_array($ext, $IllegalExtentions)) { - $errors = array('FILE_ILLEGAL', $ext); - $msg->addError($errors); - FileUtility::handleAjaxUpload(500); - header('Location: index.php?pathext='.$_POST['pathext'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - exit; - } - - /* also have to handle the 'application/x-zip-compressed' case */ - if ( ($_FILES['uploadedfile']['type'] == 'application/x-zip-compressed') - || ($_FILES['uploadedfile']['type'] == 'application/zip') - || ($_FILES['uploadedfile']['type'] == 'application/x-zip')){ - $is_zip = true; - } - - - /* anything else should be okay, since we're on *nix.. hopefully */ - $_FILES['uploadedfile']['name'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_FILES['uploadedfile']['name']); - - /* if the file size is within allowed limits */ - if( ($_FILES['uploadedfile']['size'] > 0) && ($_FILES['uploadedfile']['size'] <= $my_MaxFileSize) ) { - - /* if adding the file will not exceed the maximum allowed total */ - $course_total = FileUtility::dirsize($path); - - if ((($course_total + $_FILES['uploadedfile']['size']) <= $my_MaxCourseSize) || ($my_MaxCourseSize == TR_COURSESIZE_UNLIMITED)) { - - /* check if this file exists first */ - if (file_exists($path.$_FILES['uploadedfile']['name'])) { - /* this file already exists, so we want to prompt for override */ - - /* save it somewhere else, temporarily first */ - /* file_name.time ? */ - $_FILES['uploadedfile']['name'] = substr(time(), -4).'.'.$_FILES['uploadedfile']['name']; - - $f = array('FILE_EXISTS', - substr($_FILES['uploadedfile']['name'], 5), - $_FILES['uploadedfile']['name']); - $msg->addFeedback($f); - } - - /* copy the file in the directory */ - $result = move_uploaded_file( $_FILES['uploadedfile']['tmp_name'], $path.$_FILES['uploadedfile']['name'] ); - - if (!$result) { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('FILE_NOT_SAVED'); - echo '' . _AT('back') . ''; - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } else { - if ($is_zip) { - $f = array('FILE_UPLOADED_ZIP', - urlencode($_POST['pathext']), - urlencode($_FILES['uploadedfile']['name']), - $_GET['popup'], - $_course_id, - SEP); - $msg->addFeedback($f); - FileUtility::handleAjaxUpload(200); - if ($alter) - header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); - else - header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - exit; - } /* else */ - - // uploading an alternative content object - if ($_GET['a_type'] > 0) { - header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'uploadfile='.urlencode($_FILES['uploadedfile']['name']).SEP.'_course_id='.$_course_id); - } - else { - $msg->addFeedback('FILE_UPLOADED'); - FileUtility::handleAjaxUpload(200); - - if ($alter) - header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); - else - header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - } - exit; - } - } else { - $msg->addError(array('MAX_STORAGE_EXCEEDED', get_human_size($my_MaxCourseSize))); - FileUtility::handleAjaxUpload(500); - if ($alter) - header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); - else - header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - - exit; - } - } else { - $msg->addError(array('FILE_TOO_BIG', get_human_size($my_MaxFileSize))); - FileUtility::handleAjaxUpload(500); - if ($alter) - header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); - else - header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - - exit; - } - } else { - $msg->addError('FILE_NOT_SELECTED'); - FileUtility::handleAjaxUpload(500); - if ($alter) - header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); - else - header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); - exit; - } -} - -?> \ No newline at end of file +get($_course_id); +$my_MaxCourseSize = $row['max_quota']; +$my_MaxFileSize = $row['max_file_size']; + +if ($my_MaxCourseSize != TR_COURSESIZE_UNLIMITED) $my_MaxCourseSize = $MaxCourseSize; +$my_MaxFileSize = FileUtility::megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1)); + +// if ($my_MaxCourseSize == TR_COURSESIZE_DEFAULT) { +// $my_MaxCourseSize = $MaxCourseSize; +// } +// if ($my_MaxFileSize == TR_FILESIZE_DEFAULT) { +// $my_MaxFileSize = $MaxFileSize; +// } else if ($my_MaxFileSize == TR_FILESIZE_SYSTEM_MAX) { +// $my_MaxFileSize = megabytes_to_bytes(substr(ini_get('upload_max_filesize'), 0, -1)); +// } + +$path = TR_CONTENT_DIR . $_course_id.'/'.$_POST['pathext']; + +if (isset($_POST['submit'])) { + if($_FILES['file']) { + $_FILES['uploadedfile'] = $_FILES['file']; + } + if($_FILES['uploadedfile']['name']) { + $_FILES['uploadedfile']['name'] = trim($_FILES['uploadedfile']['name']); + $_FILES['uploadedfile']['name'] = str_replace(' ', '_', $_FILES['uploadedfile']['name']); + + $path_parts = pathinfo($_FILES['uploadedfile']['name']); + $ext = $path_parts['extension']; + /* check if this file extension is allowed: */ + /* $IllegalExtentions is defined in ./include/config.inc.php */ + if (in_array($ext, $IllegalExtentions)) { + $errors = array('FILE_ILLEGAL', $ext); + $msg->addError($errors); + FileUtility::handleAjaxUpload(500); + header('Location: index.php?pathext='.$_POST['pathext'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + exit; + } + + /* also have to handle the 'application/x-zip-compressed' case */ + if ( ($_FILES['uploadedfile']['type'] == 'application/x-zip-compressed') + || ($_FILES['uploadedfile']['type'] == 'application/zip') + || ($_FILES['uploadedfile']['type'] == 'application/x-zip')){ + $is_zip = true; + } + + + /* anything else should be okay, since we're on *nix.. hopefully */ + $_FILES['uploadedfile']['name'] = str_replace(array(' ', '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\''), '', $_FILES['uploadedfile']['name']); + + /* if the file size is within allowed limits */ + if( ($_FILES['uploadedfile']['size'] > 0) && ($_FILES['uploadedfile']['size'] <= $my_MaxFileSize) ) { + + /* if adding the file will not exceed the maximum allowed total */ + $course_total = FileUtility::dirsize($path); + + if ((($course_total + $_FILES['uploadedfile']['size']) <= $my_MaxCourseSize) || ($my_MaxCourseSize == TR_COURSESIZE_UNLIMITED)) { + + /* check if this file exists first */ + if (file_exists($path.$_FILES['uploadedfile']['name'])) { + /* this file already exists, so we want to prompt for override */ + + /* save it somewhere else, temporarily first */ + /* file_name.time ? */ + $_FILES['uploadedfile']['name'] = substr(time(), -4).'.'.$_FILES['uploadedfile']['name']; + + $f = array('FILE_EXISTS', + substr($_FILES['uploadedfile']['name'], 5), + $_FILES['uploadedfile']['name']); + $msg->addFeedback($f); + } + + /* copy the file in the directory */ + $result = move_uploaded_file( $_FILES['uploadedfile']['tmp_name'], $path.$_FILES['uploadedfile']['name'] ); + + if (!$result) { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('FILE_NOT_SAVED'); + echo '' . _AT('back') . ''; + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } else { + if ($is_zip) { + $f = array('FILE_UPLOADED_ZIP', + urlencode($_POST['pathext']), + urlencode($_FILES['uploadedfile']['name']), + $_GET['popup'], + $_course_id, + SEP); + $msg->addFeedback($f); + FileUtility::handleAjaxUpload(200); + if ($alter) + header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); + else + header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + exit; + } /* else */ + + // uploading an alternative content object + if ($_GET['a_type'] > 0) { + header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'uploadfile='.urlencode($_FILES['uploadedfile']['name']).SEP.'_course_id='.$_course_id); + } + else { + $msg->addFeedback('FILE_UPLOADED'); + FileUtility::handleAjaxUpload(200); + + if ($alter) + header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); + else + header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + } + exit; + } + } else { + $msg->addError(array('MAX_STORAGE_EXCEEDED', get_human_size($my_MaxCourseSize))); + FileUtility::handleAjaxUpload(500); + if ($alter) + header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); + else + header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + + exit; + } + } else { + $msg->addError(array('FILE_TOO_BIG', get_human_size($my_MaxFileSize))); + FileUtility::handleAjaxUpload(500); + if ($alter) + header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); + else + header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + + exit; + } + } else { + $msg->addError('FILE_NOT_SELECTED'); + FileUtility::handleAjaxUpload(500); + if ($alter) + header('Location: '.$_base_href.'editor/edit_content.php?cid='.$_REQUEST['cid'].SEP . 'pathext='.$_POST['pathext'].SEP. 'popup='.$_GET['popup'].SEP. 'tab='.$_REQUEST['tab'].SEP.'_course_id='.$_course_id); + else + header('Location: index.php?pathext=' . $_POST['pathext'] . SEP . 'popup=' . $_GET['popup'].SEP. 'framed='.$framed.SEP.'cp='.$_GET['cp'].SEP.'pid='.$_GET['pid'].SEP.'cid='.$_GET['cid'].SEP.'a_type='.$_GET['a_type'].SEP.'_course_id='.$_course_id); + exit; + } +} + +?> diff --git a/file_manager/zip.php b/file_manager/zip.php index a4246543..29b93a11 100644 --- a/file_manager/zip.php +++ b/file_manager/zip.php @@ -1,290 +1,291 @@ -addFeedback('CANCELLED'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_POST['popup'].SEP.'framed='.$_POST['framed'].SEP.'_course_id='.$_course_id); - exit; -} - - $path = TR_CONTENT_DIR . $_course_id.'/'; - - if ($_REQUEST['pathext'] != '') { - $pathext = $_REQUEST['pathext']; - } - if ($_REQUEST['file'] != '') { - $file = $_REQUEST['file']; - } - - if (strpos($file, '..') !== false) { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('UNKNOWN'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - $path_parts = pathinfo($pathext.$file); - - $temp_name = substr($file, 0, -strlen('.'.$path_parts['extension'])); - - $zip = new PclZip($path.$pathext.$file); - - if (($list = $zip->listContent()) == 0) { - die("Error : ".$zip->errorInfo(true)); - } - -/*****************************************************************/ - $totalBytes = 0; - $translated_file_names = array(); - - for ($i=0; $i'; - - $is_dir = true; - - } else if ($ext == 'zip') { - - $totalBytes += $list[$i]['size']; - $filename = $list[$i]['stored_filename']; - $fileicon = ''._AT('zip_archive').''; - - } else { - $totalBytes += $list[$i]['size']; - $filename = $list[$i]['stored_filename']; - $fileicon = ''._AT('file').''; - } - - if ($is_dir) { - $dirs[strtolower($filename)] .= ' - '.$filename.''; - - $dirs[strtolower($filename)] .= ''.FileUtility::get_human_size($list[$i]['size']).' '; - $dirs[strtolower($filename)] .= ' '; - - $dirs[strtolower($filename)] .= AT_date(_AT('filemanager_date_format'), $filedata[10], TR_DATE_UNIX_TIMESTAMP); - - $dirs[strtolower($filename)] .= ' '; - - $dirs[strtolower($filename)] .= ''; - } else { - - $files[strtolower($filename)] .= ' - '; - - if (in_array($ext, $IllegalExtentions)) { - $files[strtolower($filename)] .= ''.$filename.''; - } else { - $files[strtolower($filename)] .= $filename; - - $trans_name = str_replace(' ', '_', $path_parts['basename']); - $trans_name = preg_replace("/[^A-Za-z0-9._\-]/", '', $trans_name); - - if (in_array($path_parts['dirname'].$trans_name, $translated_file_names)) { - $trans_count = 2; - while (in_array($trans_name, $translated_file_names)) { - $part = substr($trans_name, 0, -strlen($ext)- 1 - (2*($trans_count-2))); - $trans_name = $part.'_'.$trans_count.'.'.$ext; - $trans_count++; - if ($trans_count>15){ - exit; // INF loop safety thing.. - } - } - } - - $translated_file_names[$list[$i]['index']] = $path_parts['dirname'].$trans_name; - - if ($path_parts['dirname'].$trans_name != $filename) { - $files[strtolower($filename)] .= ' => '.$trans_name; - } - - } - - $files[strtolower($filename)] .= ''; - - $files[strtolower($filename)] .= ''.FileUtility::get_human_size($list[$i]['size']).' '; - $files[strtolower($filename)] .= ' '; - - $files[strtolower($filename)] .= AT_date(_AT('filemanager_date_format'), $list[$i]['mtime'], TR_DATE_UNIX_TIMESTAMP); - - $files[strtolower($filename)] .= ''; - - $files[strtolower($filename)] .= ''; - } - } - - $row = $coursesDAO->get($_course_id); - $my_MaxCourseSize = $row['max_quota']; - $my_MaxFileSize = $row['max_file_size']; - - $course_total = FileUtility::dirsize($path); - if ($my_MaxCourseSize == TR_COURSESIZE_UNLIMITED) { - $total_after = 1; - } else { - $my_MaxCourseSize = $MaxCourseSize; - $total_after = FileUtility::get_human_size($my_MaxCourseSize-$course_total-$totalBytes); - } -// else{ -// $total_after = get_human_size($my_MaxCourseSize - $course_total - $totalBytes); -// } - - // if $total_after < 0: redirect with error msg - - if (isset($_POST['submit']) && ($total_after > 0)) { - $_POST['custom_path'] = trim($_POST['custom_path']); - $_POST['custom_path'] = str_replace(' ', '_', $_POST['custom_path']); - - /* anything else should be okay, since we're on *nix.. hopefully */ - $_POST['custom_path'] = preg_replace('/[^a-zA-Z0-9._\/]/', '', $_POST['custom_path']); - - if (strpos($_POST['pathext'].$_POST['custom_path'], '..') !== false) { - $msg->addError('UNKNOWN'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'_course_id='.$_course_id); - exit; - } else if ($zip->extract( PCLZIP_OPT_PATH, $path. $_POST['pathext'] . $_POST['custom_path'], - PCLZIP_CB_PRE_EXTRACT, 'preExtractCallBack') == 0) { - - echo ("Error : ".$zip->errorInfo(true)); - } else { - $msg->addFeedback('ARCHIVE_EXTRACTED'); - header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_POST['popup'].SEP.'framed='.$_POST['framed'].SEP.'_course_id='.$_course_id); - exit; - } - - header('Location: index.php'.SEP.'_course_id='.$_course_id); - exit; - } - - require(TR_INCLUDE_PATH.'header.inc.php'); - - if ($total_after <= 0) { - $msg->printErrors('NO_SPACE_LEFT'); - } else { -?> -
    - - - - - -
    -
    -

    -

    -
    - -
    - *
    - -
    - -
    - - -
    -
    -
    - - - - - - - - - - - - $y) { - echo $y; - } - } - - if (is_array($files)) { - foreach($files as $x => $y) { - echo $y; - } - } -?> - - - - - - - - - - - - - - - - - - - - - - - -
    : 
    : 
    : 
    :'; - echo $total_after; - echo ''; - } else { - echo $total_after; - } - } ?> 
    - - \ No newline at end of file +addFeedback('CANCELLED'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_POST['popup'].SEP.'framed='.$_POST['framed'].SEP.'_course_id='.$_course_id); + exit; +} + + $path = TR_CONTENT_DIR . $_course_id.'/'; + + if ($_REQUEST['pathext'] != '') { + $pathext = $_REQUEST['pathext']; + } + if ($_REQUEST['file'] != '') { + $file = $_REQUEST['file']; + } + + if (strpos($file, '..') !== false) { + require(TR_INCLUDE_PATH.'header.inc.php'); + $msg->printErrors('UNKNOWN'); + require(TR_INCLUDE_PATH.'footer.inc.php'); + exit; + } + + $path_parts = pathinfo($pathext.$file); + + $temp_name = substr($file, 0, -strlen('.'.$path_parts['extension'])); + + $zip = new PclZip($path.$pathext.$file); + + if (($list = $zip->listContent()) == 0) { + die("Error : ".$zip->errorInfo(true)); + } + +/*****************************************************************/ + $totalBytes = 0; + $translated_file_names = array(); + + for ($i=0; $i'; + + $is_dir = true; + + } else if ($ext == 'zip') { + + $totalBytes += $list[$i]['size']; + $filename = $list[$i]['stored_filename']; + $fileicon = ''._AT('zip_archive').''; + + } else { + $totalBytes += $list[$i]['size']; + $filename = $list[$i]['stored_filename']; + $fileicon = ''._AT('file').''; + } + + if ($is_dir) { + $dirs[strtolower($filename)] .= ' + '.$filename.''; + + $dirs[strtolower($filename)] .= ''.FileUtility::get_human_size($list[$i]['size']).' '; + $dirs[strtolower($filename)] .= ' '; + + $dirs[strtolower($filename)] .= AT_date(_AT('filemanager_date_format'), $filedata[10], TR_DATE_UNIX_TIMESTAMP); + + $dirs[strtolower($filename)] .= ' '; + + $dirs[strtolower($filename)] .= ''; + } else { + + $files[strtolower($filename)] .= ' + '; + + if (in_array($ext, $IllegalExtentions)) { + $files[strtolower($filename)] .= ''.$filename.''; + } else { + $files[strtolower($filename)] .= $filename; + + $trans_name = str_replace(' ', '_', $path_parts['basename']); + $trans_name = preg_replace("/[^A-Za-z0-9._\-]/", '', $trans_name); + + if (in_array($path_parts['dirname'].$trans_name, $translated_file_names)) { + $trans_count = 2; + while (in_array($trans_name, $translated_file_names)) { + $part = substr($trans_name, 0, -strlen($ext)- 1 - (2*($trans_count-2))); + $trans_name = $part.'_'.$trans_count.'.'.$ext; + $trans_count++; + if ($trans_count>15){ + exit; // INF loop safety thing.. + } + } + } + + $translated_file_names[$list[$i]['index']] = $path_parts['dirname'].$trans_name; + + if ($path_parts['dirname'].$trans_name != $filename) { + $files[strtolower($filename)] .= ' => '.$trans_name; + } + + } + + $files[strtolower($filename)] .= ''; + + $files[strtolower($filename)] .= ''.FileUtility::get_human_size($list[$i]['size']).' '; + $files[strtolower($filename)] .= ' '; + + $files[strtolower($filename)] .= AT_date(_AT('filemanager_date_format'), $list[$i]['mtime'], TR_DATE_UNIX_TIMESTAMP); + + $files[strtolower($filename)] .= ''; + + $files[strtolower($filename)] .= ''; + } + } + + $row = $coursesDAO->get($_course_id); + $my_MaxCourseSize = $row['max_quota']; + $my_MaxFileSize = $row['max_file_size']; + + $course_total = FileUtility::dirsize($path); + if ($my_MaxCourseSize == TR_COURSESIZE_UNLIMITED) { + $total_after = 1; + } else { + $my_MaxCourseSize = $MaxCourseSize; + $total_after = FileUtility::get_human_size($my_MaxCourseSize-$course_total-$totalBytes); + } +// else{ +// $total_after = get_human_size($my_MaxCourseSize - $course_total - $totalBytes); +// } + + // if $total_after < 0: redirect with error msg + + if (isset($_POST['submit']) && ($total_after > 0)) { + $_POST['custom_path'] = trim($_POST['custom_path']); + $_POST['custom_path'] = str_replace(' ', '_', $_POST['custom_path']); + + /* anything else should be okay, since we're on *nix.. hopefully */ + $_POST['custom_path'] = preg_replace('/[^a-zA-Z0-9._\/]/', '', $_POST['custom_path']); + + if (strpos($_POST['pathext'].$_POST['custom_path'], '..') !== false) { + $msg->addError('UNKNOWN'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'framed='.$_POST['framed'].SEP.'popup='.$_POST['popup'].SEP.'_course_id='.$_course_id); + exit; + } else if ($zip->extract( PCLZIP_OPT_PATH, $path. $_POST['pathext'] . $_POST['custom_path'], + PCLZIP_CB_PRE_EXTRACT, 'preExtractCallBack') == 0) { + + echo ("Error : ".$zip->errorInfo(true)); + } else { + $msg->addFeedback('ARCHIVE_EXTRACTED'); + header('Location: index.php?pathext='.$_POST['pathext'].SEP.'popup='.$_POST['popup'].SEP.'framed='.$_POST['framed'].SEP.'_course_id='.$_course_id); + exit; + } + + header('Location: index.php'.SEP.'_course_id='.$_course_id); + exit; + } + + require(TR_INCLUDE_PATH.'header.inc.php'); + + if ($total_after <= 0) { + $msg->printErrors('NO_SPACE_LEFT'); + } else { +?> +
    + + + + + +
    +
    +

    +

    +
    + +
    + *
    + +
    + +
    + + +
    +
    +
    + + + + + + + + + + + + $y) { + echo $y; + } + } + + if (is_array($files)) { + foreach($files as $x => $y) { + echo $y; + } + } +?> + + + + + + + + + + + + + + + + + + + + + + + +
    : 
    : 
    : 
    :'; + echo $total_after; + echo ''; + } else { + echo $total_after; + } + } ?> 
    + + From c8346af257720238ad94617ede8edfd1219dc2ea Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 11:00:39 +0700 Subject: [PATCH 61/94] Change Token to CSRF_Token --- themes/default/profile/change_email.tmpl.php | 4 ++-- .../default/profile/change_password.tmpl.php | 2 +- themes/default/profile/index.tmpl.php | 22 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/themes/default/profile/change_email.tmpl.php b/themes/default/profile/change_email.tmpl.php index 8fe54796..b385ecd9 100644 --- a/themes/default/profile/change_email.tmpl.php +++ b/themes/default/profile/change_email.tmpl.php @@ -57,14 +57,14 @@ function encrypt_password() - +

    -
    +

    diff --git a/themes/default/profile/change_password.tmpl.php b/themes/default/profile/change_password.tmpl.php index 2f6ca5a2..8a1af07f 100644 --- a/themes/default/profile/change_password.tmpl.php +++ b/themes/default/profile/change_password.tmpl.php @@ -100,7 +100,7 @@ function encrypt_password()

    -
    +

    diff --git a/themes/default/profile/index.tmpl.php b/themes/default/profile/index.tmpl.php index 8d47ea0f..d65222d6 100644 --- a/themes/default/profile/index.tmpl.php +++ b/themes/default/profile/index.tmpl.php @@ -58,17 +58,17 @@ *: - + *: - + - onclick="if (this.checked) jQuery('#table_is_author').show('slow'); else jQuery('#table_is_author').hide('slow');" /> + onclick="if (this.checked) jQuery('#table_is_author').show('slow'); else jQuery('#table_is_author').hide('slow');" /> @@ -78,37 +78,37 @@ - + - + - + - + - + - + - +
    :
    :
    :
    :
    :
    :
    :
    @@ -119,7 +119,7 @@

    -
    +

    From 678ef3332eb32281434deedc52b4a1224dddfb54 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 11:02:10 +0700 Subject: [PATCH 62/94] Delete change_email.php --- themes/default/profile/change_email.php | 135 ------------------------ 1 file changed, 135 deletions(-) delete mode 100644 themes/default/profile/change_email.php diff --git a/themes/default/profile/change_email.php b/themes/default/profile/change_email.php deleted file mode 100644 index 20d7f3d9..00000000 --- a/themes/default/profile/change_email.php +++ /dev/null @@ -1,135 +0,0 @@ -printInfos('INVALID_USER'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (isset($_POST['cancel'])) -{ - $msg->addFeedback('CANCELLED'); - Header('Location: ../index.php'); - exit; -} - -if (isset($_POST['submit'])) -{ - if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) - { - $this_password = $_POST['form_password_hidden']; - - // password check - if (!empty($this_password)) - { - //check if old password entered is correct - if ($row = $_current_user->getInfo()) - { - if ($row['password'] != $this_password) - { - $msg->addError('WRONG_PASSWORD'); - Header('Location: change_email.php'); - exit; - } - } - } - else - { - $msg->addError(array('EMPTY_FIELDS', _AT('password'))); - header('Location: change_email.php'); - exit; - } - - // email check - if ($_POST['email'] == '') - { - $msg->addError(array('EMPTY_FIELDS', _AT('email'))); - } - else - { - if(!preg_match("/^[a-z0-9\._-]+@+[a-z0-9\._-]+\.+[a-z]{2,6}$/i", $_POST['email'])) - { - $msg->addError('EMAIL_INVALID'); - } - - $usersDAO = new UsersDAO(); - $row = $usersDAO->getUserByEmail($_POST['email']); - if ($row['user_id'] > 0 && $row['user_id'] <> $_SESSION['user_id']) - { - $msg->addError('EMAIL_EXISTS'); - } - } - - if (!$msg->containsErrors()) - { - - if (defined('TR_EMAIL_CONFIRMATION') && TR_EMAIL_CONFIRMATION) - { - //send confirmation email - $row = $_current_user->getInfo(); - - if ($row['email'] != $_POST['email']) { - $code = substr(md5($_POST['email'] . $row['creation_date'] . $_SESSION['user_id']), 0, 10); - $confirmation_link = TR_BASE_HREF . 'confirm.php?id='.$_SESSION['user_id'].SEP .'e='.urlencode($_POST['email']).SEP.'m='.$code; - - /* send the email confirmation message: */ - require(TR_INCLUDE_PATH . 'classes/phpmailer/transformablemailer.class.php'); - $mail = new TransformableMailer(); - - $mail->From = $_config['contact_email']; - $mail->AddAddress($_POST['email']); - $mail->Subject = SITE_NAME . ' - ' . _AT('email_confirmation_subject'); - $mail->Body = _AT('email_confirmation_message2', $_config['site_name'], $confirmation_link); - - $mail->Send(); - - $msg->addFeedback('CONFIRM_EMAIL'); - } else { - $msg->addFeedback('CHANGE_TO_SAME_EMAIL'); - } - } else { - - //insert into database - $_current_user->setEmail($_POST[email]); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - } - } - } else - { - $msg->addError('INVALID_TOKEN'); - } -} - -$row = $_current_user->getInfo(); - -if (!isset($_POST['submit'])) { - $_POST = $row; -} - -/* template starts here */ -$savant->assign('row', $row); -$savant->display('profile/change_email.tmpl.php'); - -?> From e1b6983ca0bfb43f97b7ec3bc47dc2001c29ecc2 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 11:02:23 +0700 Subject: [PATCH 63/94] Delete index.php --- themes/default/profile/index.php | 84 -------------------------------- 1 file changed, 84 deletions(-) delete mode 100644 themes/default/profile/index.php diff --git a/themes/default/profile/index.php b/themes/default/profile/index.php deleted file mode 100644 index e65481fb..00000000 --- a/themes/default/profile/index.php +++ /dev/null @@ -1,84 +0,0 @@ -printInfos('INVALID_USER'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - Header('Location: ../index.php'); - exit; -} - -if (isset($_POST['submit'])) { - if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) - { - if (isset($_POST['is_author'])) $is_author = 1; - else $is_author = 0; - - $usersDAO = new UsersDAO(); - $user_row = $usersDAO->getUserByID($_SESSION['user_id']); - - if ($usersDAO->Update($_SESSION['user_id'], - $user_row['user_group_id'], - $user_row['login'], - $user_row['email'], - $_POST['first_name'], - $_POST['last_name'], - $is_author, - $_POST['organization'], - $_POST['phone'], - $_POST['address'], - $_POST['city'], - $_POST['province'], - $_POST['country'], - $_POST['postal_code'], - $_POST['status'])) - - { - $msg->addFeedback('PROFILE_UPDATED'); - } - } else - { - $msg->addError('INVALID_TOKEN'); - } -} - -$row = $_current_user->getInfo(); - -if (!isset($_POST['submit'])) { - $_POST = $row; -} - -/* template starts here */ -$savant->assign('row', $row); - -global $onload; -$onload = 'document.form.first_name.focus();'; - -$savant->display('profile/index.tmpl.php'); -?> From fd3ac508c3e65992c781a87a91400ffd7f2c7d2c Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 11:02:39 +0700 Subject: [PATCH 64/94] Delete change_password.php --- themes/default/profile/change_password.php | 96 ---------------------- 1 file changed, 96 deletions(-) delete mode 100644 themes/default/profile/change_password.php diff --git a/themes/default/profile/change_password.php b/themes/default/profile/change_password.php deleted file mode 100644 index bf65ecd5..00000000 --- a/themes/default/profile/change_password.php +++ /dev/null @@ -1,96 +0,0 @@ -printInfos('INVALID_USER'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - Header('Location: ../index.php'); - exit; -} - -if (isset($_POST['submit'])) { - if (CSRF_Token::isValid() AND CSRF_Token::isRecent()) - { - if (!empty($_POST['form_old_password_hidden'])) - { - //check if old password entered is correct - if ($row = $_current_user->getInfo()) - { - if ($row['password'] != $purifier->purify($_POST['form_old_password_hidden'])) - { - $msg->addError('WRONG_PASSWORD'); - Header('Location: change_password.php'); - exit; - } - } - } - else - { - $msg->addError(array('EMPTY_FIELDS', _AT('password'))); - header('Location: change_password.php'); - exit; - } - - /* password check: password is verified front end by javascript. here is to handle the errors from javascript */ - if ($_POST['password_error'] <> "") - { - $pwd_errors = explode(",", $_POST['password_error']); - - foreach ($pwd_errors as $pwd_error) - { - if ($pwd_error == "missing_password") - $missing_fields[] = _AT('password'); - else - $msg->addError($pwd_error); - } - } - - if (!$msg->containsErrors()) { - - // insert into the db. - $password = $purifier->purify($_POST['form_password_hidden']); - - if (!$_current_user->setPassword($password)) - { - require(TR_INCLUDE_PATH.'header.inc.php'); - $msg->printErrors('DB_NOT_UPDATED'); - require(TR_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - $msg->addFeedback('PASSWORD_CHANGED'); - } - } else - { - $msg->addError('INVALID_TOKEN'); - } -} - -/* template starts here */ -$savant->display('profile/change_password.tmpl.php'); - -?> From 005339f3f7e084ca5aa2da1ad0cded4aab6ae7c3 Mon Sep 17 00:00:00 2001 From: Metamorfosec <33624021+metamorfosec@users.noreply.github.com> Date: Mon, 17 Sep 2018 13:24:23 +0700 Subject: [PATCH 65/94] add ' ' to unibo --- templates/system/Layout.class.php | 928 +++++++++++++++--------------- 1 file changed, 464 insertions(+), 464 deletions(-) diff --git a/templates/system/Layout.class.php b/templates/system/Layout.class.php index 9b889e07..451aadf8 100755 --- a/templates/system/Layout.class.php +++ b/templates/system/Layout.class.php @@ -1,464 +1,464 @@ -content_id = (isset($_REQUEST['cid']) ? intval($_REQUEST['cid']) : $_content_id); - $this->course_id = (isset($_REQUEST['course_id']) ? intval($_REQUEST['course_id']) : $_course_id); - - if(isset($_POST['apply_layout_to_course'])) - $this->applyLayoutToCourse(); - elseif(isset($_POST['apply_layout_to_content'])) - $this->applyLayoutToContent(); - - $this->mod_path = $mod_path; - - if($this->mod_path != '') - $this->config = parse_ini_file($this->mod_path['syspath'].'config.ini'); - - return; - } - - /* - * Open the configuration file reading the parameters - * input: none - * output: none - * - * */ - - public function getConfig(){ - return $this->config; - } - - /* - * Read loaded layout creating a list of available layout - * input: none - * output: none - * - * */ - - public function getLayoutList(){ - - $layout_list = array(); - $dir = array(); - - // read the list of available layout - $dir = scandir($this->mod_path['layout_dir_int']); - - // subtract files to be excluded from the list of available layout - $dir = array_diff($dir, $this->except); - // call the function that validates the available layout - $layout_list = $this->validated_layout($dir); - - return $layout_list; - } - - /* - * The following function reads from the filesystem existing layout and validates them - * according to pre-set criteria (eg comparison between version of the layout and core) - * and returns an array of available and valid layout. - * input: $dir[] list of available layout - * output: list of available layout skimmed according to the compatibility of each layout - * - * */ - - private function validated_layout($dir = array()){ - - // scan all existing layout - $layouts = array(); - - foreach($dir as $item){ - - $isdir = $this->mod_path['layout_dir_int'].$item; - - // checking if the element is a directory - if(is_dir($isdir)){ - - // check if exists the .info file and parse it - - $xml_file = $isdir.'/layouts.xml'; - if(is_file($xml_file)) { - $xml = simplexml_load_file($xml_file); - - foreach($xml->children() as $child) { - $name = $child->getName(); - if($name == "release") { - $info['core'] = $child->version; - - } - $info[$name] = $child; - } - - // if you did not specify a name, use the folder name - if(!$info['name']) - $info['name'] = $item; - - // check the "core" - if(!$info['core']) - continue; - else { - - $vfile = explode('.', $info['core']); - $vcore = explode('.', VERSION); - - // cursory check for version compatibility - // stopping the cycle to the first incompatibility found - if($vfile[0] < $vcore[0]) - // not compatible! - continue; - elseif(strtolower($vfile[1]) != 'x' and $vfile[1] < $vcore[1]) - // not compatible! - continue; - } - - // put the info of the current layout into an array - $layouts[$item] = $info; - - } - } - } - - return $layouts; - } - - /* - * The following function provides for the generation of a form - * to graphically show the user the list of available layout. - * The form is returned by the function and, then, - * integrated the output of this module. - * input: $layout_list[] list of available layout - * output: none - * */ - - public function createUI($layout_list,$_content_id){ - $IDcontent=$_content_id; - - $ui = ''; - $ui .= '