diff options
86 files changed, 1086 insertions, 416 deletions
diff --git a/actions/friends/collections/add.php b/actions/friends/collections/add.php index 1e2bc1d5c..9dc17b37e 100644 --- a/actions/friends/collections/add.php +++ b/actions/friends/collections/add.php @@ -20,8 +20,7 @@ if ($id) { $result = update_access_collection($id, $friends); if ($result) { system_message(elgg_echo("friends:collectionadded")); - // go to the collections page - forward("pg/collections/" . get_loggedin_user()->username); + forward("collections/" . elgg_get_logged_in_user_entity()->username); } else { register_error(elgg_echo("friends:nocollectionname")); forward(REFERER); diff --git a/engine/classes/ElggGroup.php b/engine/classes/ElggGroup.php index f7f67bf41..121186196 100644 --- a/engine/classes/ElggGroup.php +++ b/engine/classes/ElggGroup.php @@ -16,8 +16,6 @@ class ElggGroup extends ElggEntity * Sets the type to group. * * @return void - * - * @deprecated 1.8 Use initializeAttributes */ protected function initializeAttributes() { parent::initializeAttributes(); diff --git a/engine/classes/ElggMemcache.php b/engine/classes/ElggMemcache.php index f27b017d0..d9539b9cb 100644 --- a/engine/classes/ElggMemcache.php +++ b/engine/classes/ElggMemcache.php @@ -40,7 +40,7 @@ class ElggMemcache extends ElggSharedMemoryCache { // Do we have memcache? if (!class_exists('Memcache')) { - throw new ConfigurationException(elgg_echo('memcache:notinstalled')); + throw new ConfigurationException('PHP memcache module not installed, you must install php5-memcache'); } // Create memcache object @@ -48,7 +48,7 @@ class ElggMemcache extends ElggSharedMemoryCache { // Now add servers if (!$CONFIG->memcache_servers) { - throw new ConfigurationException(elgg_echo('memcache:noservers')); + throw new ConfigurationException('No memcache servers defined, please populate the $CONFIG->memcache_servers variable'); } if (is_callable(array($this->memcache, 'addServer'))) { @@ -85,7 +85,7 @@ class ElggMemcache extends ElggSharedMemoryCache { // Get version $this->version = $this->memcache->getVersion(); if (version_compare($this->version, ElggMemcache::$MINSERVERVERSION, '<')) { - $msg = elgg_echo('memcache:versiontoolow', + $msg = vsprintf('Memcache needs at least version %s to run, you are running %s', array(ElggMemcache::$MINSERVERVERSION, $this->version )); diff --git a/engine/classes/ElggSite.php b/engine/classes/ElggSite.php index e793ab9c6..401939005 100644 --- a/engine/classes/ElggSite.php +++ b/engine/classes/ElggSite.php @@ -381,14 +381,24 @@ class ElggSite extends ElggEntity { public function checkWalledGarden() { global $CONFIG; - if ($CONFIG->walled_garden && !elgg_is_logged_in()) { - // hook into the index system call at the highest priority - elgg_register_plugin_hook_handler('index', 'system', 'elgg_walled_garden_index', 1); - - if (!$this->isPublicPage()) { - $_SESSION['last_forward_from'] = current_page_url(); - register_error(elgg_echo('loggedinrequired')); - forward(); + if ($CONFIG->walled_garden) { + if ($CONFIG->default_access == ACCESS_PUBLIC) { + $CONFIG->default_access = ACCESS_LOGGED_IN; + } + elgg_register_plugin_hook_handler( + 'access:collections:write', + 'user', + '_elgg_walled_garden_remove_public_access'); + + if (!elgg_is_logged_in()) { + // hook into the index system call at the highest priority + elgg_register_plugin_hook_handler('index', 'system', 'elgg_walled_garden_index', 1); + + if (!$this->isPublicPage()) { + $_SESSION['last_forward_from'] = current_page_url(); + register_error(elgg_echo('loggedinrequired')); + forward(); + } } } } diff --git a/engine/lib/database.php b/engine/lib/database.php index cc2b99f6a..7d90b30b8 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -253,6 +253,10 @@ function execute_query($query, $dblink) { throw new DatabaseException(elgg_echo('DatabaseException:InvalidQuery')); } + if (!is_resource($dblink)) { + throw new DatabaseException(elgg_echo('DatabaseException:InvalidDBLink')); + } + $dbcalls++; $result = mysql_query($query, $dblink); diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index 62cb2d5bb..3026a78e3 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -1060,7 +1060,6 @@ function _elgg_php_error_handler($errno, $errmsg, $filename, $linenum, $vars) { switch ($errno) { case E_USER_ERROR: - case E_RECOVERABLE_ERROR: // (e.g. type hint violation) error_log("PHP ERROR: $error"); register_error("ERROR: $error"); @@ -1070,6 +1069,7 @@ function _elgg_php_error_handler($errno, $errmsg, $filename, $linenum, $vars) { case E_WARNING : case E_USER_WARNING : + case E_RECOVERABLE_ERROR: // (e.g. type hint violation) error_log("PHP WARNING: $error"); break; @@ -1265,7 +1265,7 @@ function elgg_deprecated_notice($msg, $dep_version, $backtrace_level = 1) { $msg .= implode("<br /> -> ", $stack); - elgg_dump($msg, elgg_is_admin_logged_in(), 'WARNING'); + elgg_log($msg, 'WARNING'); return true; } @@ -1578,7 +1578,11 @@ function elgg_http_url_is_identical($url1, $url2, $ignore_params = array('offset * @return void * @since 1.8.0 */ -function elgg_extract($key, array $array, $default = NULL, $strict = true) { +function elgg_extract($key, array $array, $default = null, $strict = true) { + if (!is_array($array)) { + return $default; + } + if ($strict) { return (isset($array[$key])) ? $array[$key] : $default; } else { @@ -2094,6 +2098,22 @@ function elgg_walled_garden() { } /** + * Remove public access for walled gardens + * + * @param string $hook + * @param string $type + * @param array $accesses + * @return array + * @access private + */ +function _elgg_walled_garden_remove_public_access($hook, $type, $accesses) { + if (isset($accesses[ACCESS_PUBLIC])) { + unset($accesses[ACCESS_PUBLIC]); + } + return $accesses; +} + +/** * Boots the engine * * 1. sets error handlers diff --git a/engine/lib/input.php b/engine/lib/input.php index dda8211b6..6d1646e1a 100644 --- a/engine/lib/input.php +++ b/engine/lib/input.php @@ -283,7 +283,7 @@ function input_livesearch_page_handler($page) { WHERE e.guid = ue.guid AND e.enabled = 'yes' AND ue.banned = 'no' - AND (ue.name LIKE '$q%' OR ue.username LIKE '$q%') + AND (ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%') LIMIT $limit "; @@ -333,7 +333,7 @@ function input_livesearch_page_handler($page) { WHERE e.guid = ge.guid AND e.enabled = 'yes' $owner_where - AND (ge.name LIKE '$q%' OR ge.description LIKE '%$q%') + AND (ge.name LIKE '$q%' OR ge.name LIKE '% $q%' OR ge.description LIKE '% $q%') LIMIT $limit "; if ($entities = get_data($query)) { @@ -379,7 +379,7 @@ function input_livesearch_page_handler($page) { AND e.guid = ue.guid AND e.enabled = 'yes' AND ue.banned = 'no' - AND (ue.name LIKE '$q%' OR ue.username LIKE '$q%') + AND (ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%') LIMIT $limit "; diff --git a/engine/lib/notification.php b/engine/lib/notification.php index 5a2f5f8ac..18faff27f 100644 --- a/engine/lib/notification.php +++ b/engine/lib/notification.php @@ -480,8 +480,8 @@ function object_notifications($event, $object_type, $object) { } if (isset($CONFIG->register_objects[$object_type][$object_subtype])) { - $descr = $CONFIG->register_objects[$object_type][$object_subtype]; - $string = $descr . ": " . $object->getURL(); + $subject = $CONFIG->register_objects[$object_type][$object_subtype]; + $string = $subject . ": " . $object->getURL(); // Get users interested in content from this person and notify them // (Person defined by container_guid so we can also subscribe to groups if we want) @@ -500,16 +500,16 @@ function object_notifications($event, $object_type, $object) { if ($user instanceof ElggUser && !$user->isBanned()) { if (($user->guid != $SESSION['user']->guid) && has_access_to_entity($object, $user) && $object->access_id != ACCESS_PRIVATE) { - $methodstring = elgg_trigger_plugin_hook('notify:entity:message', $object->getType(), array( + $body = elgg_trigger_plugin_hook('notify:entity:message', $object->getType(), array( 'entity' => $object, 'to_entity' => $user, 'method' => $method), $string); - if (empty($methodstring) && $methodstring !== false) { - $methodstring = $string; + if (empty($body) && $body !== false) { + $body = $string; } - if ($methodstring !== false) { - notify_user($user->guid, $object->container_guid, $descr, $methodstring, - NULL, array($method)); + if ($body !== false) { + notify_user($user->guid, $object->container_guid, $subject, $body, + null, array($method)); } } } diff --git a/engine/lib/users.php b/engine/lib/users.php index 241b524f9..527eff3cd 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -136,7 +136,6 @@ function ban_user($user_guid, $reason = "") { global $CONFIG; $user_guid = (int)$user_guid; - $reason = sanitise_string($reason); $user = get_entity($user_guid); diff --git a/engine/lib/views.php b/engine/lib/views.php index c98ad4e78..25acbf2b2 100644 --- a/engine/lib/views.php +++ b/engine/lib/views.php @@ -1224,12 +1224,12 @@ function elgg_view_image_block($image, $body, $vars = array()) { * @param string $type The type of module (main, info, popup, aside, etc.) * @param string $title A title to put in the header * @param string $body Content of the module - * @param string $vars Additional parameters for the module + * @param array $vars Additional parameters for the module * * @return string * @since 1.8.0 */ -function elgg_view_module($type, $title, $body, $vars = array()) { +function elgg_view_module($type, $title, $body, array $vars = array()) { $vars['class'] = elgg_extract('class', $vars, '') . " elgg-module-$type"; $vars['title'] = $title; diff --git a/js/lib/languages.js b/js/lib/languages.js index bfa858364..a8ba72c31 100644 --- a/js/lib/languages.js +++ b/js/lib/languages.js @@ -4,8 +4,6 @@ */ elgg.provide('elgg.config.translations'); -elgg.config.language = 'en'; - /** * Analagous to the php version. Merges translations for a * given language into the current translations map. diff --git a/js/lib/ui.widgets.js b/js/lib/ui.widgets.js index d897564b4..b7d4b2fe4 100644 --- a/js/lib/ui.widgets.js +++ b/js/lib/ui.widgets.js @@ -107,6 +107,11 @@ elgg.ui.widgets.move = function(event, ui) { * @return void */ elgg.ui.widgets.remove = function(event) { + if (confirm(elgg.echo('deleteconfirm')) == false) { + event.preventDefault(); + return; + } + var $widget = $(this).closest('.elgg-module-widget'); // if widget type is single instance type, enable the add buton diff --git a/languages/en.php b/languages/en.php index e9c333041..7cd091115 100644 --- a/languages/en.php +++ b/languages/en.php @@ -56,6 +56,7 @@ $english = array( 'DatabaseException:DBSetupIssues' => "There were a number of issues: ", 'DatabaseException:ScriptNotFound' => "Elgg couldn't find the requested database script at %s.", 'DatabaseException:InvalidQuery' => "Invalid query", + 'DatabaseException:InvalidDBLink' => "Connection to database was lost.", 'IOException:FailedToLoadGUID' => "Failed to load new %s from GUID:%d", 'InvalidParameterException:NonElggObject' => "Passing a non-ElggObject to an ElggObject constructor!", @@ -75,10 +76,10 @@ $english = array( 'ElggPlugin:MissingID' => 'Missing plugin ID (guid %s)', 'ElggPlugin:NoPluginPackagePackage' => 'Missing ElggPluginPackage for plugin ID %s (guid %s)', - 'ElggPluginPackage:InvalidPlugin:MissingFile' => 'Missing file %s in package', - 'ElggPluginPackage:InvalidPlugin:InvalidDependency' => 'Invalid dependency type "%s"', - 'ElggPluginPackage:InvalidPlugin:InvalidProvides' => 'Invalid provides type "%s"', - 'ElggPluginPackage:InvalidPlugin:CircularDep' => 'Invalid %s dependency "%s" in plugin %s. Plugins cannot conflict with or require something they provide!', + 'ElggPluginPackage:InvalidPlugin:MissingFile' => 'The required file "%s" is missing.', + 'ElggPluginPackage:InvalidPlugin:InvalidDependency' => 'Its manifest contains an invalid dependency type "%s".', + 'ElggPluginPackage:InvalidPlugin:InvalidProvides' => 'Its manifest contains an invalid provides type "%s".', + 'ElggPluginPackage:InvalidPlugin:CircularDep' => 'There is an invalid %s dependency "%s" in plugin %s. Plugins cannot conflict with or require something they provide!', 'ElggPlugin:Exception:CannotIncludeFile' => 'Cannot include %s for plugin %s (guid: %s) at %s.', 'ElggPlugin:Exception:CannotRegisterViews' => 'Cannot open views dir for plugin %s (guid: %s) at %s.', @@ -229,17 +230,12 @@ $english = array( 'LoginException:AccountLocked' => 'Your account has been locked for too many log in failures.', 'LoginException:ChangePasswordFailure' => 'Failed current password check.', - 'memcache:notinstalled' => 'PHP memcache module not installed, you must install php5-memcache', - 'memcache:noservers' => 'No memcache servers defined, please populate the $CONFIG->memcache_servers variable', - 'memcache:versiontoolow' => 'Memcache needs at least version %s to run, you are running %s', - 'memcache:noaddserver' => 'Multiple server support disabled, you may need to upgrade your PECL memcache library', - 'deprecatedfunction' => 'Warning: This code uses the deprecated function \'%s\' and is not compatible with this version of Elgg', 'pageownerunavailable' => 'Warning: The page owner %d is not accessible!', 'viewfailure' => 'There was an internal failure in the view %s', 'changebookmark' => 'Please change your bookmark for this page', - 'noaccess' => 'The content you were trying to view has been removed or you do not have permission to view it.', + 'noaccess' => 'You need to login to view this content or the content has been removed or you do not have permission to view it.', 'error:missing_data' => 'There was some data missing in your request', 'error:default' => 'Oops...something went wrong.', @@ -697,7 +693,8 @@ $english = array( 'admin:plugins:warning:elgg_version_unknown' => 'This plugin uses a legacy manifest file and does not specify a compatible Elgg version. It probably will not work!', 'admin:plugins:warning:unmet_dependencies' => 'This plugin has unmet dependencies and cannot be activated. Check dependencies under more info.', - 'admin:plugins:warning:invalid' => '%s is not a valid Elgg plugin. Check <a href="http://docs.elgg.org/Invalid_Plugin">the Elgg documentation</a> for troubleshooting tips.', + 'admin:plugins:warning:invalid' => 'This plugin is invalid: %s', + 'admin:plugins:warning:invalid:check_docs' => 'Check <a href="http://docs.elgg.org/Invalid_Plugin">the Elgg documentation</a> for troubleshooting tips.', 'admin:plugins:cannot_activate' => 'cannot activate', 'admin:plugins:set_priority:yes' => "Reordered %s.", @@ -1079,7 +1076,7 @@ Once you have logged in, we highly recommend that you change your password. 'email:settings' => "Email settings", 'email:address:label' => "Your email address", - 'email:save:success' => "New email address saved. Verification is requested.", + 'email:save:success' => "New email address saved.", 'email:save:fail' => "Your new email address could not be saved.", 'friend:newfriend:subject' => "%s has made you a friend!", diff --git a/mod/blog/lib/blog.php b/mod/blog/lib/blog.php index 43de7a646..9a02a8cc3 100644 --- a/mod/blog/lib/blog.php +++ b/mod/blog/lib/blog.php @@ -22,8 +22,9 @@ function blog_get_page_content_read($guid = NULL) { $return['filter'] = ''; if (!elgg_instanceof($blog, 'object', 'blog')) { - $return['content'] = elgg_echo('noaccess'); - return $return; + register_error(elgg_echo('noaccess')); + $_SESSION['last_forward_from'] = current_page_url(); + forward(''); } $return['title'] = $blog->title; diff --git a/mod/bookmarks/pages/bookmarks/view.php b/mod/bookmarks/pages/bookmarks/view.php index c819b8b41..70a6a5bfe 100644 --- a/mod/bookmarks/pages/bookmarks/view.php +++ b/mod/bookmarks/pages/bookmarks/view.php @@ -8,6 +8,7 @@ $bookmark = get_entity(get_input('guid')); if (!$bookmark) { register_error(elgg_echo('noaccess')); + $_SESSION['last_forward_from'] = current_page_url(); forward(''); } diff --git a/mod/developers/views/default/page/theme_preview.php b/mod/developers/views/default/page/theme_preview.php index 5b31fd789..584387ec1 100644 --- a/mod/developers/views/default/page/theme_preview.php +++ b/mod/developers/views/default/page/theme_preview.php @@ -20,7 +20,7 @@ header("Content-type: text/html; charset=UTF-8"); <div class="elgg-page elgg-page-default"> <div class="elgg-page-header"> <div class="elgg-inner"> - <h1 class="elgg-heading-site">Theme Preview</h1> + <h1 class="elgg-heading-site">Theme Sandbox</h1> </div> </div> <div class="elgg-page-body"> diff --git a/mod/developers/views/default/theme_preview/components.php b/mod/developers/views/default/theme_preview/components.php index 45f520f2c..2f414cd88 100644 --- a/mod/developers/views/default/theme_preview/components.php +++ b/mod/developers/views/default/theme_preview/components.php @@ -15,5 +15,11 @@ echo elgg_view_module('info', 'Table (.elgg-table)', $body); $body = elgg_view('theme_preview/components/table', array('class' => 'elgg-table-alt')); echo elgg_view_module('info', 'Table Alternate (.elgg-table-alt)', $body); +$body = elgg_view('theme_preview/components/tagcloud'); +echo elgg_view_module('info', 'Tag cloud (.elgg-tagcloud)', $body); + +$body = elgg_view('theme_preview/components/tags'); +echo elgg_view_module('info', 'Tags (.elgg-tag)', $body); + $body = elgg_view('theme_preview/components/messages'); echo elgg_view_module('info', 'Messages (.elgg-message)', $body); diff --git a/mod/developers/views/default/theme_preview/components/tagcloud.php b/mod/developers/views/default/theme_preview/components/tagcloud.php new file mode 100644 index 000000000..3cbf34745 --- /dev/null +++ b/mod/developers/views/default/theme_preview/components/tagcloud.php @@ -0,0 +1,17 @@ +<?php + +$tags = array( + (object)array('tag' => 'php', 'total' => 2), + (object)array('tag' => 'elgg', 'total' => 8), + (object)array('tag' => 'javascript', 'total' => 3), + (object)array('tag' => 'css', 'total' => 4), + (object)array('tag' => 'html', 'total' => 1), + (object)array('tag' => 'framework', 'total' => 4), + (object)array('tag' => 'social', 'total' => 3), + (object)array('tag' => 'web', 'total' => 7), + (object)array('tag' => 'code', 'total' => 2), +); + +echo '<div style="width: 200px;">'; +echo elgg_view('output/tagcloud', array('value' => $tags)); +echo '</div>'; diff --git a/mod/developers/views/default/theme_preview/components/tags.php b/mod/developers/views/default/theme_preview/components/tags.php new file mode 100644 index 000000000..04df9511a --- /dev/null +++ b/mod/developers/views/default/theme_preview/components/tags.php @@ -0,0 +1,5 @@ +<?php + +echo elgg_view('output/tags', array( + 'value' => array('one', 'two', 'three', 'four', 'cinco'), +)); diff --git a/mod/developers/views/default/theme_preview/general.php b/mod/developers/views/default/theme_preview/general.php index 35d8ccbfd..629462873 100644 --- a/mod/developers/views/default/theme_preview/general.php +++ b/mod/developers/views/default/theme_preview/general.php @@ -1,12 +1,12 @@ <?php /** - * Quick introduction to the theme preview + * Quick introduction to the theme sandbox * * @todo links to resources? */ ?> -<p>This theme preview provides a visual catalog for many of the theming elements +<p>This theme sandbox provides a visual catalog for many of the theming elements that Elgg uses. The primary css selector is listed with each theme element. The preview is divided into sections that are listed in the page menu (usually in the sidebar but depends on your current theme). diff --git a/mod/developers/views/default/theme_preview/navigation.php b/mod/developers/views/default/theme_preview/navigation.php index b80634317..5d3060d10 100644 --- a/mod/developers/views/default/theme_preview/navigation.php +++ b/mod/developers/views/default/theme_preview/navigation.php @@ -2,9 +2,9 @@ /** * Navigation CSS */ -echo elgg_view_module('info', "Tabs", elgg_view('theme_preview/navigation/tabs')); +echo elgg_view_module('info', "Tabs (.elgg-tabs)", elgg_view('theme_preview/navigation/tabs')); -echo elgg_view_module('info', "Pagination", elgg_view('theme_preview/navigation/pagination')); +echo elgg_view_module('info', "Pagination (.elgg-pagination)", elgg_view('theme_preview/navigation/pagination')); echo elgg_view_module('info', "Site Menu (.elgg-menu-site)", elgg_view('theme_preview/navigation/site')); @@ -14,8 +14,10 @@ echo elgg_view_module('info', "Page Menu (.elgg-menu-page)", elgg_view('theme_pr echo elgg_view_module('info', "Filter Menu (.elgg-menu-filter)", elgg_view('theme_preview/navigation/filter')); -echo elgg_view_module('info', "Extras Menu (.elgg-menu-extras)", elgg_view('theme_preview/navigation/extras')); +echo elgg_view_module('info', "Extras Menu (.elgg-menu-extras and .elgg-menu-hz)", elgg_view('theme_preview/navigation/extras')); + +echo elgg_view_module('info', "Entity Menu (.elgg-menu-entity and .elgg-menu-hz)", elgg_view('theme_preview/navigation/entity')); echo elgg_view_module('info', "Owner Block Menu (.elgg-menu-owner-block)", elgg_view('theme_preview/navigation/owner_block')); -?> +echo elgg_view_module('info', "Footer Menu (.elgg-menu-footer)", elgg_view('theme_preview/navigation/footer')); diff --git a/mod/developers/views/default/theme_preview/navigation/breadcrumbs.php b/mod/developers/views/default/theme_preview/navigation/breadcrumbs.php index eb3dd47a3..c910b2aa4 100644 --- a/mod/developers/views/default/theme_preview/navigation/breadcrumbs.php +++ b/mod/developers/views/default/theme_preview/navigation/breadcrumbs.php @@ -3,4 +3,8 @@ elgg_push_breadcrumb('First', "#"); elgg_push_breadcrumb('Second', "#");
elgg_push_breadcrumb('Third');
-echo elgg_view('navigation/breadcrumbs');
+echo elgg_view('navigation/breadcrumbs', array('class' => mts));
+
+elgg_pop_breadcrumb();
+elgg_pop_breadcrumb();
+elgg_pop_breadcrumb();
diff --git a/mod/developers/views/default/theme_preview/navigation/default.php b/mod/developers/views/default/theme_preview/navigation/default.php index fd67b8094..bfd26162f 100644 --- a/mod/developers/views/default/theme_preview/navigation/default.php +++ b/mod/developers/views/default/theme_preview/navigation/default.php @@ -4,7 +4,7 @@ $params = array(); $params['menu'] = array();
$params['menu']['default'] = array();
for ($i=1; $i<=5; $i++) {
- $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "$url#");
+ $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "#");
}
$params['menu']['default'][2]->setSelected(true);
diff --git a/mod/developers/views/default/theme_preview/navigation/entity.php b/mod/developers/views/default/theme_preview/navigation/entity.php new file mode 100644 index 000000000..465585b00 --- /dev/null +++ b/mod/developers/views/default/theme_preview/navigation/entity.php @@ -0,0 +1,12 @@ +<?php +$params = array(); +$params['menu'] = array(); +$params['menu']['default'] = array(); +$params['menu']['default'][] = new ElggMenuItem(1, "Public", false); +$params['menu']['default'][] = new ElggMenuItem(2, "Edit", "#"); +$params['menu']['default'][] = new ElggMenuItem(3, elgg_view_icon('thumbs-up'), "#"); +$params['name'] = 'entity'; +$params['class'] = 'elgg-menu-hz'; + +echo elgg_view('navigation/menu/default', $params); + diff --git a/mod/developers/views/default/theme_preview/navigation/extras.php b/mod/developers/views/default/theme_preview/navigation/extras.php index 6982cf57d..43b19f8e3 100644 --- a/mod/developers/views/default/theme_preview/navigation/extras.php +++ b/mod/developers/views/default/theme_preview/navigation/extras.php @@ -3,11 +3,11 @@ $params = array();
$params['menu'] = array();
$params['menu']['default'] = array();
-for ($i=1; $i<=5; $i++) {
- $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "$url#");
-}
-$params['class'] = 'elgg-menu-extras';
-
+$params['menu']['default'][] = new ElggMenuItem(1, elgg_view_icon('push-pin-alt'), "#");
+$params['menu']['default'][] = new ElggMenuItem(2, elgg_view_icon('rss'), "#");
+$params['menu']['default'][] = new ElggMenuItem(3, elgg_view_icon('star-alt'), "#");
+$params['name'] = 'extras';
+$params['class'] = 'elgg-menu-hz';
?>
diff --git a/mod/developers/views/default/theme_preview/navigation/filter.php b/mod/developers/views/default/theme_preview/navigation/filter.php index f27edf150..ea1c8b033 100644 --- a/mod/developers/views/default/theme_preview/navigation/filter.php +++ b/mod/developers/views/default/theme_preview/navigation/filter.php @@ -4,7 +4,7 @@ $params = array(); $params['menu'] = array();
$params['menu']['default'] = array();
for ($i=1; $i<=5; $i++) {
- $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "$url#");
+ $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "#");
}
$params['menu']['default'][2]->setSelected(true);
diff --git a/mod/developers/views/default/theme_preview/navigation/footer.php b/mod/developers/views/default/theme_preview/navigation/footer.php new file mode 100644 index 000000000..92a1bb43c --- /dev/null +++ b/mod/developers/views/default/theme_preview/navigation/footer.php @@ -0,0 +1,10 @@ +<?php +$params = array(); +$params['menu'] = array(); +$params['menu']['default'] = array(); +for ($i=1; $i<=5; $i++) { + $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "#"); +} +$params['name'] = 'footer'; + +echo elgg_view('navigation/menu/default', $params); diff --git a/mod/developers/views/default/theme_preview/navigation/horizontal.php b/mod/developers/views/default/theme_preview/navigation/horizontal.php index 69e75c063..f404f42c0 100644 --- a/mod/developers/views/default/theme_preview/navigation/horizontal.php +++ b/mod/developers/views/default/theme_preview/navigation/horizontal.php @@ -4,7 +4,7 @@ $params = array(); $params['menu'] = array();
$params['menu']['default'] = array();
for ($i=1; $i<=5; $i++) {
- $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "$url#");
+ $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "#");
}
$params['menu']['default'][2]->setSelected(true);
$params['class'] = 'elgg-menu-hz';
diff --git a/mod/developers/views/default/theme_preview/navigation/owner_block.php b/mod/developers/views/default/theme_preview/navigation/owner_block.php index 6bf79fe7e..20b93d166 100644 --- a/mod/developers/views/default/theme_preview/navigation/owner_block.php +++ b/mod/developers/views/default/theme_preview/navigation/owner_block.php @@ -3,9 +3,11 @@ $params = array(); $params['menu'] = array();
$params['menu']['default'] = array();
for ($i=1; $i<=5; $i++) {
- $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "$url#");
+ $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "#");
}
$params['menu']['default'][2]->setSelected(true);
-$params['class'] = 'elgg-menu-owner-block';
+$params['name'] = 'owner-block';
-echo elgg_view('navigation/menu/default', $params);
\ No newline at end of file +echo '<div class="elgg-sidebar">';
+echo elgg_view('navigation/menu/default', $params);
+echo '</div>';
diff --git a/mod/developers/views/default/theme_preview/navigation/page.php b/mod/developers/views/default/theme_preview/navigation/page.php index fb3f075dc..a57edc2e2 100644 --- a/mod/developers/views/default/theme_preview/navigation/page.php +++ b/mod/developers/views/default/theme_preview/navigation/page.php @@ -5,11 +5,10 @@ $params['menu'] = array(); $params['menu']['default'] = array();
for ($i=1; $i<=5; $i++) {
$params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "#");
- $params['menu']['alt'][] = new ElggMenuItem($i, "Page $i", "#");
}
$params['menu']['default'][2]->setSelected(true);
-$m = new ElggMenuItem(10, "Child", "$url#");
+$m = new ElggMenuItem(10, "Child", "#");
$m->setParent($params['menu']['default'][1]);
$params['menu']['default'][1]->addChild($m);
?>
diff --git a/mod/developers/views/default/theme_preview/navigation/site.php b/mod/developers/views/default/theme_preview/navigation/site.php index df8dc1b70..329036b80 100644 --- a/mod/developers/views/default/theme_preview/navigation/site.php +++ b/mod/developers/views/default/theme_preview/navigation/site.php @@ -4,7 +4,7 @@ $params = array(); $params['menu'] = array();
$params['menu']['default'] = array();
for ($i=1; $i<=5; $i++) {
- $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "$url#");
+ $params['menu']['default'][] = new ElggMenuItem($i, "Page $i", "#");
}
$params['menu']['default'][2]->setSelected(true);
?>
diff --git a/mod/developers/views/default/theme_preview/navigation/tabs.php b/mod/developers/views/default/theme_preview/navigation/tabs.php index b2638bb37..81fe4e669 100644 --- a/mod/developers/views/default/theme_preview/navigation/tabs.php +++ b/mod/developers/views/default/theme_preview/navigation/tabs.php @@ -1,9 +1,9 @@ <?php
$params = array(
'tabs' => array(
- array('title' => 'First', 'url' => "$url#"),
- array('title' => 'Second', 'url' => "$url#", 'selected' => true),
- array('title' => 'Third', 'url' => "$url#"),
+ array('title' => 'First', 'url' => "#"),
+ array('title' => 'Second', 'url' => "#", 'selected' => true),
+ array('title' => 'Third', 'url' => "#"),
)
);
diff --git a/mod/developers/views/default/theme_preview/typography.php b/mod/developers/views/default/theme_preview/typography.php index 6662a9a46..7a6328cf9 100644 --- a/mod/developers/views/default/theme_preview/typography.php +++ b/mod/developers/views/default/theme_preview/typography.php @@ -5,6 +5,8 @@ echo elgg_view_module('info', "Headings", elgg_view('theme_preview/typography/headings')); +echo elgg_view_module('info', "Fonts", elgg_view('theme_preview/typography/fonts')); + echo elgg_view_module('info', "Paragraph", elgg_view('theme_preview/typography/paragraph')); echo elgg_view_module('info', "Misc", elgg_view('theme_preview/typography/misc'));
\ No newline at end of file diff --git a/mod/developers/views/default/theme_preview/typography/fonts.php b/mod/developers/views/default/theme_preview/typography/fonts.php new file mode 100644 index 000000000..dd3c53f00 --- /dev/null +++ b/mod/developers/views/default/theme_preview/typography/fonts.php @@ -0,0 +1,7 @@ +<ul> + <li>Lorem ipsum dolor sit amet (body)</li> + <li><span class="elgg-text-help" style="display: inline;">Lorem ipsum dolor sit amet</span> (.elgg-text-help)</li> + <li><span class="elgg-quiet">Lorem ipsum dolor sit amet</span> (.elgg-quiet)</li> + <li><span class="elgg-loud">Lorem ipsum dolor sit amet</span> (.elgg-loud)</li> + <li><span class="elgg-monospace">Lorem ipsum dolor sit amet</span> (.elgg-monospace)</li> +</ul>
\ No newline at end of file diff --git a/mod/file/pages/file/view.php b/mod/file/pages/file/view.php index ec51b30e6..6c9566a89 100644 --- a/mod/file/pages/file/view.php +++ b/mod/file/pages/file/view.php @@ -8,6 +8,7 @@ $file = get_entity(get_input('guid')); if (!$file) { register_error(elgg_echo('noaccess')); + $_SESSION['last_forward_from'] = current_page_url(); forward(''); } diff --git a/mod/groups/icon.php b/mod/groups/icon.php index f86f84fa5..1bd240ea6 100644 --- a/mod/groups/icon.php +++ b/mod/groups/icon.php @@ -8,7 +8,13 @@ require_once(dirname(dirname(dirname(__FILE__))) . "/engine/start.php"); $group_guid = get_input('group_guid'); + +/* @var ElggGroup $group */ $group = get_entity($group_guid); +if (!($group instanceof ElggGroup)) { + header("HTTP/1.1 404 Not Found"); + exit; +} // If is the same ETag, content didn't changed. $etag = $group->icontime . $group_guid; diff --git a/mod/groups/languages/en.php b/mod/groups/languages/en.php index e51e51a14..88aeccb54 100644 --- a/mod/groups/languages/en.php +++ b/mod/groups/languages/en.php @@ -64,6 +64,7 @@ $english = array( 'groups:search_in_group' => "Search in this group", 'groups:acl' => "Group: %s", + 'discussion:notification:topic:subject' => 'New group discussion post', 'groups:notification' => '%s added a new discussion topic to %s: @@ -74,6 +75,15 @@ View and reply to the discussion: %s ', + 'discussion:notification:reply:body' => +'%s replied to the discussion topic %s in the group %s: + +%s + +View and reply to the discussion: +%s +', + 'groups:activity' => "Group activity", 'groups:enableactivity' => 'Enable group activity', 'groups:activity:none' => "There is no group activity yet", diff --git a/mod/groups/lib/discussion.php b/mod/groups/lib/discussion.php index 55642644d..02ab27fdc 100644 --- a/mod/groups/lib/discussion.php +++ b/mod/groups/lib/discussion.php @@ -149,8 +149,9 @@ function discussion_handle_view_page($guid) { $topic = get_entity($guid); if (!$topic) { - register_error(elgg_echo('discussion:topic:notfound')); - forward(); + register_error(elgg_echo('noaccess')); + $_SESSION['last_forward_from'] = current_page_url(); + forward(''); } $group = $topic->getContainerEntity(); diff --git a/mod/groups/start.php b/mod/groups/start.php index aeab0649a..193b72a4e 100644 --- a/mod/groups/start.php +++ b/mod/groups/start.php @@ -93,7 +93,6 @@ function groups_init() { elgg_register_event_handler('join', 'group', 'groups_user_join_event_listener'); elgg_register_event_handler('leave', 'group', 'groups_user_leave_event_listener'); elgg_register_event_handler('pagesetup', 'system', 'groups_setup_sidebar_menus'); - elgg_register_event_handler('annotate', 'all', 'group_object_notifications'); elgg_register_plugin_hook_handler('access:collections:add_user', 'collection', 'groups_access_collection_override'); @@ -284,12 +283,21 @@ function groups_url($entity) { * @return string Relative URL */ function groups_icon_url_override($hook, $type, $returnvalue, $params) { + /* @var ElggGroup $group */ $group = $params['entity']; $size = $params['size']; - if (isset($group->icontime)) { + $icontime = $group->icontime; + // handle missing metadata (pre 1.7 installations) + if (null === $icontime) { + $file = new ElggFile(); + $file->owner_guid = $group->owner_guid; + $file->setFilename("groups/" . $group->guid . "large.jpg"); + $icontime = $file->exists() ? time() : 0; + create_metadata($group->guid, 'icontime', $icontime, 'integer', $group->owner_guid, ACCESS_PUBLIC); + } + if ($icontime) { // return thumbnail - $icontime = $group->icontime; return "groupicon/$group->guid/$size/$icontime.jpg"; } @@ -714,6 +722,7 @@ function discussion_init() { elgg_register_library('elgg:discussion', elgg_get_plugins_path() . 'groups/lib/discussion.php'); elgg_register_page_handler('discussion', 'discussion_page_handler'); + elgg_register_page_handler('forum', 'discussion_forum_page_handler'); elgg_register_entity_url_handler('object', 'groupforumtopic', 'discussion_override_topic_url'); @@ -740,8 +749,24 @@ function discussion_init() { elgg_extend_view('groups/tool_latest', 'discussion/group_module'); // notifications - register_notification_object('object', 'groupforumtopic', elgg_echo('groupforumtopic:new')); + register_notification_object('object', 'groupforumtopic', elgg_echo('discussion:notification:topic:subject')); elgg_register_plugin_hook_handler('notify:entity:message', 'object', 'groupforumtopic_notify_message'); + elgg_register_event_handler('create', 'annotation', 'discussion_reply_notifications'); + elgg_register_plugin_hook_handler('notify:annotation:message', 'group_topic_post', 'discussion_create_reply_notification'); +} + +/** + * Exists for backwards compatibility for Elgg 1.7 + */ +function discussion_forum_page_handler($page) { + switch ($page[0]) { + case 'topic': + header('Status: 301 Moved Permanently'); + forward("/discussion/view/{$page[1]}/{$page[2]}"); + break; + default: + return false; + } } /** @@ -792,7 +817,7 @@ function discussion_page_handler($page) { * @return string */ function discussion_override_topic_url($entity) { - return 'discussion/view/' . $entity->guid; + return 'discussion/view/' . $entity->guid . '/' . elgg_get_friendly_title($entity->title); } /** @@ -848,36 +873,16 @@ function discussion_add_to_river_menu($hook, $type, $return, $params) { } /** - * Event handler for group forum posts + * Create discussion notification body * - */ -function group_object_notifications($event, $object_type, $object) { - - static $flag; - if (!isset($flag)) { - $flag = 0; - } - - if (is_callable('object_notifications')) - if ($object instanceof ElggObject) { - if ($object->getSubtype() == 'groupforumtopic') { - if ($flag == 0) { - $flag = 1; - object_notifications($event, $object_type, $object); - } - } - } -} - -/** - * Returns a more meaningful message + * @todo namespace method with 'discussion' * - * @param unknown_type $hook - * @param unknown_type $entity_type - * @param unknown_type $returnvalue - * @param unknown_type $params + * @param string $hook + * @param string $type + * @param string $message + * @param array $params */ -function groupforumtopic_notify_message($hook, $entity_type, $returnvalue, $params) { +function groupforumtopic_notify_message($hook, $type, $message, $params) { $entity = $params['entity']; $to_entity = $params['to_entity']; $method = $params['method']; @@ -897,11 +902,103 @@ function groupforumtopic_notify_message($hook, $entity_type, $returnvalue, $para $entity->getURL() )); } - + return null; } /** + * Create discussion reply notification body + * + * @param string $hook + * @param string $type + * @param string $message + * @param array $params + */ +function discussion_create_reply_notification($hook, $type, $message, $params) { + $reply = $params['annotation']; + $method = $params['method']; + $topic = $reply->getEntity(); + $poster = $reply->getOwnerEntity(); + $group = $topic->getContainerEntity(); + + return elgg_echo('discussion:notification:reply:body', array( + $poster->name, + $topic->title, + $group->name, + $reply->value, + $topic->getURL(), + )); +} + +/** + * Catch reply to discussion topic and generate notifications + * + * @todo this will be replaced in Elgg 1.9 and is a clone of object_notifications() + * + * @param string $event + * @param string $type + * @param ElggAnnotation $annotation + * @return void + */ +function discussion_reply_notifications($event, $type, $annotation) { + global $CONFIG, $NOTIFICATION_HANDLERS; + + if ($annotation->name !== 'group_topic_post') { + return; + } + + // Have we registered notifications for this type of entity? + $object_type = 'object'; + $object_subtype = 'groupforumtopic'; + + $topic = $annotation->getEntity(); + if (!$topic) { + return; + } + + $poster = $annotation->getOwnerEntity(); + if (!$poster) { + return; + } + + if (isset($CONFIG->register_objects[$object_type][$object_subtype])) { + $subject = $CONFIG->register_objects[$object_type][$object_subtype]; + $string = $subject . ": " . $topic->getURL(); + + // Get users interested in content from this person and notify them + // (Person defined by container_guid so we can also subscribe to groups if we want) + foreach ($NOTIFICATION_HANDLERS as $method => $foo) { + $interested_users = elgg_get_entities_from_relationship(array( + 'relationship' => 'notify' . $method, + 'relationship_guid' => $topic->getContainerGUID(), + 'inverse_relationship' => true, + 'types' => 'user', + 'limit' => 0, + )); + + if ($interested_users && is_array($interested_users)) { + foreach ($interested_users as $user) { + if ($user instanceof ElggUser && !$user->isBanned()) { + if (($user->guid != $poster->guid) && has_access_to_entity($topic, $user) && $topic->access_id != ACCESS_PRIVATE) { + $body = elgg_trigger_plugin_hook('notify:annotation:message', $annotation->getSubtype(), array( + 'annotation' => $annotation, + 'to_entity' => $user, + 'method' => $method), $string); + if (empty($body) && $body !== false) { + $body = $string; + } + if ($body !== false) { + notify_user($user->guid, $topic->getContainerGUID(), $subject, $body, null, array($method)); + } + } + } + } + } + } + } +} + +/** * A simple function to see who can edit a group discussion post * @param the comment $entity * @param user who owns the group $group_owner diff --git a/mod/groups/topicposts.php b/mod/groups/topicposts.php index f9dd3344b..d0137e2f5 100644 --- a/mod/groups/topicposts.php +++ b/mod/groups/topicposts.php @@ -10,10 +10,10 @@ // Load Elgg engine require_once(dirname(dirname(dirname(__FILE__))) . "/engine/start.php"); -elgg_load_library('elgg:topic'); +elgg_load_library('elgg:discussion'); $guid = get_input('topic'); register_error(elgg_echo('changebookmark')); -topic_handle_view_page($guid); +forward("/discussion/view/$guid"); diff --git a/mod/groups/views/default/forms/groups/edit.php b/mod/groups/views/default/forms/groups/edit.php index 26436ef01..8055b6430 100644 --- a/mod/groups/views/default/forms/groups/edit.php +++ b/mod/groups/views/default/forms/groups/edit.php @@ -55,7 +55,7 @@ if ($group_profile_fields > 0) { <div> <label> <?php echo elgg_echo('groups:membership'); ?><br /> - <?php echo elgg_view('input/access', array( + <?php echo elgg_view('input/dropdown', array( 'name' => 'membership', 'value' => $membership, 'options_values' => array( diff --git a/mod/htmlawed/manifest.xml b/mod/htmlawed/manifest.xml index 074f98fb3..6807e96a4 100644 --- a/mod/htmlawed/manifest.xml +++ b/mod/htmlawed/manifest.xml @@ -2,10 +2,10 @@ <plugin_manifest xmlns="http://www.elgg.org/plugin_manifest/1.8"> <name>HTMLawed</name> <author>Core developers</author> - <version>1.5</version> + <version>1.8</version> <category>bundled</category> <category>security</category> - <description>Provides security filtering. Disabling this plugin is extremely insecure. DO NOT DISABLE.</description> + <description>Provides security filtering. Running a site with this plugin disabled is extremely insecure. DO NOT DISABLE.</description> <website>http://www.elgg.org/</website> <copyright>See COPYRIGHT.txt</copyright> <license>GNU General Public License version 2</license> diff --git a/mod/htmlawed/start.php b/mod/htmlawed/start.php index 10bea2a52..5af18f4dd 100644 --- a/mod/htmlawed/start.php +++ b/mod/htmlawed/start.php @@ -90,7 +90,7 @@ function htmLawedArray(&$v, $k, $htmlawed_config) { * @param array $attributes An array of attributes * @return string */ -function htmlawed_tag_post_processor($element, $attributes) { +function htmlawed_tag_post_processor($element, $attributes = array()) { // these are the default styles used by tinymce. $allowed_styles = array( 'color', 'cursor', 'text-align', 'vertical-align', 'font-size', diff --git a/mod/htmlawed/vendors/htmLawed/htmLawed.php b/mod/htmlawed/vendors/htmLawed/htmLawed.php index 2556fdcf2..0d9624961 100644..100755 --- a/mod/htmlawed/vendors/htmLawed/htmLawed.php +++ b/mod/htmlawed/vendors/htmLawed/htmLawed.php @@ -1,9 +1,9 @@ <?php /* -htmLawed 1.1.9, 22 December 2009 +htmLawed 1.1.11, 5 June 2012 Copyright Santosh Patnaik -GPL v3 license +Dual licensed with LGPL 3 and GPL 2 or later A PHP Labware internal utility; www.bioinformatics.org/phplabware/internal_utilities/htmLawed See htmLawed_README.txt/htm @@ -51,7 +51,7 @@ foreach(explode(';', str_replace(array(' ', "\t", "\r", "\n"), '', $x)) as $v){ if($x2){$C['schemes'][$x] = array_flip(explode(',', $x2));} } if(!isset($C['schemes']['*'])){$C['schemes']['*'] = array('file'=>1, 'http'=>1, 'https'=>1,);} -if(!empty($C['safe']) && empty($C['schemes']['style'])){$C['schemes']['style'] = array('nil'=>1);} +if(!empty($C['safe']) && empty($C['schemes']['style'])){$C['schemes']['style'] = array('!'=>1);} $C['abs_url'] = isset($C['abs_url']) ? $C['abs_url'] : 0; if(!isset($C['base_url']) or !preg_match('`^[a-zA-Z\d.+\-]+://[^/]+/(.+?/)?$`', $C['base_url'])){ $C['base_url'] = $C['abs_url'] = 0; @@ -65,6 +65,7 @@ $C['cdata'] = isset($C['cdata']) ? $C['cdata'] : (empty($C['safe']) ? 3 : 0); $C['clean_ms_char'] = empty($C['clean_ms_char']) ? 0 : $C['clean_ms_char']; $C['comment'] = isset($C['comment']) ? $C['comment'] : (empty($C['safe']) ? 3 : 0); $C['css_expression'] = empty($C['css_expression']) ? 0 : 1; +$C['direct_list_nest'] = empty($C['direct_list_nest']) ? 0 : 1; $C['hexdec_entity'] = isset($C['hexdec_entity']) ? $C['hexdec_entity'] : 1; $C['hook'] = (!empty($C['hook']) && function_exists($C['hook'])) ? $C['hook'] : 0; $C['hook_tag'] = (!empty($C['hook_tag']) && function_exists($C['hook_tag'])) ? $C['hook_tag'] : 0; @@ -149,14 +150,15 @@ $cI = array('a'=>1, 'abbr'=>1, 'acronym'=>1, 'address'=>1, 'b'=>1, 'bdo'=>1, 'bi $cN = array('a'=>array('a'=>1), 'button'=>array('a'=>1, 'button'=>1, 'fieldset'=>1, 'form'=>1, 'iframe'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'fieldset'=>array('fieldset'=>1), 'form'=>array('form'=>1), 'label'=>array('label'=>1), 'noscript'=>array('script'=>1), 'pre'=>array('big'=>1, 'font'=>1, 'img'=>1, 'object'=>1, 'script'=>1, 'small'=>1, 'sub'=>1, 'sup'=>1), 'rb'=>array('ruby'=>1), 'rt'=>array('ruby'=>1)); // Illegal $cN2 = array_keys($cN); $cR = array('blockquote'=>1, 'dir'=>1, 'dl'=>1, 'form'=>1, 'map'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'optgroup'=>1, 'rbc'=>1, 'rtc'=>1, 'ruby'=>1, 'select'=>1, 'table'=>1, 'tbody'=>1, 'tfoot'=>1, 'thead'=>1, 'tr'=>1, 'ul'=>1); -$cS = array('colgroup'=>array('col'=>1), 'dir'=>array('li'), 'dl'=>array('dd'=>1, 'dt'=>1), 'menu'=>array('li'=>1), 'ol'=>array('li'=>1), 'optgroup'=>array('option'=>1), 'option'=>array('#pcdata'=>1), 'rbc'=>array('rb'=>1), 'rp'=>array('#pcdata'=>1), 'rtc'=>array('rt'=>1), 'ruby'=>array('rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1), 'select'=>array('optgroup'=>1, 'option'=>1), 'script'=>array('#pcdata'=>1), 'table'=>array('caption'=>1, 'col'=>1, 'colgroup'=>1, 'tfoot'=>1, 'tbody'=>1, 'tr'=>1, 'thead'=>1), 'tbody'=>array('tr'=>1), 'tfoot'=>array('tr'=>1), 'textarea'=>array('#pcdata'=>1), 'thead'=>array('tr'=>1), 'tr'=>array('td'=>1, 'th'=>1), 'ul'=>array('li'=>1)); // Specific - immediate parent-child +$cS = array('colgroup'=>array('col'=>1), 'dir'=>array('li'=>1), 'dl'=>array('dd'=>1, 'dt'=>1), 'menu'=>array('li'=>1), 'ol'=>array('li'=>1), 'optgroup'=>array('option'=>1), 'option'=>array('#pcdata'=>1), 'rbc'=>array('rb'=>1), 'rp'=>array('#pcdata'=>1), 'rtc'=>array('rt'=>1), 'ruby'=>array('rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1), 'select'=>array('optgroup'=>1, 'option'=>1), 'script'=>array('#pcdata'=>1), 'table'=>array('caption'=>1, 'col'=>1, 'colgroup'=>1, 'tfoot'=>1, 'tbody'=>1, 'tr'=>1, 'thead'=>1), 'tbody'=>array('tr'=>1), 'tfoot'=>array('tr'=>1), 'textarea'=>array('#pcdata'=>1), 'thead'=>array('tr'=>1), 'tr'=>array('td'=>1, 'th'=>1), 'ul'=>array('li'=>1)); // Specific - immediate parent-child +if($GLOBALS['C']['direct_list_nest']){$cS['ol'] = $cS['ul'] += array('ol'=>1, 'ul'=>1);} $cO = array('address'=>array('p'=>1), 'applet'=>array('param'=>1), 'blockquote'=>array('script'=>1), 'fieldset'=>array('legend'=>1, '#pcdata'=>1), 'form'=>array('script'=>1), 'map'=>array('area'=>1), 'object'=>array('param'=>1, 'embed'=>1)); // Other $cT = array('colgroup'=>1, 'dd'=>1, 'dt'=>1, 'li'=>1, 'option'=>1, 'p'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1); // Omitable closing // block/inline type; ins & del both type; #pcdata: text $eB = array('address'=>1, 'blockquote'=>1, 'center'=>1, 'del'=>1, 'dir'=>1, 'dl'=>1, 'div'=>1, 'fieldset'=>1, 'form'=>1, 'ins'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'isindex'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'p'=>1, 'pre'=>1, 'table'=>1, 'ul'=>1); -$eI = array('#pcdata'=>1, 'a'=>1, 'abbr'=>1, 'acronym'=>1, 'applet'=>1, 'b'=>1, 'bdo'=>1, 'big'=>1, 'br'=>1, 'button'=>1, 'cite'=>1, 'code'=>1, 'del'=>1, 'dfn'=>1, 'em'=>1, 'embed'=>1, 'font'=>1, 'i'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'ins'=>1, 'kbd'=>1, 'label'=>1, 'map'=>1, 'object'=>1, 'param'=>1, 'q'=>1, 'ruby'=>1, 's'=>1, 'samp'=>1, 'select'=>1, 'script'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'sup'=>1, 'textarea'=>1, 'tt'=>1, 'u'=>1, 'var'=>1); +$eI = array('#pcdata'=>1, 'a'=>1, 'abbr'=>1, 'acronym'=>1, 'applet'=>1, 'b'=>1, 'bdo'=>1, 'big'=>1, 'br'=>1, 'button'=>1, 'cite'=>1, 'code'=>1, 'del'=>1, 'dfn'=>1, 'em'=>1, 'embed'=>1, 'font'=>1, 'i'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'ins'=>1, 'kbd'=>1, 'label'=>1, 'map'=>1, 'object'=>1, 'q'=>1, 'ruby'=>1, 's'=>1, 'samp'=>1, 'select'=>1, 'script'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'sup'=>1, 'textarea'=>1, 'tt'=>1, 'u'=>1, 'var'=>1); $eN = array('a'=>1, 'big'=>1, 'button'=>1, 'fieldset'=>1, 'font'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'label'=>1, 'object'=>1, 'ruby'=>1, 'script'=>1, 'select'=>1, 'small'=>1, 'sub'=>1, 'sup'=>1, 'textarea'=>1); // Exclude from specific ele; $cN values -$eO = array('area'=>1, 'caption'=>1, 'col'=>1, 'colgroup'=>1, 'dd'=>1, 'dt'=>1, 'legend'=>1, 'li'=>1, 'optgroup'=>1, 'option'=>1, 'rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1, 'script'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'thead'=>1, 'th'=>1, 'tr'=>1); // Missing in $eB & $eI +$eO = array('area'=>1, 'caption'=>1, 'col'=>1, 'colgroup'=>1, 'dd'=>1, 'dt'=>1, 'legend'=>1, 'li'=>1, 'optgroup'=>1, 'option'=>1, 'param'=>1, 'rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1, 'script'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'thead'=>1, 'th'=>1, 'tr'=>1); // Missing in $eB & $eI $eF = $eB + $eI; // $in sets allowed child @@ -295,20 +297,14 @@ function hl_cmtcd($t){ // comment/CDATA sec handler $t = $t[0]; global $C; -if($t[3] == '-'){ - if(!$C['comment']){return $t;} - if($C['comment'] == 1){return '';} +if(!($v = $C[$n = $t[3] == '-' ? 'comment' : 'cdata'])){return $t;} +if($v == 1){return '';} +if($n == 'comment'){ if(substr(($t = preg_replace('`--+`', '-', substr($t, 4, -3))), -1) != ' '){$t .= ' ';} - $t = $C['comment'] == 2 ? str_replace(array('&', '<', '>'), array('&', '<', '>'), $t) : $t; - $t = "\x01\x02\x04!--$t--\x05\x02\x01"; -}else{ // CDATA - if(!$C['cdata']){return $t;} - if($C['cdata'] == 1){return '';} - $t = substr($t, 1, -1); - $t = $C['cdata'] == 2 ? str_replace(array('&', '<', '>'), array('&', '<', '>'), $t) : $t; - $t = "\x01\x01\x04$t\x05\x01\x01"; -} -return str_replace(array('&', '<', '>'), array("\x03", "\x04", "\x05"), $t); +} +else{$t = substr($t, 1, -1);} +$t = $v == 2 ? str_replace(array('&', '<', '>'), array('&', '<', '>'), $t) : $t; +return str_replace(array('&', '<', '>'), array("\x03", "\x04", "\x05"), ($n == 'comment' ? "\x01\x02\x04!--$t--\x05\x02\x01" : "\x01\x01\x04$t\x05\x01\x01")); // eof } @@ -334,9 +330,11 @@ global $C; $b = $a = ''; if($c == null){$c = 'style'; $b = $p[1]; $a = $p[3]; $p = trim($p[2]);} $c = isset($C['schemes'][$c]) ? $C['schemes'][$c] : $C['schemes']['*']; -if(isset($c['*']) or !strcspn($p, '#?;')){return "{$b}{$p}{$a}";} // All ok, frag, query, param +static $d = 'denied:'; +if(isset($c['!']) && substr($p, 0, 7) != $d){$p = "$d$p";} +if(isset($c['*']) or !strcspn($p, '#?;') or (substr($p, 0, 7) == $d)){return "{$b}{$p}{$a}";} // All ok, frag, query, param if(preg_match('`^([a-z\d\-+.&#; ]+?)(:|&#(58|x3a);|%3a|\\\\0{0,4}3a).`i', $p, $m) && !isset($c[strtolower($m[1])])){ // Denied prot - return "{$b}denied:{$p}{$a}"; + return "{$b}{$d}{$p}{$a}"; } if($C['abs_url']){ if($C['abs_url'] == -1 && strpos($p, $C['base_url']) === 0){ // Make url rel @@ -429,11 +427,11 @@ if($C['make_tag_strict'] && isset($eD[$e])){ // close tag static $eE = array('area'=>1, 'br'=>1, 'col'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'param'=>1); // Empty ele if(!empty($m[1])){ - return (!isset($eE[$e]) ? "</$e>" : (($C['keep_bad'])%2 ? str_replace(array('<', '>'), array('<', '>'), $t) : '')); + return (!isset($eE[$e]) ? (empty($C['hook_tag']) ? "</$e>" : $C['hook_tag']($e)) : (($C['keep_bad'])%2 ? str_replace(array('<', '>'), array('<', '>'), $t) : '')); } // open tag & attr -static $aN = array('abbr'=>array('td'=>1, 'th'=>1), 'accept-charset'=>array('form'=>1), 'accept'=>array('form'=>1, 'input'=>1), 'accesskey'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'legend'=>1, 'textarea'=>1), 'action'=>array('form'=>1), 'align'=>array('caption'=>1, 'embed'=>1, 'applet'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'legend'=>1, 'table'=>1, 'hr'=>1, 'div'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'p'=>1, 'col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'alt'=>array('applet'=>1, 'area'=>1, 'img'=>1, 'input'=>1), 'archive'=>array('applet'=>1, 'object'=>1), 'axis'=>array('td'=>1, 'th'=>1), 'bgcolor'=>array('embed'=>1, 'table'=>1, 'tr'=>1, 'td'=>1, 'th'=>1), 'border'=>array('table'=>1, 'img'=>1, 'object'=>1), 'bordercolor'=>array('table'=>1, 'td'=>1, 'tr'=>1), 'cellpadding'=>array('table'=>1), 'cellspacing'=>array('table'=>1), 'char'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charoff'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charset'=>array('a'=>1, 'script'=>1), 'checked'=>array('input'=>1), 'cite'=>array('blockquote'=>1, 'q'=>1, 'del'=>1, 'ins'=>1), 'classid'=>array('object'=>1), 'clear'=>array('br'=>1), 'code'=>array('applet'=>1), 'codebase'=>array('object'=>1, 'applet'=>1), 'codetype'=>array('object'=>1), 'color'=>array('font'=>1), 'cols'=>array('textarea'=>1), 'colspan'=>array('td'=>1, 'th'=>1), 'compact'=>array('dir'=>1, 'dl'=>1, 'menu'=>1, 'ol'=>1, 'ul'=>1), 'coords'=>array('area'=>1, 'a'=>1), 'data'=>array('object'=>1), 'datetime'=>array('del'=>1, 'ins'=>1), 'declare'=>array('object'=>1), 'defer'=>array('script'=>1), 'dir'=>array('bdo'=>1), 'disabled'=>array('button'=>1, 'input'=>1, 'optgroup'=>1, 'option'=>1, 'select'=>1, 'textarea'=>1), 'enctype'=>array('form'=>1), 'face'=>array('font'=>1), 'for'=>array('label'=>1), 'frame'=>array('table'=>1), 'frameborder'=>array('iframe'=>1), 'headers'=>array('td'=>1, 'th'=>1), 'height'=>array('embed'=>1, 'iframe'=>1, 'td'=>1, 'th'=>1, 'img'=>1, 'object'=>1, 'applet'=>1), 'href'=>array('a'=>1, 'area'=>1), 'hreflang'=>array('a'=>1), 'hspace'=>array('applet'=>1, 'img'=>1, 'object'=>1), 'ismap'=>array('img'=>1, 'input'=>1), 'label'=>array('option'=>1, 'optgroup'=>1), 'language'=>array('script'=>1), 'longdesc'=>array('img'=>1, 'iframe'=>1), 'marginheight'=>array('iframe'=>1), 'marginwidth'=>array('iframe'=>1), 'maxlength'=>array('input'=>1), 'method'=>array('form'=>1), 'model'=>array('embed'=>1), 'multiple'=>array('select'=>1), 'name'=>array('button'=>1, 'embed'=>1, 'textarea'=>1, 'applet'=>1, 'select'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'a'=>1, 'input'=>1, 'object'=>1, 'map'=>1, 'param'=>1), 'nohref'=>array('area'=>1), 'noshade'=>array('hr'=>1), 'nowrap'=>array('td'=>1, 'th'=>1), 'object'=>array('applet'=>1), 'onblur'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'onchange'=>array('input'=>1, 'select'=>1, 'textarea'=>1), 'onfocus'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'onreset'=>array('form'=>1), 'onselect'=>array('input'=>1, 'textarea'=>1), 'onsubmit'=>array('form'=>1), 'pluginspage'=>array('embed'=>1), 'pluginurl'=>array('embed'=>1), 'prompt'=>array('isindex'=>1), 'readonly'=>array('textarea'=>1, 'input'=>1), 'rel'=>array('a'=>1), 'rev'=>array('a'=>1), 'rows'=>array('textarea'=>1), 'rowspan'=>array('td'=>1, 'th'=>1), 'rules'=>array('table'=>1), 'scope'=>array('td'=>1, 'th'=>1), 'scrolling'=>array('iframe'=>1), 'selected'=>array('option'=>1), 'shape'=>array('area'=>1, 'a'=>1), 'size'=>array('hr'=>1, 'font'=>1, 'input'=>1, 'select'=>1), 'span'=>array('col'=>1, 'colgroup'=>1), 'src'=>array('embed'=>1, 'script'=>1, 'input'=>1, 'iframe'=>1, 'img'=>1), 'standby'=>array('object'=>1), 'start'=>array('ol'=>1), 'summary'=>array('table'=>1), 'tabindex'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'object'=>1, 'select'=>1, 'textarea'=>1), 'target'=>array('a'=>1, 'area'=>1, 'form'=>1), 'type'=>array('a'=>1, 'embed'=>1, 'object'=>1, 'param'=>1, 'script'=>1, 'input'=>1, 'li'=>1, 'ol'=>1, 'ul'=>1, 'button'=>1), 'usemap'=>array('img'=>1, 'input'=>1, 'object'=>1), 'valign'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'value'=>array('input'=>1, 'option'=>1, 'param'=>1, 'button'=>1, 'li'=>1), 'valuetype'=>array('param'=>1), 'vspace'=>array('applet'=>1, 'img'=>1, 'object'=>1), 'width'=>array('embed'=>1, 'hr'=>1, 'iframe'=>1, 'img'=>1, 'object'=>1, 'table'=>1, 'td'=>1, 'th'=>1, 'applet'=>1, 'col'=>1, 'colgroup'=>1, 'pre'=>1), 'wmode'=>array('embed'=>1), 'xml:space'=>array('pre'=>1, 'script'=>1, 'style'=>1)); // Ele-specific +static $aN = array('abbr'=>array('td'=>1, 'th'=>1), 'accept-charset'=>array('form'=>1), 'accept'=>array('form'=>1, 'input'=>1), 'accesskey'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'legend'=>1, 'textarea'=>1), 'action'=>array('form'=>1), 'align'=>array('caption'=>1, 'embed'=>1, 'applet'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'legend'=>1, 'table'=>1, 'hr'=>1, 'div'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'p'=>1, 'col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'alt'=>array('applet'=>1, 'area'=>1, 'img'=>1, 'input'=>1), 'archive'=>array('applet'=>1, 'object'=>1), 'axis'=>array('td'=>1, 'th'=>1), 'bgcolor'=>array('embed'=>1, 'table'=>1, 'tr'=>1, 'td'=>1, 'th'=>1), 'border'=>array('table'=>1, 'img'=>1, 'object'=>1), 'bordercolor'=>array('table'=>1, 'td'=>1, 'tr'=>1), 'cellpadding'=>array('table'=>1), 'cellspacing'=>array('table'=>1), 'char'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charoff'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charset'=>array('a'=>1, 'script'=>1), 'checked'=>array('input'=>1), 'cite'=>array('blockquote'=>1, 'q'=>1, 'del'=>1, 'ins'=>1), 'classid'=>array('object'=>1), 'clear'=>array('br'=>1), 'code'=>array('applet'=>1), 'codebase'=>array('object'=>1, 'applet'=>1), 'codetype'=>array('object'=>1), 'color'=>array('font'=>1), 'cols'=>array('textarea'=>1), 'colspan'=>array('td'=>1, 'th'=>1), 'compact'=>array('dir'=>1, 'dl'=>1, 'menu'=>1, 'ol'=>1, 'ul'=>1), 'coords'=>array('area'=>1, 'a'=>1), 'data'=>array('object'=>1), 'datetime'=>array('del'=>1, 'ins'=>1), 'declare'=>array('object'=>1), 'defer'=>array('script'=>1), 'dir'=>array('bdo'=>1), 'disabled'=>array('button'=>1, 'input'=>1, 'optgroup'=>1, 'option'=>1, 'select'=>1, 'textarea'=>1), 'enctype'=>array('form'=>1), 'face'=>array('font'=>1), 'flashvars'=>array('embed'=>1), 'for'=>array('label'=>1), 'frame'=>array('table'=>1), 'frameborder'=>array('iframe'=>1), 'headers'=>array('td'=>1, 'th'=>1), 'height'=>array('embed'=>1, 'iframe'=>1, 'td'=>1, 'th'=>1, 'img'=>1, 'object'=>1, 'applet'=>1), 'href'=>array('a'=>1, 'area'=>1), 'hreflang'=>array('a'=>1), 'hspace'=>array('applet'=>1, 'img'=>1, 'object'=>1), 'ismap'=>array('img'=>1, 'input'=>1), 'label'=>array('option'=>1, 'optgroup'=>1), 'language'=>array('script'=>1), 'longdesc'=>array('img'=>1, 'iframe'=>1), 'marginheight'=>array('iframe'=>1), 'marginwidth'=>array('iframe'=>1), 'maxlength'=>array('input'=>1), 'method'=>array('form'=>1), 'model'=>array('embed'=>1), 'multiple'=>array('select'=>1), 'name'=>array('button'=>1, 'embed'=>1, 'textarea'=>1, 'applet'=>1, 'select'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'a'=>1, 'input'=>1, 'object'=>1, 'map'=>1, 'param'=>1), 'nohref'=>array('area'=>1), 'noshade'=>array('hr'=>1), 'nowrap'=>array('td'=>1, 'th'=>1), 'object'=>array('applet'=>1), 'onblur'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'onchange'=>array('input'=>1, 'select'=>1, 'textarea'=>1), 'onfocus'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'onreset'=>array('form'=>1), 'onselect'=>array('input'=>1, 'textarea'=>1), 'onsubmit'=>array('form'=>1), 'pluginspage'=>array('embed'=>1), 'pluginurl'=>array('embed'=>1), 'prompt'=>array('isindex'=>1), 'readonly'=>array('textarea'=>1, 'input'=>1), 'rel'=>array('a'=>1), 'rev'=>array('a'=>1), 'rows'=>array('textarea'=>1), 'rowspan'=>array('td'=>1, 'th'=>1), 'rules'=>array('table'=>1), 'scope'=>array('td'=>1, 'th'=>1), 'scrolling'=>array('iframe'=>1), 'selected'=>array('option'=>1), 'shape'=>array('area'=>1, 'a'=>1), 'size'=>array('hr'=>1, 'font'=>1, 'input'=>1, 'select'=>1), 'span'=>array('col'=>1, 'colgroup'=>1), 'src'=>array('embed'=>1, 'script'=>1, 'input'=>1, 'iframe'=>1, 'img'=>1), 'standby'=>array('object'=>1), 'start'=>array('ol'=>1), 'summary'=>array('table'=>1), 'tabindex'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'object'=>1, 'select'=>1, 'textarea'=>1), 'target'=>array('a'=>1, 'area'=>1, 'form'=>1), 'type'=>array('a'=>1, 'embed'=>1, 'object'=>1, 'param'=>1, 'script'=>1, 'input'=>1, 'li'=>1, 'ol'=>1, 'ul'=>1, 'button'=>1), 'usemap'=>array('img'=>1, 'input'=>1, 'object'=>1), 'valign'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'value'=>array('input'=>1, 'option'=>1, 'param'=>1, 'button'=>1, 'li'=>1), 'valuetype'=>array('param'=>1), 'vspace'=>array('applet'=>1, 'img'=>1, 'object'=>1), 'width'=>array('embed'=>1, 'hr'=>1, 'iframe'=>1, 'img'=>1, 'object'=>1, 'table'=>1, 'td'=>1, 'th'=>1, 'applet'=>1, 'col'=>1, 'colgroup'=>1, 'pre'=>1), 'wmode'=>array('embed'=>1), 'xml:space'=>array('pre'=>1, 'script'=>1, 'style'=>1)); // Ele-specific static $aNE = array('checked'=>1, 'compact'=>1, 'declare'=>1, 'defer'=>1, 'disabled'=>1, 'ismap'=>1, 'multiple'=>1, 'nohref'=>1, 'noresize'=>1, 'noshade'=>1, 'nowrap'=>1, 'readonly'=>1, 'selected'=>1); // Empty static $aNP = array('action'=>1, 'cite'=>1, 'classid'=>1, 'codebase'=>1, 'data'=>1, 'href'=>1, 'longdesc'=>1, 'model'=>1, 'pluginspage'=>1, 'pluginurl'=>1, 'usemap'=>1); // Need scheme check; excludes style, on* & src static $aNU = array('class'=>array('param'=>1, 'script'=>1), 'dir'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'id'=>array('script'=>1), 'lang'=>array('applet'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'xml:lang'=>array('applet'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'onclick'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'ondblclick'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeydown'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeypress'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeyup'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmousedown'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmousemove'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseout'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseover'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseup'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'style'=>array('param'=>1, 'script'=>1), 'title'=>array('param'=>1, 'script'=>1)); // Univ & exceptions @@ -472,8 +470,8 @@ while(strlen($a)){ $aA[$nm] = ''; } break; case 2: // Val - if(preg_match('`^"[^"]*"`', $a, $m) or preg_match("`^'[^']*'`", $a, $m) or preg_match("`^\s*[^\s\"']+`", $a, $m)){ - $m = $m[0]; $w = 1; $mode = 0; $a = ltrim(substr_replace($a, '', 0, strlen($m))); + if(preg_match('`^((?:"[^"]*")|(?:\'[^\']*\')|(?:\s*[^\s"\']+))(.*)`', $a, $m)){ + $a = ltrim($m[2]); $m = $m[1]; $w = 1; $mode = 0; $aA[$nm] = trim(($m[0] == '"' or $m[0] == '\'') ? substr($m, 1, -1) : $m); } break; @@ -500,7 +498,7 @@ foreach($aA as $k=>$v){ static $sC = array(' '=>' ', ' '=>' ', 'E'=>'e', 'E'=>'e', 'e'=>'e', 'e'=>'e', 'X'=>'x', 'X'=>'x', 'x'=>'x', 'x'=>'x', 'P'=>'p', 'P'=>'p', 'p'=>'p', 'p'=>'p', 'S'=>'s', 'S'=>'s', 's'=>'s', 's'=>'s', 'I'=>'i', 'I'=>'i', 'i'=>'i', 'i'=>'i', 'O'=>'o', 'O'=>'o', 'o'=>'o', 'o'=>'o', 'N'=>'n', 'N'=>'n', 'n'=>'n', 'n'=>'n', 'U'=>'u', 'U'=>'u', 'u'=>'u', 'u'=>'u', 'R'=>'r', 'R'=>'r', 'r'=>'r', 'r'=>'r', 'L'=>'l', 'L'=>'l', 'l'=>'l', 'l'=>'l', '('=>'(', '('=>'(', ')'=>')', ')'=>')', ' '=>':', ' '=>':', '"'=>'"', '"'=>'"', '''=>"'", '''=>"'", '/'=>'/', '/'=>'/', '*'=>'*', '*'=>'*', '\'=>'\\', '\'=>'\\'); $v = strtr($v, $sC); } - $v = preg_replace_callback('`(url(?:\()(?: )*(?:\'|"|&(?:quot|apos);)?)(.+)((?:\'|"|&(?:quot|apos);)?(?: )*(?:\)))`iS', 'hl_prot', $v); + $v = preg_replace_callback('`(url(?:\()(?: )*(?:\'|"|&(?:quot|apos);)?)(.+?)((?:\'|"|&(?:quot|apos);)?(?: )*(?:\)))`iS', 'hl_prot', $v); $v = !$C['css_expression'] ? preg_replace('`expression`i', ' ', preg_replace('`\\\\\S|(/|(%2f))(\*|(%2a))`i', ' ', $v)) : $v; }elseif(isset($aNP[$k]) or strpos($k, 'src') !== false or $k[0] == 'o'){ $v = str_replace("\xad", ' ', (strpos($v, '&') !== false ? str_replace(array('­', '­', '­'), ' ', $v) : $v)); @@ -643,7 +641,7 @@ return ''; function hl_tidy($t, $w, $p){ // Tidy/compact HTM if(strpos(' pre,script,textarea', "$p,")){return $t;} -$t = str_replace(' </', '</', preg_replace(array('`(<\w[^>]*(?<!/)>)\s+`', '`\s+`', '`(<\w[^>]*(?<!/)>) `'), array(' $1', ' ', '$1'), preg_replace_callback(array('`(<(!\[CDATA\[))(.+?)(\]\]>)`sm', '`(<(!--))(.+?)(-->)`sm', '`(<(pre|script|textarea).*?>)(.+?)(</\2>)`sm'), create_function('$m', 'return $m[1]. str_replace(array("<", ">", "\n", "\r", "\t", " "), array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), $m[3]). $m[4];'), $t))); +$t = str_replace(' </', '</', preg_replace(array('`(<\w[^>]*(?<!/)>)\s+`', '`\s+`', '`(<\w[^>]*(?<!/)>) `'), array(' $1', ' ', '$1'), preg_replace_callback(array('`(<(!\[CDATA\[))(.+?)(\]\]>)`sm', '`(<(!--))(.+?)(-->)`sm', '`(<(pre|script|textarea)[^>]*?>)(.+?)(</\2>)`sm'), create_function('$m', 'return $m[1]. str_replace(array("<", ">", "\n", "\r", "\t", " "), array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), $m[3]). $m[4];'), $t))); if(($w = strtolower($w)) == -1){ return str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), array('<', '>', "\n", "\r", "\t", ' '), $t); } @@ -688,7 +686,7 @@ return str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), array( function hl_version(){ // rel -return '1.1.9'; +return '1.1.11'; // eof } diff --git a/mod/htmlawed/vendors/htmLawed/htmLawedTest.php b/mod/htmlawed/vendors/htmLawed/htmLawedTest.php index 160bd012d..806aa4641 100644..100755 --- a/mod/htmlawed/vendors/htmLawed/htmLawedTest.php +++ b/mod/htmlawed/vendors/htmLawed/htmLawedTest.php @@ -1,10 +1,10 @@ <?php /* -htmLawedTest.php, 16 July 2009 -htmLawed 1.1.9, 22 December 2009 +htmLawedTest.php, 22 October 2011 +htmLawed 1.1.11, 5 June 2012 Copyright Santosh Patnaik -GPL v3 license +Dual licensed with LGPL 3 and GPL 2 or later A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed Test htmLawed; user provides text input; input and processed input are shown as highlighted code and rendered HTML; also shown are execution time and peak memory usage @@ -44,7 +44,9 @@ if(get_magic_quotes_gpc()){ } ini_set('magic_quotes_gpc', 0); } -set_magic_quotes_runtime(0); +if(get_magic_quotes_runtime()){ + set_magic_quotes_runtime(0); +} $_POST['enc'] = (isset($_POST['enc']) and preg_match('`^[-\w]+$`', $_POST['enc'])) ? $_POST['enc'] : 'utf-8'; @@ -328,7 +330,7 @@ tRs = { a.appendChild(document.createTextNode("\u2195")); a.style.cursor = 'n-resize'; a.className= 'resizer'; - a.title = 'click-drag to resize' + a.title = 'click-drag to resize textarea' tRs.adEv(a, 'mousedown', tRs.initResize); textareas[i].parentNode.appendChild(a); } @@ -420,7 +422,7 @@ else{ } ?> -<span style="float:right;" class="help"><span style="font-size: 85%;">Encoding: </span><input type="text" size="8" id="enc" name="enc" style="vertical-align: middle;" value="<?php echo htmlspecialchars($_POST['enc']); ?>" title="IANA-recognized name of the input character-set; can be multiple ;- or space-separated values; may not work in some browsers" /></span> +<span style="float:right;" class="help" title="IANA-recognized name of the input character-set; can be multiple ;- or space-separated values; may not work in some browsers"><span style="font-size: 85%;">Encoding: </span><input type="text" size="8" id="enc" name="enc" style="vertical-align: middle;" value="<?php echo htmlspecialchars($_POST['enc']); ?>" /></span> </div> <br style="clear:both;" /> @@ -454,6 +456,7 @@ $cfg = array( 'comment'=>array('4', 'nil', 'allow HTML comments', 'nil'), 'css_expression'=>array('2', 'nil', 'allow dynamic expressions in CSS style properties', 'nil'), 'deny_attribute'=>array('1', '0', 'denied attributes', '0', '50', '', 'these'), +'direct_list_nest'=>array('2', 'nil', 'allow direct nesting of a list within another without requiring it to be a list item', 'nil'), 'elements'=>array('', '', 'allowed elements', '50'), 'hexdec_entity'=>array('3', '1', 'convert hexadecimal numeric entities to decimal ones, or vice versa', '0'), 'hook'=>array('', '', 'name of hook function', '25'), @@ -516,23 +519,23 @@ if($do){ } } - if($cfg['anti_link_spam'] && (!empty($cfg['anti_link_spam11']) or !empty($cfg['anti_link_spam12']))){ + if(isset($cfg['anti_link_spam']) && $cfg['anti_link_spam'] && (!empty($cfg['anti_link_spam11']) or !empty($cfg['anti_link_spam12']))){ $cfg['anti_link_spam'] = array($cfg['anti_link_spam11'], $cfg['anti_link_spam12']); } unset($cfg['anti_link_spam11'], $cfg['anti_link_spam12']); - if($cfg['anti_mail_spam'] == 1){ + if(isset($cfg['anti_mail_spam']) && $cfg['anti_mail_spam'] == 1){ $cfg['anti_mail_spam'] = isset($cfg['anti_mail_spam1'][0]) ? $cfg['anti_mail_spam1'] : 0; } unset($cfg['anti_mail_spam11']); - if($cfg['deny_attribute'] == 1){ + if(isset($cfg['deny_attribute']) && $cfg['deny_attribute'] == 1){ $cfg['deny_attribute'] = isset($cfg['deny_attribute1'][0]) ? $cfg['deny_attribute1'] : 0; } unset($cfg['deny_attribute1']); - if($cfg['tidy'] == 2){ + if(isset($cfg['tidy']) && $cfg['tidy'] == 2){ $cfg['tidy'] = isset($cfg['tidy2'][0]) ? $cfg['tidy2'] : 0; } unset($cfg['tidy2']); - if($cfg['unique_ids'] == 2){ + if(isset($cfg['unique_ids']) && $cfg['unique_ids'] == 2){ $cfg['unique_ids'] = isset($cfg['unique_ids2'][0]) ? $cfg['unique_ids2'] : 1; } unset($cfg['unique_ids2']); @@ -540,9 +543,9 @@ if($do){ $cfg['show_setting'] = 'hlcfg'; $st = microtime(); - $out = htmLawed($_POST['text'], $cfg, str_replace(array('$', '{'), '', $_POST['spec'])); + $out = htmLawed($_POST['text'], $cfg, $_POST['spec']); $et = microtime(); - echo '<br /><a href="htmLawedTest.php" title="[toggle visibility] syntax-highlighted" onclick="javascript:toggle(\'inputR\'); return false;"><span class="notice">Input code »</span></a> <span class="help" title="tags estimated as half of total > and < chars; values may be inaccurate for non-ASCII text"><small><big>', strlen($_POST['text']), '</big> chars, ~<big>', round((substr_count($_POST['text'], '>') + substr_count($_POST['text'], '<'))/2), '</big> tags</small> </span><div id="inputR" style="display: none;">', format($_POST['text']), '</div><script type="text/javascript">hl(\'inputR\');</script>', (!isset($_POST['text'][$_hlimit]) ? ' <a href="htmLawedTest.php" title="[toggle visibility] hexdump; non-viewable characters like line-returns are shown as dots" onclick="javascript:toggle(\'inputD\'); return false;"><span class="notice">Input binary » </span></a><div id="inputD" style="display: none;">'. hexdump($_POST['text']). '</div>' : ''), ' <a href="htmLawedTest.php" title="[toggle visibility] finalized internal settings as interpreted by htmLawed; for developers" onclick="javascript:toggle(\'settingF\'); return false;"><span class="notice">Finalized internal settings » </span></a> <div id="settingF" style="display: none;">', str_replace(array(' ', "\t", ' '), array(' ', ' ', ' '), nl2br(htmlspecialchars(print_r($GLOBALS['hlcfg']['config'], true)))), '</div><script type="text/javascript">hl(\'settingF\');</script>', '<br /><a href="htmLawedTest.php" title="[toggle visibility] suitable for copy-paste" onclick="javascript:toggle(\'outputF\'); return false;"><span class="notice">Output »</span></a> <span class="help" title="approx., server-specific value excluding the \'include()\' call"><small>htmLawed processing time <big>', number_format(((substr($et,0,9)) + (substr($et,-10)) - (substr($st,0,9)) - (substr($st,-10))),4), '</big> s</small></span>', (($mem = memory_get_peak_usage()) !== false ? '<span class="help"><small>, peak memory usage <big>'. round(($mem-$pre_mem)/1048576, 2). '</big> <small>MB</small>' : ''), '</small></span><div id="outputF" style="display: block;"><div><textarea id="text2" class="textarea" name="text2" rows="5" cols="100" style="width: 100%;">', htmlspecialchars($out), '</textarea></div><button type="button" onclick="javascript:document.getElementById(\'text2\').focus();document.getElementById(\'text2\').select()" title="select all to copy" style="float:right;">Select all</button>'; + echo '<br /><a href="htmLawedTest.php" title="[toggle visibility] syntax-highlighted" onclick="javascript:toggle(\'inputR\'); return false;"><span class="notice">Input code »</span></a> <span class="help" title="tags estimated as half of total > and < chars; values may be inaccurate for non-ASCII text"><small><big>', strlen($_POST['text']), '</big> chars, ~<big>', ($tag = round((substr_count($_POST['text'], '>') + substr_count($_POST['text'], '<'))/2)), '</big> tag', ($tag > 1 ? 's' : ''), '</small> </span><div id="inputR" style="display: none;">', format($_POST['text']), '</div><script type="text/javascript">hl(\'inputR\');</script>', (!isset($_POST['text'][$_hlimit]) ? ' <a href="htmLawedTest.php" title="[toggle visibility] hexdump; non-viewable characters like line-returns are shown as dots" onclick="javascript:toggle(\'inputD\'); return false;"><span class="notice">Input binary » </span></a><div id="inputD" style="display: none;">'. hexdump($_POST['text']). '</div>' : ''), ' <a href="htmLawedTest.php" title="[toggle visibility] finalized internal settings as interpreted by htmLawed; for developers" onclick="javascript:toggle(\'settingF\'); return false;"><span class="notice">Finalized internal settings » </span></a> <div id="settingF" style="display: none;">', str_replace(array(' ', "\t", ' '), array(' ', ' ', ' '), nl2br(htmlspecialchars(print_r($GLOBALS['hlcfg']['config'], true)))), '</div><script type="text/javascript">hl(\'settingF\');</script>', '<br /><a href="htmLawedTest.php" title="[toggle visibility] suitable for copy-paste" onclick="javascript:toggle(\'outputF\'); return false;"><span class="notice">Output »</span></a> <span class="help" title="approx., server-specific value excluding the \'include()\' call"><small>htmLawed processing time <big>', number_format(((substr($et,0,9)) + (substr($et,-10)) - (substr($st,0,9)) - (substr($st,-10))),4), '</big> s</small></span>', (($mem = memory_get_peak_usage()) !== false ? '<span class="help"><small>, peak memory usage <big>'. round(($mem-$pre_mem)/1048576, 2). '</big> <small>MB</small>' : ''), '</small></span><div id="outputF" style="display: block;"><div><textarea id="text2" class="textarea" name="text2" rows="5" cols="100" style="width: 100%;">', htmlspecialchars($out), '</textarea></div><button type="button" onclick="javascript:document.getElementById(\'text2\').focus();document.getElementById(\'text2\').select()" title="select all to copy" style="float:right;">Select all</button>'; if($_w3c_validate && $validation) { ?> diff --git a/mod/htmlawed/vendors/htmLawed/htmLawed_README.htm b/mod/htmlawed/vendors/htmLawed/htmLawed_README.htm index 7138ee9c0..6dd78fb2e 100644 --- a/mod/htmlawed/vendors/htmLawed/htmLawed_README.htm +++ b/mod/htmlawed/vendors/htmLawed/htmLawed_README.htm @@ -7,40 +7,74 @@ <meta name="keywords" content="htmLawed, HTM, HTML, HTML Tidy, converter, filter, formatter, purifier, sanitizer, XSS, input, PHP, software, code, script, security, cross-site scripting, hack, sanitize, remove, standards, tags, attributes, elements, htmLawed_README.txt, rTxt2htm, PHP Labware" /> <style type="text/css" media="all"> <!--/*--><![CDATA[/*><!--*/ -a {text-decoration:none; color: blue;}
-a:hover {color: red;}
-a:visited {color: blue;}
-body {margin: 0; padding: 0;}
-body, div, html, p {font-family: Georgia, 'Times new roman', Times;}
-code.code {font-family: 'Bitstream vera sans mono', 'Courier New', 'Courier', monospace;}
-div.comment {padding: 5px; color: #999999; font-size: 80%;}
-div.comment a {color: #6699cc;}
-div#body {width: 70%; margin: 5px; padding: 5px;} /* holds non-toc content */
-div#toc {position: fixed; top: 5px; left: 73%; z-index: 2; margin-top: 5px; margin-left: 5px; border: 1px solid gray; padding: 5px; background-color: #ededed; width: 23%; overflow: auto; max-height:94%; font-size: 90%;} /* holds content table (toc) */
-div#top {font-size: 14px; margin: 5px; padding: 5px;} /* holds all content */
-div.monospace {overflow: auto; font-family: 'Bitstream vera sans mono', 'Courier New', 'Courier', monospace;}
-div.sub-section {padding-left: 15px;}
-div.sub-sub-section {padding-left: 30px;}
-h1 {font-size: 22px; margin-top: 5px; margin-bottom: 5px;}
-h2 {font-size: 20px; float: left; margin-top: 15px; margin-bottom: 5px;}
-h3 {font-size: 18px; float: left; margin-top: 15px; margin-bottom: 5px;}
-h4 {font-size: 16px; float: left; margin-top: 15px; margin-bottom: 5px;}
-hr {margin-top: 15px; margin-bottom: 5px;}
-input, textarea {font-family: 'Bitstream vera sans mono', 'Courier New', 'Courier', monospace;}
-p.subtle {color: gray; padding: 0; padding-top: 10px; margin: 0;}
-p.subtle a, p.subtle a:visited {color: #6699cc;}
-span.item-no {color: black;}
-span.subtle {color: gray; margin: 0; padding:0;}
-span.subtle a, span.subtle a:visited {color: #6699cc;}
-span.term {font-family: 'Bitstream vera sans mono', 'Courier New', 'Courier', monospace;}
-span.toc-item {color: black;}
-span.totop {float: right; margin-top: 15px; margin-bottom: 5px;}
-span.totop a, span.totop a:visited {color: #6699cc;}
-@media screen { /* fixes for old IE */
- * html, * html body {overflow-y: auto!important; height: 100%; margin: 0; padding: 0;}
- * html div#body {height: 100%; overflow-y: auto; position: relative;}
- * html div#toc {position: absolute;}
-}
+a {text-decoration:none; color: blue;} + +a:hover {color: red;} + +a:visited {color: blue;} + +body {margin: 0; padding: 0;} + +body, div, html, p {font-family: Georgia, 'Times new roman', Times;} + +code.code {font-family: 'Bitstream vera sans mono', 'Courier New', 'Courier', monospace;} + +div.comment {padding: 5px; color: #999999; font-size: 80%;} + +div.comment a {color: #6699cc;} + +div#body {width: 70%; margin: 5px; padding: 5px;} /* holds non-toc content */ + +div#toc {position: fixed; top: 5px; left: 73%; z-index: 2; margin-top: 5px; margin-left: 5px; border: 1px solid gray; padding: 5px; background-color: #ededed; width: 23%; overflow: auto; max-height:94%; font-size: 90%;} /* holds content table (toc) */ + +div#top {font-size: 14px; margin: 5px; padding: 5px;} /* holds all content */ + +div.monospace {overflow: auto; font-family: 'Bitstream vera sans mono', 'Courier New', 'Courier', monospace;} + +div.sub-section {padding-left: 15px;} + +div.sub-sub-section {padding-left: 30px;} + +h1 {font-size: 22px; margin-top: 5px; margin-bottom: 5px;} + +h2 {font-size: 20px; float: left; margin-top: 15px; margin-bottom: 5px;} + +h3 {font-size: 18px; float: left; margin-top: 15px; margin-bottom: 5px;} + +h4 {font-size: 16px; float: left; margin-top: 15px; margin-bottom: 5px;} + +hr {margin-top: 15px; margin-bottom: 5px;} + +input, textarea {font-family: 'Bitstream vera sans mono', 'Courier New', 'Courier', monospace;} + +p.subtle {color: gray; padding: 0; padding-top: 10px; margin: 0;} + +p.subtle a, p.subtle a:visited {color: #6699cc;} + +span.item-no {color: black;} + +span.subtle {color: gray; margin: 0; padding:0;} + +span.subtle a, span.subtle a:visited {color: #6699cc;} + +span.term {font-family: 'Bitstream vera sans mono', 'Courier New', 'Courier', monospace;} + +span.toc-item {color: black;} + +span.totop {float: right; margin-top: 15px; margin-bottom: 5px;} + +span.totop a, span.totop a:visited {color: #6699cc;} + +@media screen { /* fixes for old IE */ + + * html, * html body {overflow-y: auto!important; height: 100%; margin: 0; padding: 0;} + + * html div#body {height: 100%; overflow-y: auto; position: relative;} + + * html div#toc {position: absolute;} + +} + /*]]>*/--> </style> <title>htmLawed documentation | htmLawed PHP software is a free, open-source, customizable HTML input purifier and filter</title> @@ -110,10 +144,10 @@ span.totop a, span.totop a:visited {color: #6699cc;} <div id="body"> <br /> -<div class="comment">htmLawed_README.txt, 22 December 2009<br /> -htmLawed 1.1.9, 22 December 2009<br /> +<div class="comment">htmLawed_README.txt, 8 June 2012<br /> +htmLawed 1.1.11, 5 June 2012<br /> Copyright Santosh Patnaik<br /> -GPL v3 license<br /> +Dual licensed with LGPL 3 and GPL 2 or later<br /> A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed">http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed</a> </div> <br /> @@ -222,7 +256,7 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <a name="s1.4" id="s1.4"></a><span class="item-no">1.4</span>  License & copyright </h3><span class="totop"><a href="#peak">(to top)</a></span><br style="clear: both;" /> <br /> -  htmLawed is free and open-source software licensed under GPL license version <a href="http://www.gnu.org/licenses/gpl-3.0.txt">3</a>, and copyrighted by Santosh Patnaik, MD, PhD.<br /> +  htmLawed is free and open-source software dual licensed under LGPL license version <a href="http://www.gnu.org/licenses/lgpl-3.0.txt">3</a> and GPL license version <a href="http://www.gnu.org/licenses/gpl-2.0.txt">2</a> or later, and copyrighted by Santosh Patnaik, MD, PhD.<br /> </div> <div class="sub-section"><h3> @@ -254,9 +288,11 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <a name="s2" id="s2"></a><span class="item-no">2</span>  Usage </h2><span class="totop"><a href="#peak">(to top)</a></span><br style="clear: both;" /> <br /> -  htmLawed should work with PHP 4.3 and higher. Either <span class="term">include()</span> the <span class="term">htmLawed.php</span> file or copy-paste the entire code.<br /> +  htmLawed should work with PHP 4.4 and higher. Either <span class="term">include()</span> the <span class="term">htmLawed.php</span> file or copy-paste the entire code.<br /> <br />   To easily <strong>test</strong> htmLawed using a form-based interface, use the provided <a href="htmLawedTest.php">demo</a> (<span class="term">htmLawed.php</span> and <span class="term">htmLawedTest.php</span> should be in the same directory on the web-server).<br /> +<br /> +  <strong>Note</strong>: For code for usage of the htmLawed class (for htmLawed in OOP), please refer to the <a href="http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed">htmLawed</a> website; the filtering itself can be configured, etc., as described here.<br /> <div class="sub-section"><h3> <a name="s2.1" id="s2.1"></a><span class="item-no">2.1</span>  Simple @@ -371,6 +407,12 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl   <span class="term">string</span> - dictated by values in <span class="term">string</span><br />   <span class="term">on*</span> (like <span class="term">onfocus</span>) attributes not allowed - "<br /> <br /> +  <strong>direct_nest_list</strong><br /> +  Allow direct nesting of a list within another without requiring it to be a list item; see <a href="#s3.3.4">section 3.3.4</a><br /> +<br /> +  <span class="term">0</span> - no  *<br /> +  <span class="term">1</span> - yes<br /> +<br />   <strong>elements</strong><br />   Allowed HTML elements; see <a href="#s3.3">section 3.3</a><br /> <br /> @@ -441,11 +483,11 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl   <span class="term">1</span> - will auto-adjust other relevant <span class="term">$config</span> parameters (indicated by <span class="term">"</span> in this list)<br /> <br />   <strong>schemes</strong><br /> -  Array of attribute-specific, comma-separated, lower-cased list of schemes (protocols) allowed in attributes accepting URLs; <span class="term">*</span> covers all unspecified attributes; see <a href="#s3.4.3">section 3.4.3</a><br /> +  Array of attribute-specific, comma-separated, lower-cased list of schemes (protocols) allowed in attributes accepting URLs (or <span class="term">!</span> to <em>deny</em> any URL); <span class="term">*</span> covers all unspecified attributes; see <a href="#s3.4.3">section 3.4.3</a><br /> <br />   <span class="term">href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; *:file, http, https</span>  *<br />   <span class="term">*: ftp, gopher, http, https, mailto, news, nntp, telnet</span>  ^<br /> -  <span class="term">href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; style: nil; *:file, http, https</span>  "<br /> +  <span class="term">href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; style: !; *:file, http, https</span>  "<br /> <br />   <strong>show_setting</strong><br />   Name of a PHP variable to assign the <em>finalized</em> <span class="term">$config</span> and <span class="term">$spec</span> values; see <a href="#s3.8">section 3.8</a><br /> @@ -541,7 +583,7 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl   <em>Rule</em>: <span class="term">input=title(), value(maxval=8/default=6)</span><br />   <em>Output</em>: <span class="term"><input title="WIDTH" value="6" /><input title="length" value="5" /></span><br /> <br /> -  <em>Rule</em>: <span class="term">input=title(nomatch=$w.d$i), value(match=$em$/default=6em)</span><br /> +  <em>Rule</em>: <span class="term">input=title(nomatch=%w.d%i), value(match=%em%/default=6em)</span><br />   <em>Output</em>: <span class="term"><input value="10em" /><input title="length" value="6em" /></span><br /> <br />   <em>Rule</em>: <span class="term">input=title(oneof=height|depth/default=depth), value(noneof=5|6)</span><br /> @@ -565,9 +607,9 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <a name="s2.5" id="s2.5"></a><span class="item-no">2.5</span>  Some security risks to keep in mind </h3><span class="totop"><a href="#peak">(to top)</a></span><br style="clear: both;" /> <br /> -  When setting the parameters/arguments (like those to allow certain HTML elements) for use with htmLawed, one should bear in mind that the setting may let through potentially <em>dangerous</em> HTML code. (This may not be a problem if the authors are trusted.)<br /> +  When setting the parameters/arguments (like those to allow certain HTML elements) for use with htmLawed, one should bear in mind that the setting may let through potentially <em>dangerous</em> HTML code which is meant to steal user-data, deface a website, render a page non-functional, etc.<br /> <br /> -  For example, following increase security risks:<br /> +  Unless end-users, either people or software, supplying the content are completely trusted, security issues arising from the degree of HTML usage permission has to be kept in mind. For example, following increase security risks:<br /> <br />   *  Allowing <span class="term">script</span>, <span class="term">applet</span>, <span class="term">embed</span>, <span class="term">iframe</span> or <span class="term">object</span> elements, or certain of their attributes like <span class="term">allowscriptaccess</span><br /> <br /> @@ -575,7 +617,13 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <br />   *  Allowing dynamic CSS expressions (a feature of the IE browser)<br /> <br /> -  <em>Unsafe</em> HTML can be removed by setting <span class="term">$config</span> appropriately. E.g., <span class="term">$config["elements"] = "* -script"</span> (<a href="#s3.3">section 3.3</a>), <span class="term">$config["safe"] = 1</span> (<a href="#s3.6">section 3.6</a>), etc.<br /> +  *  Allowing the <span class="term">style</span> attribute<br /> +<br /> +  To remove <em>unsecure</em> HTML, code-developers using htmLawed must set <span class="term">$config</span> appropriately. E.g., <span class="term">$config["elements"] = "* -script"</span> to deny the <span class="term">script</span> element (<a href="#s3.3">section 3.3</a>), <span class="term">$config["safe"] = 1</span> to auto-configure ceratin htmLawed parameters for maximizing security (<a href="#s3.6">section 3.6</a>), etc.<br /> +<br /> +  Permitting the <span class="term">*style*</span> attribute brings in risks of <em>click-jacking</em>, <em>phishing</em>, web-page overlays, etc., <em>even</em> when the <span class="term">safe</span> parameter is enabled (see <a href="#s3.6">section 3.6</a>). Except for URLs and a few other things like CSS dynamic expressions, htmLawed currently does not check every CSS style property. It does provide ways for the code-developer implementing htmLawed to do such checks through htmLawed's <span class="term">$spec</span> argument, and through the <span class="term">hook_tag</span> parameter (see <a href="#s3.4.8">section 3.4.8</a> for more). Disallowing <span class="term">style</span> completely and relying on CSS classes and stylesheet files is recommended.<br /> +<br /> +  htmLawed does not check or correct the character <strong>encoding</strong> of the input it receives. In conjunction with permitting circumstances such as when the character encoding is left undefined through HTTP headers or HTML <span class="term">meta</span> tags, this can permit an exploit (like Google's UTF-7/XSS vulnerability of the past).<br /> </div> <div class="sub-section"><h3> @@ -722,6 +770,8 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <br />   *  Because of poor Unicode support in PHP, htmLawed does not remove the <em>high value</em> HTML-invalid characters with multi-byte code-points. Such characters however are extremely unlikely to be in the input. (see <a href="#s3.1">section 3.1</a>).<br /> <br /> +  *  htmLawed does not check or correct the character encoding of the input it receives. In conjunction with permitting circumstances such as when the character encoding is left undefined through HTTP headers or HTML <span class="term">meta</span> tags, this can permit an exploit (like Google's UTF-7/XSS vulnerability of the past).<br /> +<br />   *  Like any script using PHP's PCRE regex functions, PHP setup-specific low PCRE limit values can cause htmLawed to at least partially fail with very long input texts.<br /> </div> @@ -1162,6 +1212,8 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl   In some cases, the specs stipulate the number and/or the ordering of the child elements. A <span class="term">table</span> can have 0 or 1 <span class="term">caption</span>, <span class="term">tbody</span>, <span class="term">tfoot</span>, and <span class="term">thead</span>, but they must be in this order: <span class="term">caption</span>, <span class="term">thead</span>, <span class="term">tfoot</span>, <span class="term">tbody</span>.<br /> <br />   htmLawed currently does not check for conformance to these rules. Note that any non-compliance in this regard will not introduce security vulnerabilities, crash browser applications, or affect the rendering of web-pages.<br /> +<br /> +  With <span class="term">$config["direct_list_nest"]</span> set to <span class="term">1</span>, htmLawed will allow direct nesting of an <span class="term">ol</span> or <span class="term">ul</span> list within another <span class="term">ol</span> or <span class="term">ul</span> without requiring the child list to be within an <span class="term">li</span> of the parent list. While this is not standard-compliant, directly nested lists are rendered properly by almost all browsers. The parameter <span class="term">$config["direct_list_nest"]</span> has no effect if tag-balancing (<a href="#s3.3.3">section 3.3.3</a>) is turned off.<br /> </div> <div class="sub-section"><h3> @@ -1271,6 +1323,8 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <br />   As a side-note, one may find <span class="term">style: *</span> useful as URLs in <span class="term">style</span> attributes can be specified in a variety of ways, and the patterns that htmLawed uses to identify URLs may mistakenly identify non-URL text.<br /> <br /> +  <span class="term">!</span> can be put in the list of schemes to disallow all protocols as well as <em>local</em> URLs. Thus, with <span class="term">href: http, style: !</span>, '<a href="http://cnn.com" style="background-image: url('local.jpg');">CNN</a>' will become '<a href="http://cnn.com" style="background-image: url('denied:local.jpg');">CNN</a>'.<br /> +<br />   <strong>Note</strong>: If URL-accepting attributes other than those listed above are being allowed, then the scheme will not be checked unless the attribute name contains the string <span class="term">src</span> (e.g., <span class="term">dynsrc</span>) or starts with <span class="term">o</span> (e.g., <span class="term">onbeforecopy</span>).<br /> <br />   With <span class="term">$config["safe"] = 1</span>, all URLs are disallowed in the <span class="term">style</span> attribute values.<br /> @@ -1488,7 +1542,7 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <a name="s3.4.8" id="s3.4.8"></a><span class="item-no">3.4.8</span>  Inline style properties </h3><span class="totop"><a href="#peak">(to top)</a></span><br style="clear: both;" /> <br /> -  htmLawed can check URL schemes and dynamic expressions (to guard against Javascript, etc., script-based insecurities) in inline CSS style property values in the <span class="term">style</span> attributes. (CSS properties like <span class="term">background-image</span> that accept URLs in their values are noted in <a href="#s5.3">section 5.3</a>.) Dynamic CSS expressions that allow scripting in the IE browser, and can be a vulnerability, can be removed from property values by setting <span class="term">$config["css_expression"]</span> to <span class="term">1</span> (default setting).<br /> +  htmLawed can check URL schemes and dynamic expressions (to guard against Javascript, etc., script-based insecurities) in inline CSS style property values in the <span class="term">style</span> attributes. (CSS properties like <span class="term">background-image</span> that accept URLs in their values are noted in <a href="#s5.3">section 5.3</a>.) Dynamic CSS expressions that allow scripting in the IE browser, and can be a vulnerability, can be removed from property values by setting <span class="term">$config["css_expression"]</span> to <span class="term">1</span> (default setting). Note that when <span class="term">$config["css_expression"]</span> is set to <span class="term">1</span>, htmLawed will remove <span class="term">/*</span> from the <span class="term">style</span> values.<br /> <br />   <strong>Note</strong>: Because of the various ways of representing characters in attribute values (URL-escapement, entitification, etc.), htmLawed might alter the values of the <span class="term">style</span> attribute values, and may even falsely identify dynamic CSS expressions and URL schemes in them. If this is an important issue, checking of URLs and dynamic expressions can be turned off (<span class="term">$config["schemes"] = "...style:*..."</span>, see <a href="#s3.4.3">section 3.4.3</a>, and <span class="term">$config["css_expression"] = 0</span>). Alternately, admins can use their own custom function for finer handling of <span class="term">style</span> values through the <span class="term">hook_tag</span> parameter (see <a href="#s3.4.9">section 3.4.9</a>).<br /> <br /> @@ -1503,14 +1557,30 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <br />   It is possible to utilize a custom hook function to alter the tag content htmLawed has finalized (i.e., after it has checked/corrected for required attributes, transformed attributes, lower-cased attribute names, etc.).<br /> <br /> -  When <span class="term">$config</span> parameter <span class="term">hook_tag</span> is set to the name of a function, htmLawed (function <span class="term">hl_tag()</span>) will pass on the element name, and the <em>finalized</em> attribute name-value pairs as array elements to the function. The function is expected to return the full opening tag string like <span class="term"><element_name attribute_1_name="attribute_1_value"...></span> (for empty elements like <span class="term">img</span> and <span class="term">input</span>, the element-closing slash <span class="term">/</span> should also be included).<br /> +  When <span class="term">$config</span> parameter <span class="term">hook_tag</span> is set to the name of a function, htmLawed (function <span class="term">hl_tag()</span>) will pass on the element name, and, in the case of an opening tag, the <em>finalized</em> attribute name-value pairs as array elements to the function. The function, after completing a task such as filtering or tag transformation, will typically return an empty string, the full opening tag string like <span class="term"><element_name attribute_1_name="attribute_1_value"...></span> (for empty elements like <span class="term">img</span> and <span class="term">input</span>, the element-closing slash <span class="term">/</span> should also be included), etc.<br /> +<br /> +  Any <span class="term">hook_tag</span> function, since htmLawed version 1.1.11, also receives names of elements in closing tags, such as <span class="term">a</span> in the closing <span class="term"></a></span> tag of the element <span class="term"><a href="http://cnn.com">CNN</a></span>. Unlike for opening tags, no other value (i.e., the attribute name-value array) is passed to the function since a closing tag contains only element names. Typically, the function will return an empty string or a full closing tag (like <span class="term"></a></span>).<br /> <br />   This is a <strong>powerful functionality</strong> that can be exploited for various objectives: consolidate-and-convert inline <span class="term">style</span> attributes to <span class="term">class</span>, convert <span class="term">embed</span> elements to <span class="term">object</span>, permit only one <span class="term">caption</span> element in a <span class="term">table</span> element, disallow embedding of certain types of media, <strong>inject HTML</strong>, use <a href="http://csstidy.sourceforge.net">CSSTidy</a> to sanitize <span class="term">style</span> attribute values, etc.<br /> <br />   As an example, the custom hook code below can be used to force a series of specifically ordered <span class="term">id</span> attributes on all elements, and a specific <span class="term">param</span> element inside all <span class="term">object</span> elements:<br /> <br /> -<code class="code">    function my_tag_function($element, $attribute_array){</code> +<code class="code">    function my_tag_function($element, $attribute_array=0){</code> +<br /> +<br /> + +<code class="code">      // If second argument is not received, it means a closing tag is being handled</code> +<br /> + +<code class="code">      if(is_numeric($attribute_array)){</code> +<br /> + +<code class="code">        return "</$element>";</code> +<br /> + +<code class="code">      }</code> +<br /> <br /> <code class="code">      static $id = 0;</code> @@ -1570,6 +1640,11 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <code class="code">      }</code> <br /> +<br /> + +<code class="code">      static $empty_elements = array('area'=>1, 'br'=>1, 'col'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'param'=>1);</code> +<br /> +<br /> <code class="code">      return "<{$element}{$string}". (isset($in_array($element, $empty_elements) ? ' /' : ''). '>'. $new_element;</code> <br /> @@ -1598,7 +1673,7 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <br />   htmLawed allows an admin to use <span class="term">$config["safe"]</span> to auto-adjust multiple <span class="term">$config</span> parameters (such as <span class="term">elements</span> which declares the allowed element-set), which otherwise would have to be manually set. The relevant parameters are indicated by <span class="term">"</span> in <a href="#s2.2">section 2.2</a>). Thus, one can pass the <span class="term">$config</span> argument with a simpler value.<br /> <br /> -  With the value of <span class="term">1</span>, htmLawed considers <span class="term">CDATA</span> sections and HTML comments as plain text, and prohibits the <span class="term">applet</span>, <span class="term">embed</span>, <span class="term">iframe</span>, <span class="term">object</span> and <span class="term">script</span> elements, and the <span class="term">on*</span> attributes like <span class="term">onclick</span>. ( There are <span class="term">$config</span> parameters like <span class="term">css_expression</span> that are not affected by the value set for <span class="term">safe</span> but whose default values still contribute towards a more <em>safe</em> output.) Further, URLs with schemes (see <a href="#s3.4.3">section 3.4.3</a>) are neutralized so that, e.g., <span class="term">style="moz-binding:url(http://danger)"</span> becomes <span class="term">style="moz-binding:url(denied:http://danger)"</span> while <span class="term">style="moz-binding:url(ok)"</span> remains intact.<br /> +  With the value of <span class="term">1</span>, htmLawed considers <span class="term">CDATA</span> sections and HTML comments as plain text, and prohibits the <span class="term">applet</span>, <span class="term">embed</span>, <span class="term">iframe</span>, <span class="term">object</span> and <span class="term">script</span> elements, and the <span class="term">on*</span> attributes like <span class="term">onclick</span>. ( There are <span class="term">$config</span> parameters like <span class="term">css_expression</span> that are not affected by the value set for <span class="term">safe</span> but whose default values still contribute towards a more <em>safe</em> output.) Further, URLs with schemes (see <a href="#s3.4.3">section 3.4.3</a>) are neutralized so that, e.g., <span class="term">style="moz-binding:url(http://danger)"</span> becomes <span class="term">style="moz-binding:url(denied:http://danger)"</span>.<br /> <br />   Admins, however, may still want to completely deny the <span class="term">style</span> attribute, e.g., with code like<br /> <br /> @@ -1606,6 +1681,8 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <code class="code">    $processed = htmLawed($text, array('safe'=>1, 'deny_attribute'=>'style'));</code> <br /> <br /> +  Permitting the <span class="term">style</span> attribute brings in risks of <em>click-jacking</em>, etc. CSS property values can render a page non-functional or be used to deface it. Except for URLs, dynamic expressions, and some other things, htmLawed does not completely check <span class="term">style</span> values. It does provide ways for the code-developer implementing htmLawed to do such checks through the <span class="term">$spec</span> argument, and through the <span class="term">hook_tag</span> parameter (see <a href="#s3.4.8">section 3.4.8</a> for more). Disallowing style completely and relying on CSS classes and stylesheet files is recommended.<br /> +<br />   If a value for a parameter auto-set through <span class="term">safe</span> is still manually provided, then that value can over-ride the auto-set value. E.g., with <span class="term">$config["safe"] = 1</span> and <span class="term">$config["elements"] = "*+script"</span>, <span class="term">script</span>, but not <span class="term">applet</span>, is allowed.<br /> <br />   A page illustrating the efficacy of htmLawed's anti-XSS abilities with <span class="term">safe</span> set to <span class="term">1</span> against XSS vectors listed by <a href="http://ha.ckers.org/xss.html">RSnake</a> may be available <a href="http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/rsnake/RSnakeXSSTest.htm">here</a>.<br /> @@ -1688,6 +1765,20 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <br />   <em>Version number - Release date. Notes</em><br /> <br /> +  1.1.11 - 5 June 2012. Fix for possible problem with handling of multi-byte characters in attribute values in an mbstring.func_overload enviroment. <span class="term">$config["hook_tag"]</span>, if specified, now receives names of elements in closing tags.<br /> +<br /> +  1.1.10 - 22 October 2011. Fix for a bug in the <span class="term">tidy</span> functionality that caused the entire input to be replaced with a single space; new parameter, <span class="term">$config["direct_list_nest"]</span> to allow direct descendance of a list in a list. (5 April 2012. Dual licensing from LGPLv3 to LGPLv3 and GPLv2+.)<br /> +<br /> +  1.1.9.5 - 6 July 2011. Minor correction of a rule for nesting of <span class="term">li</span> within <span class="term">dir</span><br /> +<br /> +  1.1.9.4 - 3 July 2010. Parameter <span class="term">schemes</span> now accepts <span class="term">!</span> so any URL, even a local one, can be <em>denied</em>. An issue in which a second URL value in <span class="term">style</span> properties was not checked was fixed.<br /> +<br /> +  1.1.9.3 - 17 May 2010. Checks for correct nesting of <span class="term">param</span><br /> +<br /> +  1.1.9.2 - 26 April 2010. Minor fix regarding rendering of denied URL schemes<br /> +<br /> +  1.1.9.1 - 26 February 2010. htmLawed now uses the LGPL version 3 license; support for <span class="term">flashvars</span> attribute for <span class="term">embed</span><br /> +<br />   1.1.9 - 22 December 2009. Soft-hyphens are now removed only from URL-accepting attribute values<br /> <br />   1.1.8.1 - 16 July 2009. Minor code-change to fix a PHP error notice<br /> @@ -1738,6 +1829,10 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <br />   Upgrading is as simple as replacing the previous version of <span class="term">htmLawed.php</span> (assuming it was not modified for customized features). As htmLawed output is almost always used in static documents, upgrading should not affect old, finalized content.<br /> <br /> +  <strong>Important</strong>  The following upgrades may affect the functionality of a specific htmLawed as indicated by their corresponding notes:<br /> +<br /> +  (1) From version 1.1-1.1.10 to 1.1.11, if a <span class="term">hook_tag</span> function is in use: In version 1.1.11, elements in closing tags (and not just the opening tags) are also passed to the function. There are no attribute names/values to pass, so a <span class="term">hook_tag</span> function receives only the element name. The <span class="term">hook_tag</span> function therefore may have to be edited. See <a href="#s3.4.9">section 3.4.9</a>.<br /> +<br />   Old versions of htmLawed may be available online. E.g., for version 1.0, check <a href="http://www.bioinformatics.org/phplabware/downloads/htmLawed1.zip">http://www.bioinformatics.org/phplabware/downloads/htmLawed1.zip</a>, for 1.1.1, htmLawed111.zip, and for 1.1.10, htmLawed1110.zip.<br /> </div> @@ -1789,7 +1884,7 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl <a name="s4.10" id="s4.10"></a><span class="item-no">4.10</span>  Acknowledgements </h3><span class="totop"><a href="#peak">(to top)</a></span><br style="clear: both;" /> <br /> -  Bryan Blakey, Ulf Harnhammer, Gareth Heyes, Lukasz Pilorz, Shelley Powers, Edward Yang, and many anonymous users.<br /> +  Nicholas Alipaz, Bryan Blakey, Pádraic Brady, Ulf Harnhammer, Gareth Heyes, Klaus Leithoff, Lukasz Pilorz, Shelley Powers, Edward Yang, and many anonymous users.<br /> <br />   Thank you!<br /> @@ -1856,6 +1951,7 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl   disabled - button, input, optgroup, option, select, textarea<br />   enctype - form<br />   face - font<br /> +  flashvars* - embed<br />   for - label<br />   frame - table<br />   frameborder - iframe<br /> @@ -2057,7 +2153,7 @@ A PHP Labware internal utility - <a href="http://www.bioinformatics.org/phpl </div> </div> <br /> -<hr /><br /><br /><span class="subtle"><small>HTM version of <em><a href="htmLawed_README.txt">htmLawed_README.txt</a></em> generated on 22 Dec, 2009 using <a href="http://www.bioinformatics.org/phplabware/internal_utilities">rTxt2htm</a> from PHP Labware</small></span> +<hr /><br /><br /><span class="subtle"><small>HTM version of <em><a href="htmLawed_README.txt">htmLawed_README.txt</a></em> generated on 06 Jun, 2012 using <a href="http://www.bioinformatics.org/phplabware/internal_utilities">rTxt2htm</a> from PHP Labware</small></span> </div><!-- ended div body --> </div><!-- ended div top --> </body> diff --git a/mod/htmlawed/vendors/htmLawed/htmLawed_README.txt b/mod/htmlawed/vendors/htmLawed/htmLawed_README.txt index 48a67009b..e4027e465 100644..100755 --- a/mod/htmlawed/vendors/htmLawed/htmLawed_README.txt +++ b/mod/htmlawed/vendors/htmLawed/htmLawed_README.txt @@ -1,8 +1,8 @@ /* -htmLawed_README.txt, 22 December 2009 -htmLawed 1.1.9, 22 December 2009 +htmLawed_README.txt, 8 June 2012 +htmLawed 1.1.11, 5 June 2012 Copyright Santosh Patnaik -GPL v3 license +Dual licensed with LGPL 3 and GPL 2 or later A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed */ @@ -171,7 +171,7 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern -- 1.4 License & copyright ----------------------------------------o - htmLawed is free and open-source software licensed under GPL license version 3:- http://www.gnu.org/licenses/gpl-3.0.txt, and copyrighted by Santosh Patnaik, MD, PhD. + htmLawed is free and open-source software dual licensed under LGPL license version 3:- http://www.gnu.org/licenses/lgpl-3.0.txt and GPL license version 2:- http://www.gnu.org/licenses/gpl-2.0.txt or later, and copyrighted by Santosh Patnaik, MD, PhD. -- 1.5 Terms used here --------------------------------------------o @@ -200,9 +200,11 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern == 2 Usage ========================================================oo - htmLawed should work with PHP 4.3 and higher. Either 'include()' the 'htmLawed.php' file or copy-paste the entire code. + htmLawed should work with PHP 4.4 and higher. Either 'include()' the 'htmLawed.php' file or copy-paste the entire code. To easily *test* htmLawed using a form-based interface, use the provided demo:- htmLawedTest.php ('htmLawed.php' and 'htmLawedTest.php' should be in the same directory on the web-server). + + *Note*: For code for usage of the htmLawed class (for htmLawed in OOP), please refer to the htmLawed:- http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed website; the filtering itself can be configured, etc., as described here. -- 2.1 Simple ------------------------------------------------------ @@ -305,6 +307,12 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern '0' - none * 'string' - dictated by values in 'string' 'on*' (like 'onfocus') attributes not allowed - " + + *direct_nest_list* + Allow direct nesting of a list within another without requiring it to be a list item; see section:- #3.3.4 + + '0' - no * + '1' - yes *elements* Allowed HTML elements; see section:- #3.3 @@ -376,11 +384,11 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern '1' - will auto-adjust other relevant '$config' parameters (indicated by '"' in this list) *schemes* - Array of attribute-specific, comma-separated, lower-cased list of schemes (protocols) allowed in attributes accepting URLs; '*' covers all unspecified attributes; see section:- #3.4.3 + Array of attribute-specific, comma-separated, lower-cased list of schemes (protocols) allowed in attributes accepting URLs (or '!' to `deny` any URL); '*' covers all unspecified attributes; see section:- #3.4.3 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; *:file, http, https' * '*: ftp, gopher, http, https, mailto, news, nntp, telnet' ^ - 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; style: nil; *:file, http, https' " + 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; style: !; *:file, http, https' " *show_setting* Name of a PHP variable to assign the `finalized` '$config' and '$spec' values; see section:- #3.8 @@ -469,7 +477,7 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern `Rule`: 'input=title(), value(maxval=8/default=6)' `Output`: '<input title="WIDTH" value="6" /><input title="length" value="5" />' - `Rule`: 'input=title(nomatch=$w.d$i), value(match=$em$/default=6em)' + `Rule`: 'input=title(nomatch=%w.d%i), value(match=%em%/default=6em)' `Output`: '<input value="10em" /><input title="length" value="6em" />' `Rule`: 'input=title(oneof=height|depth/default=depth), value(noneof=5|6)' @@ -491,17 +499,23 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern -- 2.5 Some security risks to keep in mind ------------------------o - When setting the parameters/arguments (like those to allow certain HTML elements) for use with htmLawed, one should bear in mind that the setting may let through potentially `dangerous` HTML code. (This may not be a problem if the authors are trusted.) + When setting the parameters/arguments (like those to allow certain HTML elements) for use with htmLawed, one should bear in mind that the setting may let through potentially `dangerous` HTML code which is meant to steal user-data, deface a website, render a page non-functional, etc. - For example, following increase security risks: + Unless end-users, either people or software, supplying the content are completely trusted, security issues arising from the degree of HTML usage permission has to be kept in mind. For example, following increase security risks: * Allowing 'script', 'applet', 'embed', 'iframe' or 'object' elements, or certain of their attributes like 'allowscriptaccess' * Allowing HTML comments (some Internet Explorer versions are vulnerable with, e.g., '<!--[if gte IE 4]><script>alert("xss");</script><![endif]-->' * Allowing dynamic CSS expressions (a feature of the IE browser) + + * Allowing the 'style' attribute - `Unsafe` HTML can be removed by setting '$config' appropriately. E.g., '$config["elements"] = "* -script"' (section:- #3.3), '$config["safe"] = 1' (section:- #3.6), etc. + To remove `unsecure` HTML, code-developers using htmLawed must set '$config' appropriately. E.g., '$config["elements"] = "* -script"' to deny the 'script' element (section:- #3.3), '$config["safe"] = 1' to auto-configure ceratin htmLawed parameters for maximizing security (section:- #3.6), etc. + + Permitting the '*style*' attribute brings in risks of `click-jacking`, `phishing`, web-page overlays, etc., `even` when the 'safe' parameter is enabled (see section:- #3.6). Except for URLs and a few other things like CSS dynamic expressions, htmLawed currently does not check every CSS style property. It does provide ways for the code-developer implementing htmLawed to do such checks through htmLawed's '$spec' argument, and through the 'hook_tag' parameter (see section:- #3.4.8 for more). Disallowing 'style' completely and relying on CSS classes and stylesheet files is recommended. + + htmLawed does not check or correct the character *encoding* of the input it receives. In conjunction with permitting circumstances such as when the character encoding is left undefined through HTTP headers or HTML 'meta' tags, this can permit an exploit (like Google's UTF-7/XSS vulnerability of the past). -- 2.6 Use without modifying old 'kses()' code --------------------o @@ -614,6 +628,8 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern * htmLawed does not correct certain possible attribute-based security vulnerabilities (e.g., '<a href="http://x%22+style=%22background-image:xss">x</a>'). These arise when browsers mis-identify markup in `escaped` text, defeating the very purpose of escaping text (a bad browser will read the given example as '<a href="http://x" style="background-image:xss">x</a>'). * Because of poor Unicode support in PHP, htmLawed does not remove the `high value` HTML-invalid characters with multi-byte code-points. Such characters however are extremely unlikely to be in the input. (see section:- #3.1). + + * htmLawed does not check or correct the character encoding of the input it receives. In conjunction with permitting circumstances such as when the character encoding is left undefined through HTTP headers or HTML 'meta' tags, this can permit an exploit (like Google's UTF-7/XSS vulnerability of the past). * Like any script using PHP's PCRE regex functions, PHP setup-specific low PCRE limit values can cause htmLawed to at least partially fail with very long input texts. @@ -925,6 +941,8 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern In some cases, the specs stipulate the number and/or the ordering of the child elements. A 'table' can have 0 or 1 'caption', 'tbody', 'tfoot', and 'thead', but they must be in this order: 'caption', 'thead', 'tfoot', 'tbody'. htmLawed currently does not check for conformance to these rules. Note that any non-compliance in this regard will not introduce security vulnerabilities, crash browser applications, or affect the rendering of web-pages. + + With '$config["direct_list_nest"]' set to '1', htmLawed will allow direct nesting of an 'ol' or 'ul' list within another 'ol' or 'ul' without requiring the child list to be within an 'li' of the parent list. While this is not standard-compliant, directly nested lists are rendered properly by almost all browsers. The parameter '$config["direct_list_nest"]' has no effect if tag-balancing (section:- #3.3.3) is turned off. -- 3.3.5 Beautify or compact HTML ---------------------------------o @@ -1020,6 +1038,8 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern Thus, `to allow Javascript`, one can set '$config["schemes"]' as 'href: mailto, http, https; *: http, https, javascript', or 'href: mailto, http, https, javascript; *: http, https, javascript', or '*: *', and so on. As a side-note, one may find 'style: *' useful as URLs in 'style' attributes can be specified in a variety of ways, and the patterns that htmLawed uses to identify URLs may mistakenly identify non-URL text. + + '!' can be put in the list of schemes to disallow all protocols as well as `local` URLs. Thus, with 'href: http, style: !', '<a href="http://cnn.com" style="background-image: url('local.jpg');">CNN</a>' will become '<a href="http://cnn.com" style="background-image: url('denied:local.jpg');">CNN</a>'. *Note*: If URL-accepting attributes other than those listed above are being allowed, then the scheme will not be checked unless the attribute name contains the string 'src' (e.g., 'dynsrc') or starts with 'o' (e.g., 'onbeforecopy'). @@ -1149,7 +1169,7 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern -- 3.4.8 Inline style properties ----------------------------------o - htmLawed can check URL schemes and dynamic expressions (to guard against Javascript, etc., script-based insecurities) in inline CSS style property values in the 'style' attributes. (CSS properties like 'background-image' that accept URLs in their values are noted in section:- #5.3.) Dynamic CSS expressions that allow scripting in the IE browser, and can be a vulnerability, can be removed from property values by setting '$config["css_expression"]' to '1' (default setting). + htmLawed can check URL schemes and dynamic expressions (to guard against Javascript, etc., script-based insecurities) in inline CSS style property values in the 'style' attributes. (CSS properties like 'background-image' that accept URLs in their values are noted in section:- #5.3.) Dynamic CSS expressions that allow scripting in the IE browser, and can be a vulnerability, can be removed from property values by setting '$config["css_expression"]' to '1' (default setting). Note that when '$config["css_expression"]' is set to '1', htmLawed will remove '/*' from the 'style' values. *Note*: Because of the various ways of representing characters in attribute values (URL-escapement, entitification, etc.), htmLawed might alter the values of the 'style' attribute values, and may even falsely identify dynamic CSS expressions and URL schemes in them. If this is an important issue, checking of URLs and dynamic expressions can be turned off ('$config["schemes"] = "...style:*..."', see section:- #3.4.3, and '$config["css_expression"] = 0'). Alternately, admins can use their own custom function for finer handling of 'style' values through the 'hook_tag' parameter (see section:- #3.4.9). @@ -1163,13 +1183,21 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern It is possible to utilize a custom hook function to alter the tag content htmLawed has finalized (i.e., after it has checked/corrected for required attributes, transformed attributes, lower-cased attribute names, etc.). - When '$config' parameter 'hook_tag' is set to the name of a function, htmLawed (function 'hl_tag()') will pass on the element name, and the `finalized` attribute name-value pairs as array elements to the function. The function is expected to return the full opening tag string like '<element_name attribute_1_name="attribute_1_value"...>' (for empty elements like 'img' and 'input', the element-closing slash '/' should also be included). + When '$config' parameter 'hook_tag' is set to the name of a function, htmLawed (function 'hl_tag()') will pass on the element name, and, in the case of an opening tag, the `finalized` attribute name-value pairs as array elements to the function. The function, after completing a task such as filtering or tag transformation, will typically return an empty string, the full opening tag string like '<element_name attribute_1_name="attribute_1_value"...>' (for empty elements like 'img' and 'input', the element-closing slash '/' should also be included), etc. + + Any 'hook_tag' function, since htmLawed version 1.1.11, also receives names of elements in closing tags, such as 'a' in the closing '</a>' tag of the element '<a href="http://cnn.com">CNN</a>'. Unlike for opening tags, no other value (i.e., the attribute name-value array) is passed to the function since a closing tag contains only element names. Typically, the function will return an empty string or a full closing tag (like '</a>'). This is a *powerful functionality* that can be exploited for various objectives: consolidate-and-convert inline 'style' attributes to 'class', convert 'embed' elements to 'object', permit only one 'caption' element in a 'table' element, disallow embedding of certain types of media, *inject HTML*, use CSSTidy:- http://csstidy.sourceforge.net to sanitize 'style' attribute values, etc. As an example, the custom hook code below can be used to force a series of specifically ordered 'id' attributes on all elements, and a specific 'param' element inside all 'object' elements: - function my_tag_function($element, $attribute_array){ + function my_tag_function($element, $attribute_array=0){ + + // If second argument is not received, it means a closing tag is being handled + if(is_numeric($attribute_array)){ + return "</$element>"; + } + static $id = 0; // Remove any duplicate element if($element == 'param' && isset($attribute_array['allowscriptaccess'])){ @@ -1192,6 +1220,9 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern foreach($attribute_array as $k=>$v){ $string .= " {$k}=\"{$v}\""; } + + static $empty_elements = array('area'=>1, 'br'=>1, 'col'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'param'=>1); + return "<{$element}{$string}". (isset($in_array($element, $empty_elements) ? ' /' : ''). '>'. $new_element; } @@ -1213,12 +1244,14 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern htmLawed allows an admin to use '$config["safe"]' to auto-adjust multiple '$config' parameters (such as 'elements' which declares the allowed element-set), which otherwise would have to be manually set. The relevant parameters are indicated by '"' in section:- #2.2). Thus, one can pass the '$config' argument with a simpler value. - With the value of '1', htmLawed considers 'CDATA' sections and HTML comments as plain text, and prohibits the 'applet', 'embed', 'iframe', 'object' and 'script' elements, and the 'on*' attributes like 'onclick'. ( There are '$config' parameters like 'css_expression' that are not affected by the value set for 'safe' but whose default values still contribute towards a more `safe` output.) Further, URLs with schemes (see section:- #3.4.3) are neutralized so that, e.g., 'style="moz-binding:url(http://danger)"' becomes 'style="moz-binding:url(denied:http://danger)"' while 'style="moz-binding:url(ok)"' remains intact. + With the value of '1', htmLawed considers 'CDATA' sections and HTML comments as plain text, and prohibits the 'applet', 'embed', 'iframe', 'object' and 'script' elements, and the 'on*' attributes like 'onclick'. ( There are '$config' parameters like 'css_expression' that are not affected by the value set for 'safe' but whose default values still contribute towards a more `safe` output.) Further, URLs with schemes (see section:- #3.4.3) are neutralized so that, e.g., 'style="moz-binding:url(http://danger)"' becomes 'style="moz-binding:url(denied:http://danger)"'. Admins, however, may still want to completely deny the 'style' attribute, e.g., with code like $processed = htmLawed($text, array('safe'=>1, 'deny_attribute'=>'style')); + Permitting the 'style' attribute brings in risks of `click-jacking`, etc. CSS property values can render a page non-functional or be used to deface it. Except for URLs, dynamic expressions, and some other things, htmLawed does not completely check 'style' values. It does provide ways for the code-developer implementing htmLawed to do such checks through the '$spec' argument, and through the 'hook_tag' parameter (see section:- #3.4.8 for more). Disallowing style completely and relying on CSS classes and stylesheet files is recommended. + If a value for a parameter auto-set through 'safe' is still manually provided, then that value can over-ride the auto-set value. E.g., with '$config["safe"] = 1' and '$config["elements"] = "*+script"', 'script', but not 'applet', is allowed. A page illustrating the efficacy of htmLawed's anti-XSS abilities with 'safe' set to '1' against XSS vectors listed by RSnake:- http://ha.ckers.org/xss.html may be available here:- http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/rsnake/RSnakeXSSTest.htm. @@ -1288,6 +1321,20 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern `Version number - Release date. Notes` + 1.1.11 - 5 June 2012. Fix for possible problem with handling of multi-byte characters in attribute values in an mbstring.func_overload enviroment. '$config["hook_tag"]', if specified, now receives names of elements in closing tags. + + 1.1.10 - 22 October 2011. Fix for a bug in the 'tidy' functionality that caused the entire input to be replaced with a single space; new parameter, '$config["direct_list_nest"]' to allow direct descendance of a list in a list. (5 April 2012. Dual licensing from LGPLv3 to LGPLv3 and GPLv2+.) + + 1.1.9.5 - 6 July 2011. Minor correction of a rule for nesting of 'li' within 'dir' + + 1.1.9.4 - 3 July 2010. Parameter 'schemes' now accepts '!' so any URL, even a local one, can be `denied`. An issue in which a second URL value in 'style' properties was not checked was fixed. + + 1.1.9.3 - 17 May 2010. Checks for correct nesting of 'param' + + 1.1.9.2 - 26 April 2010. Minor fix regarding rendering of denied URL schemes + + 1.1.9.1 - 26 February 2010. htmLawed now uses the LGPL version 3 license; support for 'flashvars' attribute for 'embed' + 1.1.9 - 22 December 2009. Soft-hyphens are now removed only from URL-accepting attribute values 1.1.8.1 - 16 July 2009. Minor code-change to fix a PHP error notice @@ -1336,6 +1383,10 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern Upgrading is as simple as replacing the previous version of 'htmLawed.php' (assuming it was not modified for customized features). As htmLawed output is almost always used in static documents, upgrading should not affect old, finalized content. + *Important* The following upgrades may affect the functionality of a specific htmLawed as indicated by their corresponding notes: + + (1) From version 1.1-1.1.10 to 1.1.11, if a 'hook_tag' function is in use: In version 1.1.11, elements in closing tags (and not just the opening tags) are also passed to the function. There are no attribute names/values to pass, so a 'hook_tag' function receives only the element name. The 'hook_tag' function therefore may have to be edited. See section:- #3.4.9. + Old versions of htmLawed may be available online. E.g., for version 1.0, check http://www.bioinformatics.org/phplabware/downloads/htmLawed1.zip, for 1.1.1, htmLawed111.zip, and for 1.1.10, htmLawed1110.zip. @@ -1382,7 +1433,7 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern -- 4.10 Acknowledgements ------------------------------------------o - Bryan Blakey, Ulf Harnhammer, Gareth Heyes, Lukasz Pilorz, Shelley Powers, Edward Yang, and many anonymous users. + Nicholas Alipaz, Bryan Blakey, Pádraic Brady, Ulf Harnhammer, Gareth Heyes, Klaus Leithoff, Lukasz Pilorz, Shelley Powers, Edward Yang, and many anonymous users. Thank you! @@ -1446,6 +1497,7 @@ A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/intern disabled - button, input, optgroup, option, select, textarea enctype - form face - font + flashvars* - embed for - label frame - table frameborder - iframe diff --git a/mod/htmlawed/vendors/htmLawed/htmLawed_TESTCASE.txt b/mod/htmlawed/vendors/htmLawed/htmLawed_TESTCASE.txt index ea24b1839..793a5a6a7 100644..100755 --- a/mod/htmlawed/vendors/htmLawed/htmLawed_TESTCASE.txt +++ b/mod/htmlawed/vendors/htmLawed/htmLawed_TESTCASE.txt @@ -1,8 +1,8 @@ /* -htmLawed_TESTCASE.txt, 22 December 2009 -htmLawed 1.1.9, 22 December 2009 +htmLawed_TESTCASE.txt, 22 October 2011 +htmLawed 1.1.11, 5 June 2012 Copyright Santosh Patnaik -GPL v3 license +Dual licensed with LGPL 3 and GPL 2 or later A PHP Labware internal utility - http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed */ @@ -94,6 +94,15 @@ The PHP <s>software</s> script used for this <strike>web-page</strike> webpage i <area href="5" shape="Rect" coords="0,0,118,28"> </map></object> +<param name="name">value</param> + +<object id="obj1"> + <param name="param1"> + <object id="obj2"> + <param name="param2"> + </object> +</object> + <h6>Complex-4: nested and other tables</h6> <table border="1" bgcolor="red"> <tr> <td> Cell </td> <td colspan="2" rowspan="2"> <table border="1" bgcolor="green"> <tr> <td> Cell </td> <td colspan="2" rowspan="2"> </td> </tr> <tr> <td> Cell </td> </tr> <tr> <td> Cell </td> <td> Cell </td> <td> Cell </td> </tr> </table> </td> </tr> <tr> <td> Cell </td> </tr> <tr> <td> Cell </td> <td> Cell </td> <td> Cell </td> </tr> </table><br /> @@ -181,10 +190,13 @@ text <img src="none" alt="none" /> <b>t<em> e <strong> x </strong> t</em></b> <h6>HTML comments (also CDATA)</h6> -Special characters inside: <!-- <![CDATA check ]]> -->, <!-- 3 < 4 > 3.5, & 4 > 4 -->, <!-- che--ck -->, <!--[if !IE]> <--><a>c</a><!--> <![endif]--><br /> -Normal: <!-- check -->, <!--check -->, <em>comment:<!-- check --></em><!-- check -->, <table><!-- check --><tr><td>text not allowed</td></tr></table><br /> -Malformed: <![cdata check ]]>, < ![CDATA check ]]>, < ![CDATA check ] ]><br /> -Invalid: <em <!-- check -->>comment in tag content</em>, <!--check--> +<strong>Script inside:</strong> <!--[if gte IE 4]> +<SCRIPT>alert('XSS');</SCRIPT> +<![endif]--><br /> +<strong>Special characters inside: <!-- <![CDATA check ]]> -->, <!-- 3 < 4 > 3.5, & 4 > 4 -->, <!-- che--ck -->, <!--[if !IE]> <--><a>c</a><!--> <![endif]--><br /> +<strong>Normal:</strong> <!-- check -->, <!--check -->, <em>comment:<!-- check --></em><!-- check -->, <table><!-- check --><tr><td>text not allowed</td></tr></table><br /> +<strong>Malformed:</strong> <![cdata check ]]>, < ![CDATA check ]]>, < ![CDATA check ] ]><br /> +Invalid:</strong> <em <!-- check -->>comment in tag content</em>, <!--check--> <h6>Ins-Del</h6> @@ -224,6 +236,11 @@ Invalid: <em <!-- check -->>comment in tag content</em>, <!--check--> <li>l3</li> <li>l4<ol><li>lo3</li><li>lo4<ol><li>lo5</li></ol></li></ol></li> </ul><br /> +<strong>Nested, directly</strong>: <ul> + <li>l1</li> + <ol>l2</ol> + <li>l3</li> +</ul><br /> <strong>Nested, close-tags omitted</strong>: <ul> <li>l1</li> <li>l2<ol><li>lo1<li>lo2</ol> @@ -242,6 +259,13 @@ Invalid: <em <!-- check -->>comment in tag content</em>, <!--check--> </li></ul> </td></tr></table></li></ol> +<h6>Microdata</h6> + +<div itemscope itemtype="http://data-vocabulary.org/Person"> +I am <span itemprop="name">X</span> but people call me <span itemprop="nickname">Y</span>. +Find me at <a href="http://www.xy.com" itemprop="url">www.xy.com</a> +</div> + <h6>Non-English text-1</h6> InscrieÅ£i-vă acum la a Zecea Conferinţă InternaÅ£ională<br /> @@ -320,7 +344,8 @@ na Alemanha. <strong>Relative and absolute:</strong> <a href="mailto:x"></a>, <a href="http://a.com/b/c/d.f"></a>, <a href="./../d.f"></a>, <a href="./d.f"></a>, <a href="d.f"></a>, <a href="#s"></a>, <a href="./../../d.f#s"></a><br /> (try base URL value of 'http://a.com/b/')<br /> <strong>CSS URLs:</strong> <div style="background-image: url('a.gif');"></div>, <div style="background-image: URL("a.gif");"></div>, <div style="background-image: url('http://a.com/a.gif');"></div>, <div style="background-image: url('./../a.gif');"></div>, <div style="background-image: url('js:xss')"></div><br /> -<strong>Anti-spam:</strong> (try regex for 'http://a.com', etc.) <a href="mailto:x@y.com"></a>, <a href="http://a.com/b@d.f"></a>, <a href="a.com/d.f" rel="nofollow"></a>, <a href="a.com/d.f" rel="1, 2"></a>, <a href="a.com/d.f"></a>, <a href="b.com/d.f"></a>, <a href="c.com/d.f"></a><br /> +<strong>Double URLs:</strong> <a style="behaviour: url(foo) url(http://example.com/xss.htc)">b</a><br /> +<strong>Anti-spam:</strong> (try regex for 'http://a.com', etc.) <a href="mailto:x@y.com"></a>, <a href="http://a.com/b@d.f"></a>, <a href="a.com/d.f" rel="nofollow"></a>, <a href="a.com/d.f" rel="1, 2"></a>, <a href="a.com/d.f"></a>, <a href="b.com/d.f"></a>, <a href="c.com/d.f">, <a href="denied:http://c.com/d.f"></a><br /> <h6>XSS</h6> diff --git a/mod/likes/actions/likes/delete.php b/mod/likes/actions/likes/delete.php index db3036bb4..88cb84467 100644 --- a/mod/likes/actions/likes/delete.php +++ b/mod/likes/actions/likes/delete.php @@ -4,17 +4,12 @@ * */ -$likes = elgg_get_annotations(array( - 'guid' => (int) get_input('guid'), - 'annotation_owner_guid' => elgg_get_logged_in_user_guid(), - 'annotation_name' => 'likes', -)); -if ($likes) { - if ($likes[0]->canEdit()) { - $likes[0]->delete(); - system_message(elgg_echo("likes:deleted")); - forward(REFERER); - } +$id = (int) get_input('id'); +$like = elgg_get_annotation_from_id($id); +if ($like && $like->canEdit()) { + $like->delete(); + system_message(elgg_echo("likes:deleted")); + forward(REFERER); } register_error(elgg_echo("likes:notdeleted")); diff --git a/mod/likes/languages/en.php b/mod/likes/languages/en.php index 4a98d7cfe..b9460aa10 100644 --- a/mod/likes/languages/en.php +++ b/mod/likes/languages/en.php @@ -17,6 +17,7 @@ $english = array( 'likes:userlikedthis' => '%s like', 'likes:userslikedthis' => '%s likes', 'likes:river:annotate' => 'likes', + 'likes:delete:confirm' => 'Are you sure you want to unlike this?', 'river:likes' => 'likes %s %s', diff --git a/mod/likes/views/default/annotation/likes.php b/mod/likes/views/default/annotation/likes.php index d41522fc4..abd4df823 100644 --- a/mod/likes/views/default/annotation/likes.php +++ b/mod/likes/views/default/annotation/likes.php @@ -29,9 +29,9 @@ $friendlytime = elgg_view_friendly_time($like->time_created); if ($like->canEdit()) { $delete_button = elgg_view("output/confirmlink",array( - 'href' => "action/likes/delete?annotation_id={$like->id}", + 'href' => "action/likes/delete?id={$like->id}", 'text' => "<span class=\"elgg-icon elgg-icon-delete float-alt\"></span>", - 'confirm' => elgg_echo('deleteconfirm'), + 'confirm' => elgg_echo('likes:delete:confirm'), 'encode_text' => false, )); } diff --git a/mod/likes/views/default/likes/button.php b/mod/likes/views/default/likes/button.php index bc7c8fd8a..956bbcb19 100644 --- a/mod/likes/views/default/likes/button.php +++ b/mod/likes/views/default/likes/button.php @@ -24,7 +24,13 @@ if (elgg_is_logged_in() && $vars['entity']->canAnnotate(0, 'likes')) { ); $likes_button = elgg_view('output/url', $params); } else { - $url = elgg_get_site_url() . "action/likes/delete?guid={$guid}"; + $like = elgg_get_annotations(array( + 'guid' => $guid, + 'annotation_owner_guid' => elgg_get_logged_in_user_guid(), + 'annotation_name' => 'likes', + )); + $like = $like[0]; + $url = elgg_get_site_url() . "action/likes/delete?id={$like->id}"; $params = array( 'href' => $url, 'text' => elgg_view_icon('thumbs-up-alt'), diff --git a/mod/messages/pages/messages/read.php b/mod/messages/pages/messages/read.php index d41551be4..19e3ecdd7 100644 --- a/mod/messages/pages/messages/read.php +++ b/mod/messages/pages/messages/read.php @@ -9,7 +9,7 @@ gatekeeper(); $message = get_entity(get_input('guid')); if (!$message) { - forward(); + forward('messages/inbox'); } // mark the message as read diff --git a/mod/messages/start.php b/mod/messages/start.php index 1a2709324..2e61d6e21 100644 --- a/mod/messages/start.php +++ b/mod/messages/start.php @@ -356,16 +356,10 @@ function messages_count_unread() { "msg_msg.name_id='{$map['msg']}' AND msg_msg.value_id='{$map[1]}'", ), 'owner_guid' => $user_guid, - 'limit' => 0 + 'count' => true, ); - $num_messages = elgg_get_entities_from_metadata($options); - - if (is_array($num_messages)) { - return sizeof($num_messages); - } - - return 0; + return elgg_get_entities_from_metadata($options); } /** diff --git a/mod/notifications/actions/groupsave.php b/mod/notifications/actions/groupsave.php index c304cb856..7838f7e63 100644 --- a/mod/notifications/actions/groupsave.php +++ b/mod/notifications/actions/groupsave.php @@ -6,27 +6,42 @@ * @package ElggNotifications */ -// Load important global vars -global $NOTIFICATION_HANDLERS; +$current_user = elgg_get_logged_in_user_entity(); + +$guid = (int) get_input('guid', 0); +if (!$guid || !($user = get_entity($guid))) { + forward(); +} +if (($user->guid != $current_user->guid) && !$current_user->isAdmin()) { + forward(); +} // Get group memberships and condense them down to an array of guids $groups = array(); -if ($groupmemberships = elgg_get_entities_from_relationship(array('relationship' => 'member', 'relationship_guid' => elgg_get_logged_in_user_guid(), 'types' => 'group', 'limit' => 9999))) { +$options = array( + 'relationship' => 'member', + 'relationship_guid' => $user->guid, + 'types' => 'group', + 'limit' => 9999, +); +if ($groupmemberships = elgg_get_entities_from_relationship($options)) { foreach($groupmemberships as $groupmembership) { $groups[] = $groupmembership->guid; } -} +} +// Load important global vars +global $NOTIFICATION_HANDLERS; foreach($NOTIFICATION_HANDLERS as $method => $foo) { $subscriptions[$method] = get_input($method.'subscriptions'); $personal[$method] = get_input($method.'personal'); $collections[$method] = get_input($method.'collections'); if (!empty($groups)) { foreach($groups as $group) { - if (in_array($group,$subscriptions[$method])) { - add_entity_relationship(elgg_get_logged_in_user_guid(), 'notify'.$method, $group); + if (in_array($group, $subscriptions[$method])) { + add_entity_relationship($user->guid, 'notify'.$method, $group); } else { - remove_entity_relationship(elgg_get_logged_in_user_guid(), 'notify'.$method, $group); + remove_entity_relationship($user->guid, 'notify'.$method, $group); } } } diff --git a/mod/notifications/actions/save.php b/mod/notifications/actions/save.php index 163b656aa..3fe0001a3 100644 --- a/mod/notifications/actions/save.php +++ b/mod/notifications/actions/save.php @@ -6,9 +6,18 @@ * @package ElggNotifications */ -$user = elgg_get_logged_in_user_entity(); +$current_user = elgg_get_logged_in_user_entity(); + +$guid = (int) get_input('guid', 0); +if (!$guid || !($user = get_entity($guid))) { + forward(); +} +if (($user->guid != $current_user->guid) && !$current_user->isAdmin()) { + forward(); +} global $NOTIFICATION_HANDLERS; +$subscriptions = array(); foreach($NOTIFICATION_HANDLERS as $method => $foo) { $subscriptions[$method] = get_input($method.'subscriptions'); $personal[$method] = get_input($method.'personal'); diff --git a/mod/notifications/groups.php b/mod/notifications/groups.php index 45fb94e83..3347d4054 100644 --- a/mod/notifications/groups.php +++ b/mod/notifications/groups.php @@ -3,16 +3,16 @@ * Elgg notifications plugin group index * * @package ElggNotifications + * + * @uses $user ElggUser */ -// Load Elgg framework -require_once(dirname(dirname(dirname(__FILE__))) . '/engine/start.php'); - -// Ensure only logged-in users can see this page -gatekeeper(); +if (!isset($user) || !($user instanceof ElggUser)) { + $url = 'notifications/group/' . elgg_get_logged_in_user_entity()->username; + forward($url); +} -elgg_set_page_owner_guid(elgg_get_logged_in_user_guid()); -$user = elgg_get_page_owner_entity(); +elgg_set_page_owner_guid($user->guid); // Set the context to settings elgg_set_context('settings'); @@ -27,12 +27,15 @@ $people = array(); $groupmemberships = elgg_get_entities_from_relationship(array( 'relationship' => 'member', - 'relationship_guid' => elgg_get_logged_in_user_guid(), + 'relationship_guid' => $user->guid, 'types' => 'group', 'limit' => 9999, )); -$body = elgg_view_form('notificationsettings/groupsave', array(), array('groups' => $groupmemberships)); +$body = elgg_view_form('notificationsettings/groupsave', array(), array( + 'groups' => $groupmemberships, + 'user' => $user, +)); $params = array( 'content' => $body, diff --git a/mod/notifications/index.php b/mod/notifications/index.php index 882389fde..cd1857f04 100644 --- a/mod/notifications/index.php +++ b/mod/notifications/index.php @@ -3,16 +3,16 @@ * Elgg notifications plugin index * * @package ElggNotifications + * + * @uses $user ElggUser */ -// Load Elgg framework -require_once(dirname(dirname(dirname(__FILE__))) . '/engine/start.php'); - -// Ensure only logged-in users can see this page -gatekeeper(); +if (!isset($user) || !($user instanceof ElggUser)) { + $url = 'notifications/personal/' . elgg_get_logged_in_user_entity()->username; + forward($url); +} -elgg_set_page_owner_guid(elgg_get_logged_in_user_guid()); -$user = elgg_get_page_owner_entity(); +elgg_set_page_owner_guid($user->guid); // Set the context to settings elgg_set_context('settings'); @@ -26,7 +26,7 @@ elgg_push_breadcrumb($title); $people = array(); if ($people_ents = elgg_get_entities_from_relationship(array( 'relationship' => 'notify', - 'relationship_guid' => elgg_get_logged_in_user_guid(), + 'relationship_guid' => $user->guid, 'types' => 'user', 'limit' => 99999, ))) { @@ -36,7 +36,10 @@ if ($people_ents = elgg_get_entities_from_relationship(array( } } -$body = elgg_view('notifications/subscriptions/form', array('people' => $people)); +$body = elgg_view('notifications/subscriptions/form', array( + 'people' => $people, + 'user' => $user, +)); $params = array( 'content' => $body, diff --git a/mod/notifications/languages/en.php b/mod/notifications/languages/en.php index b29c9df25..0f2ba2304 100644 --- a/mod/notifications/languages/en.php +++ b/mod/notifications/languages/en.php @@ -8,7 +8,7 @@ $english = array( 'notifications:subscriptions:personal:title' => 'Personal notifications', 'notifications:subscriptions:friends:title' => 'Friends', - 'notifications:subscriptions:friends:description' => 'The following is an automatic collection made up of your friends. To receive updates select below. This will affect the corresponding users in the main notification settings panel at the bottom of the page. ', + 'notifications:subscriptions:friends:description' => 'Below are collections of your friends. Selecting a collection turns on notifications for the users in that collection.', 'notifications:subscriptions:collections:edit' => 'To edit your shared access notifications, click here.', 'notifications:subscriptions:changesettings' => 'Notifications', diff --git a/mod/notifications/start.php b/mod/notifications/start.php index 761f17e40..b76b0aa1e 100644 --- a/mod/notifications/start.php +++ b/mod/notifications/start.php @@ -25,7 +25,7 @@ function notifications_plugin_init() { // update notifications when new friend or access collection membership elgg_register_event_handler('create', 'friend', 'notifications_update_friend_notify'); - elgg_register_plugin_hook_handler('access:collections:add-user', 'collection', 'notifications_update_collection_notify'); + elgg_register_plugin_hook_handler('access:collections:add_user', 'collection', 'notifications_update_collection_notify'); $actions_base = elgg_get_plugins_path() . 'notifications/actions'; elgg_register_action("notificationsettings/save", "$actions_base/save.php"); @@ -40,13 +40,25 @@ function notifications_plugin_init() { */ function notifications_page_handler($page) { + gatekeeper(); + $current_user = elgg_get_logged_in_user_entity(); + // default to personal notifications if (!isset($page[0])) { $page[0] = 'personal'; } + if (!isset($page[1])) { + forward("notifications/{$page[0]}/{$current_user->username}"); + } + + $user = get_user_by_username($page[1]); + if (($user->guid != $current_user->guid) && !$current_user->isAdmin()) { + forward(); + } $base = elgg_get_plugins_path() . 'notifications'; + // note: $user passed in switch ($page[0]) { case 'group': require "$base/groups.php"; @@ -66,12 +78,16 @@ function notifications_page_handler($page) { */ function notifications_plugin_pagesetup() { if (elgg_get_context() == "settings" && elgg_get_logged_in_user_guid()) { - $user = elgg_get_logged_in_user_entity(); + + $user = elgg_get_page_owner_entity(); + if (!$user) { + $user = elgg_get_logged_in_user_entity(); + } $params = array( 'name' => '2_a_user_notify', 'text' => elgg_echo('notifications:subscriptions:changesettings'), - 'href' => "notifications/personal", + 'href' => "notifications/personal/{$user->username}", ); elgg_register_menu_item('page', $params); @@ -79,7 +95,7 @@ function notifications_plugin_pagesetup() { $params = array( 'name' => '2_group_notify', 'text' => elgg_echo('notifications:subscriptions:changesettings:groups'), - 'href' => "notifications/group", + 'href' => "notifications/group/{$user->username}", ); elgg_register_menu_item('page', $params); } @@ -178,7 +194,7 @@ function notifications_update_collection_notify($event, $object_type, $returnval } if (in_array($collection_id, $collections_preferences)) { // notifications are on for this collection so we add/remove - if ($event == 'access:collections:add-user') { + if ($event == 'access:collections:add_user') { add_entity_relationship($user->guid, "notify$method", $member_guid); } elseif ($event == 'access:collections:remove_user') { // removing someone from an access collection is not a guarantee diff --git a/mod/notifications/views/default/forms/notificationsettings/groupsave.php b/mod/notifications/views/default/forms/notificationsettings/groupsave.php index 61b94ff8b..168639ab2 100644 --- a/mod/notifications/views/default/forms/notificationsettings/groupsave.php +++ b/mod/notifications/views/default/forms/notificationsettings/groupsave.php @@ -3,13 +3,18 @@ * Elgg notifications groups subscription form * * @package ElggNotifications + * + * @uses $vars['user'] ElggUser */ +/* @var ElggUser $user */ +$user = $vars['user']; + global $NOTIFICATION_HANDLERS; foreach ($NOTIFICATION_HANDLERS as $method => $foo) { $subsbig[$method] = elgg_get_entities_from_relationship(array( 'relationship' => 'notify' . $method, - 'relationship_guid' => elgg_get_logged_in_user_guid(), + 'relationship_guid' => $user->guid, 'types' => 'group', 'limit' => 99999, )); @@ -97,6 +102,7 @@ END; <?php } echo '<div class="elgg-foot mtm">'; + echo elgg_view('input/hidden', array('name' => 'guid', 'value' => $user->guid)); echo elgg_view('input/submit', array('value' => elgg_echo('save'))); echo '</div>'; diff --git a/mod/notifications/views/default/forms/notificationsettings/save.php b/mod/notifications/views/default/forms/notificationsettings/save.php index ff32d8558..9470256ca 100644 --- a/mod/notifications/views/default/forms/notificationsettings/save.php +++ b/mod/notifications/views/default/forms/notificationsettings/save.php @@ -1,13 +1,21 @@ <?php /** * Personal notifications form body + * + * @uses $vars['user'] ElggUser */ -echo elgg_view('notifications/subscriptions/personal'); -echo elgg_view('notifications/subscriptions/collections'); -echo elgg_view('notifications/subscriptions/forminternals'); +/* @var ElggUser $user */ +$user = $vars['user']; + +echo elgg_view('notifications/subscriptions/personal', $vars); +echo elgg_view('notifications/subscriptions/collections', $vars); +echo elgg_view('notifications/subscriptions/forminternals', $vars); ?> <div class="elgg-foot"> -<?php echo elgg_view('input/submit', array('value' => elgg_echo('save'))); ?> +<?php +echo elgg_view('input/hidden', array('name' => 'guid', 'value' => $user->guid)); +echo elgg_view('input/submit', array('value' => elgg_echo('save'))); +?> </div> diff --git a/mod/notifications/views/default/notifications/subscriptions/collections.php b/mod/notifications/views/default/notifications/subscriptions/collections.php index 28d9fb5b8..207b2e3b9 100644 --- a/mod/notifications/views/default/notifications/subscriptions/collections.php +++ b/mod/notifications/views/default/notifications/subscriptions/collections.php @@ -1,4 +1,12 @@ -<?php //@todo JS 1.8: no ?> +<?php +/** + * @uses $vars['user'] ElggUser + */ + +/* @var ElggUser $user */ +$user = $vars['user']; + +//@todo JS 1.8: no ?> <script type="text/javascript"> function setCollection(members, method, id) { @@ -42,7 +50,7 @@ </tr> <?php $members = array(); - if ($friends = get_user_friends(elgg_get_logged_in_user_guid(), '', 9999, 0)) { + if ($friends = get_user_friends($user->guid, '', 9999, 0)) { foreach($friends as $friend) { $members[] = $friend->guid; } @@ -63,7 +71,7 @@ $i = 0; foreach($NOTIFICATION_HANDLERS as $method => $foo) { $metaname = 'collections_notifications_preferences_' . $method; - if ($collections_preferences = elgg_get_logged_in_user_entity()->$metaname) { + if ($collections_preferences = $user->$metaname) { if (!empty($collections_preferences) && !is_array($collections_preferences)) { $collections_preferences = array($collections_preferences); } @@ -91,15 +99,18 @@ END; <td> </td> </tr> <?php -/* - @todo - collections removed from notifications - they are no longer used and will be replaced with shared access collections - - if ($collections = get_user_access_collections(elgg_get_logged_in_user_guid())) { - foreach($collections as $collection) { + + if ($collections = get_user_access_collections($user->guid)) { + foreach ($collections as $collection) { $members = get_members_of_access_collection($collection->id, true); - $memberno = sizeof($members); - $members = implode(',', $members); + $memberno = 0; + if ($members) { + $memberno = sizeof($members); + $members = implode(',', $members); + } else { + $members = ''; + } + ?> <tr> @@ -115,7 +126,7 @@ END; $i = 0; foreach($NOTIFICATION_HANDLERS as $method => $foo) { $metaname = 'collections_notifications_preferences_' . $method; - if ($collections_preferences = elgg_get_logged_in_user_entity()->$metaname) { + if ($collections_preferences = $user->$metaname) { if (!empty($collections_preferences) && !is_array($collections_preferences)) { $collections_preferences = array($collections_preferences); } @@ -148,7 +159,6 @@ END; } } -*/ ?> </table> </div> diff --git a/mod/notifications/views/default/notifications/subscriptions/form.php b/mod/notifications/views/default/notifications/subscriptions/form.php index f2f6238f9..559354eff 100644 --- a/mod/notifications/views/default/notifications/subscriptions/form.php +++ b/mod/notifications/views/default/notifications/subscriptions/form.php @@ -1,11 +1,12 @@ <?php /** * Elgg personal notifications + * + * @uses $vars['user'] ElggUser that owns the notification settings */ - -echo elgg_view('subscriptions/form/additions',$vars); - -// Display a description +// @todo is this a view for extensions? +echo elgg_view('subscriptions/form/additions', $vars); -echo elgg_view_form('notificationsettings/save', array('class' => 'elgg-form-alt')); +$form_vars = array('class' => 'elgg-form-alt'); +echo elgg_view_form('notificationsettings/save', $form_vars, $vars); diff --git a/mod/notifications/views/default/notifications/subscriptions/forminternals.php b/mod/notifications/views/default/notifications/subscriptions/forminternals.php index e89ce02be..11f266303 100644 --- a/mod/notifications/views/default/notifications/subscriptions/forminternals.php +++ b/mod/notifications/views/default/notifications/subscriptions/forminternals.php @@ -1,8 +1,13 @@ <?php /** * Hacked up friends picker that needs to be replaced + * + * @uses $vars['user'] ElggUser */ +/* @var ElggUser $user */ +$user = $vars['user']; + elgg_load_js('elgg.friendspicker'); elgg_load_js('jquery.easing'); @@ -19,11 +24,16 @@ elgg_load_js('jquery.easing'); <?php // Get friends and subscriptions -$friends = get_user_friends(elgg_get_logged_in_user_guid(),'',9999,0); +$friends = get_user_friends($user->guid, '', 9999, 0); global $NOTIFICATION_HANDLERS; foreach($NOTIFICATION_HANDLERS as $method => $foo) { - $subsbig[$method] = elgg_get_entities_from_relationship(array('relationship' => 'notify' . $method, 'relationship_guid' => elgg_get_logged_in_user_guid(), 'types' => 'user', 'limit' => 99999)); + $subsbig[$method] = elgg_get_entities_from_relationship(array( + 'relationship' => 'notify' . $method, + 'relationship_guid' => $user->guid, + 'types' => 'user', + 'limit' => 99999, + )); } $subs = array(); @@ -88,9 +98,9 @@ if (isset($vars['formtarget'])) { // Sort users by letter if (is_array($friends) && sizeof($friends)) { - foreach($friends as $user) { + foreach($friends as $friend) { - $letter = elgg_substr($user->name,0,1); + $letter = elgg_substr($friend->name,0,1); $letter = elgg_strtoupper($letter); if (!elgg_substr_count($chararray,$letter)) { $letter = "*"; @@ -98,7 +108,7 @@ if (is_array($friends) && sizeof($friends)) { if (!isset($users[$letter])) { $users[$letter] = array(); } - $users[$letter][$user->guid] = $user; + $users[$letter][$friend->guid] = $friend; } } diff --git a/mod/notifications/views/default/notifications/subscriptions/personal.php b/mod/notifications/views/default/notifications/subscriptions/personal.php index 7dac908fc..cf05426e2 100644 --- a/mod/notifications/views/default/notifications/subscriptions/personal.php +++ b/mod/notifications/views/default/notifications/subscriptions/personal.php @@ -1,4 +1,10 @@ <?php +/** + * @uses $vars['user'] ElggUser + */ + +/* @var ElggUser $user */ +$user = $vars['user']; global $NOTIFICATION_HANDLERS; @@ -40,7 +46,7 @@ foreach($NOTIFICATION_HANDLERS as $method => $foo) { $fields = ''; $i = 0; foreach($NOTIFICATION_HANDLERS as $method => $foo) { - if ($notification_settings = get_user_notification_settings(elgg_get_logged_in_user_guid())) { + if ($notification_settings = get_user_notification_settings($user->guid)) { if ($notification_settings->$method) { $personalchecked[$method] = 'checked="checked"'; } else { diff --git a/mod/pages/lib/pages.php b/mod/pages/lib/pages.php index 3f27118a6..9a9ba12e9 100644 --- a/mod/pages/lib/pages.php +++ b/mod/pages/lib/pages.php @@ -103,16 +103,18 @@ function pages_register_navigation_tree($container) { 'metadata_value' => $parent->getGUID(), 'limit' => 0, )); - - foreach ($children as $child) { - elgg_register_menu_item('pages_nav', array( - 'name' => $child->getGUID(), - 'text' => $child->title, - 'href' => $child->getURL(), - 'parent_name' => $parent->getGUID(), - )); - array_push($stack, $child); + + if ($children) { + foreach ($children as $child) { + elgg_register_menu_item('pages_nav', array( + 'name' => $child->getGUID(), + 'text' => $child->title, + 'href' => $child->getURL(), + 'parent_name' => $parent->getGUID(), + )); + array_push($stack, $child); + } } } } -}
\ No newline at end of file +} diff --git a/mod/pages/pages/pages/view.php b/mod/pages/pages/pages/view.php index 6b9d03f49..e1c3fdbfd 100644 --- a/mod/pages/pages/pages/view.php +++ b/mod/pages/pages/pages/view.php @@ -9,7 +9,8 @@ $page_guid = get_input('guid'); $page = get_entity($page_guid); if (!$page) { register_error(elgg_echo('noaccess')); - forward(); + $_SESSION['last_forward_from'] = current_page_url(); + forward(''); } elgg_set_page_owner_guid($page->getContainerGUID()); diff --git a/mod/pages/start.php b/mod/pages/start.php index 834e98870..6b0ad38b0 100644 --- a/mod/pages/start.php +++ b/mod/pages/start.php @@ -30,7 +30,6 @@ function pages_init() { // Register some actions $action_base = elgg_get_plugins_path() . 'pages/actions/pages'; elgg_register_action("pages/edit", "$action_base/edit.php"); - elgg_register_action("pages/editwelcome", "$action_base/editwelcome.php"); elgg_register_action("pages/delete", "$action_base/delete.php"); // Extend the main css view @@ -106,10 +105,6 @@ function pages_page_handler($page) { elgg_load_library('elgg:pages'); - // add the jquery treeview files for navigation - elgg_load_js('jquery-treeview'); - elgg_load_css('jquery-treeview'); - if (!isset($page[0])) { $page[0] = 'all'; } diff --git a/mod/pages/views/default/pages/sidebar/navigation.php b/mod/pages/views/default/pages/sidebar/navigation.php index fe017b1a7..65eb500c8 100644 --- a/mod/pages/views/default/pages/sidebar/navigation.php +++ b/mod/pages/views/default/pages/sidebar/navigation.php @@ -5,6 +5,11 @@ * @uses $vars['page'] Page object if manually setting selected item */ +// add the jquery treeview files for navigation +elgg_load_js('jquery-treeview'); +elgg_load_css('jquery-treeview'); + + $selected_page = elgg_extract('page', $vars, false); if ($selected_page) { $url = $selected_page->getURL(); @@ -51,4 +56,3 @@ if ($selected_page) { }); </script> - diff --git a/mod/profile/icondirect.php b/mod/profile/icondirect.php index 6c3148f2b..c4439f78c 100644 --- a/mod/profile/icondirect.php +++ b/mod/profile/icondirect.php @@ -11,6 +11,12 @@ require_once(dirname(dirname(dirname(__FILE__))). '/engine/settings.php'); global $CONFIG; +// won't be able to serve anything if no joindate or guid +if (!isset($_GET['joindate']) || !isset($_GET['guid'])) { + header("HTTP/1.1 404 Not Found"); + exit; +} + $join_date = (int)$_GET['joindate']; $last_cache = (int)$_GET['lastcache']; // icontime $guid = (int)$_GET['guid']; diff --git a/mod/thewire/pages/thewire/view.php b/mod/thewire/pages/thewire/view.php index 1818e725a..1709e5e9a 100644 --- a/mod/thewire/pages/thewire/view.php +++ b/mod/thewire/pages/thewire/view.php @@ -6,6 +6,7 @@ $post = get_entity(get_input('guid')); if (!$post) { register_error(elgg_echo('noaccess')); + $_SESSION['last_forward_from'] = current_page_url(); forward(''); } $owner = $post->getOwnerEntity(); diff --git a/mod/thewire/start.php b/mod/thewire/start.php index 8e3b5224a..1ba48263a 100644 --- a/mod/thewire/start.php +++ b/mod/thewire/start.php @@ -37,7 +37,7 @@ function thewire_init() { elgg_register_plugin_hook_handler('register', 'menu:entity', 'thewire_setup_entity_menu_items'); // Extend system CSS with our own styles, which are defined in the thewire/css view - elgg_extend_view('css', 'thewire/css'); + elgg_extend_view('css/elgg', 'thewire/css'); //extend views elgg_extend_view('activity/thewire', 'thewire/activity_view'); @@ -110,6 +110,7 @@ function thewire_page_handler($page) { set_input('guid', $page[1]); } include "$base_dir/view.php"; + break; case "thread": if (isset($page[1])) { diff --git a/upgrade.php b/upgrade.php index 963523200..60764ba93 100644 --- a/upgrade.php +++ b/upgrade.php @@ -27,6 +27,9 @@ if (get_input('upgrade') == 'upgrade') { if (elgg_get_unprocessed_upgrades()) { version_upgrade(); } + + // turn off time limit so plugins that have upgrade scripts aren't interrupted + set_time_limit(0); elgg_trigger_event('upgrade', 'system', null); elgg_invalidate_simplecache(); elgg_reset_system_cache(); diff --git a/views/default/core/friends/collection.php b/views/default/core/friends/collection.php index b7913da5f..1a330af01 100644 --- a/views/default/core/friends/collection.php +++ b/views/default/core/friends/collection.php @@ -43,7 +43,7 @@ if ($friends) { echo elgg_view('input/friendspicker', array( 'entities' => $friends, - 'value' => $members, + 'value' => $vars['collection']->members, 'content' => $content, 'replacement' => '', 'friendspicker' => $vars['friendspicker'], diff --git a/views/default/css/admin.php b/views/default/css/admin.php index 65797172f..0f5c1f677 100644 --- a/views/default/css/admin.php +++ b/views/default/css/admin.php @@ -127,14 +127,23 @@ p { } /* Clearfix! */ +.clearfix:after, .elgg-grid:after, -.clearfix:after { +.elgg-layout:after, +.elgg-inner:after, +.elgg-page-header:after, +.elgg-page-footer:after, +.elgg-head:after, +.elgg-foot:after, +.elgg-col:after, +.elgg-image-block:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } + .elgg-body { width: auto; word-wrap: break-word; @@ -287,14 +296,6 @@ p { .elgg-main h2 { color: #333333; } -<?php // elgg-layout gets clearfix ?> -.elgg-layout:after { - content: "."; - display: block; - height: 0; - clear: both; - visibility: hidden; -} /* *************************************** FOOTER @@ -537,20 +538,20 @@ a.elgg-button { -webkit-border-radius: 5px; } .ui-datepicker-prev, .ui-datepicker-next { - position: absolute; - top: 9px; + position: absolute; + top: 9px; cursor: pointer; } .ui-datepicker-prev { - left: 6px; + left: 6px; } .ui-datepicker-next { - right: 6px; + right: 6px; } .ui-datepicker-title { - line-height: 1.8em; - margin: 0 30px; - text-align: center; + line-height: 1.8em; + margin: 0 30px; + text-align: center; font-weight: bold; } .ui-datepicker-calendar { @@ -558,39 +559,237 @@ a.elgg-button { } .ui-datepicker th { border: none; - font-weight: bold; - padding: 5px 6px; - text-align: center; + font-weight: bold; + padding: 5px 6px; + text-align: center; } .ui-datepicker td { padding: 1px; } .ui-datepicker td span, .ui-datepicker td a { - display: block; - padding: 2px; + display: block; + padding: 2px; line-height: 1.2em; - text-align: right; - text-decoration: none; + text-align: right; + text-decoration: none; } .ui-datepicker-calendar .ui-state-default { border: 1px solid #ccc; - color: #555; + color: #555; background: #fafafa; } .ui-datepicker-calendar .ui-state-hover { border: 1px solid #aaa; - color: #333; + color: #333; background: #ccc; } .ui-datepicker-calendar .ui-state-active, .ui-datepicker-calendar .ui-state-active.ui-state-hover { font-weight: bold; - border: 1px solid #999; - color: #333; + border: 1px solid #999; + color: #333; background: #ddd; } /* *************************************** + AUTOCOMPLETE +*************************************** */ +<?php //autocomplete will expand to fullscreen without max-width ?> +.ui-autocomplete { + position: absolute; + cursor: default; +} +.elgg-autocomplete-item .elgg-body { + max-width: 600px; +} +.ui-autocomplete { + background-color: white; + border: 1px solid #ccc; + overflow: hidden; + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} +.ui-autocomplete .ui-menu-item { + padding: 0px 4px; + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} +.ui-autocomplete .ui-menu-item:hover { + background-color: #eee; +} +.ui-autocomplete a:hover { + text-decoration: none; + color: #4690D6; +} + +/* *************************************** + USER PICKER +*************************************** */ +.elgg-user-picker-list li:first-child { + border-top: 1px dotted #ccc; + margin-top: 5px; +} +.elgg-user-picker-list > li { + border-bottom: 1px dotted #ccc; +} + +/* *************************************** + FRIENDS PICKER +*************************************** */ +.friends-picker-main-wrapper { + margin-bottom: 15px; +} +.friends-picker-container h3 { + font-size:4em !important; + text-align: left; + margin:10px 0 20px !important; + color:#999 !important; + background: none !important; + padding:0 !important; +} +.friends-picker .friends-picker-container .panel ul { + text-align: left; + margin: 0; + padding:0; +} +.friends-picker-wrapper { + margin: 0; + padding:0; + position: relative; + width: 730px; +} +.friends-picker { + position: relative; + overflow: hidden; + margin: 0; + padding:0; + width: 730px; + height: auto; + background-color: #dedede; + + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; +} +.friendspicker-savebuttons { + background: white; + + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + + margin:0 10px 10px; +} +.friends-picker .friends-picker-container { /* long container used to house end-to-end panels. Width is calculated in JS */ + position: relative; + left: 0; + top: 0; + width: 100%; + list-style-type: none; +} +.friends-picker .friends-picker-container .panel { + float:left; + height: 100%; + position: relative; + width: 730px; + margin: 0; + padding:0; +} +.friends-picker .friends-picker-container .panel .wrapper { + margin: 0; + padding:4px 10px 10px 10px; + min-height: 230px; +} +.friends-picker-navigation { + margin: 0 0 10px; + padding:0 0 10px; + border-bottom:1px solid #ccc; +} +.friends-picker-navigation ul { + list-style: none; + padding-left: 0; +} +.friends-picker-navigation ul li { + float: left; + margin:0; + background:white; +} +.friends-picker-navigation a { + font-weight: bold; + text-align: center; + background: white; + color: #999; + text-decoration: none; + display: block; + padding: 0; + width:20px; + + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.tabHasContent { + background: white; + color:#333 !important; +} +.friends-picker-navigation li a:hover { + background: #333; + color:white !important; +} +.friends-picker-navigation li a.current { + background: #4690D6; + color:white !important; +} +.friends-picker-navigation-l, .friends-picker-navigation-r { + position: absolute; + top: 46px; + text-indent: -9000em; +} +.friends-picker-navigation-l a, .friends-picker-navigation-r a { + display: block; + height: 40px; + width: 40px; +} +.friends-picker-navigation-l { + right: 48px; + z-index:1; +} +.friends-picker-navigation-r { + right: 0; + z-index:1; +} +.friends-picker-navigation-l { + background: url("<?php echo elgg_get_site_url(); ?>_graphics/friendspicker.png") no-repeat left top; +} +.friends-picker-navigation-r { + background: url("<?php echo elgg_get_site_url(); ?>_graphics/friendspicker.png") no-repeat -60px top; +} +.friends-picker-navigation-l:hover { + background: url("<?php echo elgg_get_site_url(); ?>_graphics/friendspicker.png") no-repeat left -44px; +} +.friends-picker-navigation-r:hover { + background: url("<?php echo elgg_get_site_url(); ?>_graphics/friendspicker.png") no-repeat -60px -44px; +} +.friendspicker-savebuttons .elgg-button-submit, +.friendspicker-savebuttons .elgg-button-cancel { + margin:5px 20px 5px 5px; +} +.friendspicker-members-table { + background: #dedede; + + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + + margin:10px 0 0; + padding:10px 10px 0; +} + +/* *************************************** PAGINATION *************************************** */ .elgg-pagination { diff --git a/views/default/css/elements/forms.php b/views/default/css/elements/forms.php index 81db81747..2fc156447 100644 --- a/views/default/css/elements/forms.php +++ b/views/default/css/elements/forms.php @@ -104,7 +104,7 @@ input[type="radio"] { margin: 0; padding:0; position: relative; - width: 100%; + width: 730px; } .friends-picker { position: relative; @@ -315,20 +315,20 @@ input[type="radio"] { color: white; } .ui-datepicker-prev, .ui-datepicker-next { - position: absolute; - top: 5px; + position: absolute; + top: 5px; cursor: pointer; } .ui-datepicker-prev { - left: 6px; + left: 6px; } .ui-datepicker-next { - right: 6px; + right: 6px; } .ui-datepicker-title { - line-height: 1.8em; - margin: 0 30px; - text-align: center; + line-height: 1.8em; + margin: 0 30px; + text-align: center; font-weight: bold; } .ui-datepicker-calendar { @@ -337,34 +337,34 @@ input[type="radio"] { .ui-datepicker th { color: #0054A7; border: none; - font-weight: bold; - padding: 5px 6px; - text-align: center; + font-weight: bold; + padding: 5px 6px; + text-align: center; } .ui-datepicker td { padding: 1px; } .ui-datepicker td span, .ui-datepicker td a { - display: block; - padding: 2px; + display: block; + padding: 2px; line-height: 1.2em; - text-align: right; - text-decoration: none; + text-align: right; + text-decoration: none; } .ui-datepicker-calendar .ui-state-default { border: 1px solid #ccc; - color: #4690D6;; + color: #4690D6;; background: #fafafa; } .ui-datepicker-calendar .ui-state-hover { border: 1px solid #aaa; - color: #0054A7; + color: #0054A7; background: #eee; } .ui-datepicker-calendar .ui-state-active, .ui-datepicker-calendar .ui-state-active.ui-state-hover { font-weight: bold; - border: 1px solid #0054A7; - color: #0054A7; + border: 1px solid #0054A7; + color: #0054A7; background: #E4ECF5; } diff --git a/views/default/input/friendspicker.php b/views/default/input/friendspicker.php index b41449fbf..40708c890 100644 --- a/views/default/input/friendspicker.php +++ b/views/default/input/friendspicker.php @@ -9,6 +9,10 @@ * @subpackage Core * * @uses $vars['entities'] The array of ElggUser objects + * @uses $vars['name'] + * @uses $vars['value'] + * @uses $vars['highlight'] + * @uses $vars['callback'] */ elgg_load_js('elgg.friendspicker'); @@ -74,13 +78,9 @@ if (isset($vars['formtarget'])) { // Sort users by letter if (is_array($vars['entities']) && sizeof($vars['entities'])) { foreach($vars['entities'] as $user) { - if (is_callable('mb_substr')) { - $letter = strtoupper(mb_substr($user->name,0,1)); - } else { - $letter = strtoupper(substr($user->name,0,1)); - } + $letter = elgg_strtoupper(elgg_substr($user->name, 0, 1)); - if (!substr_count($chararray,$letter)) { + if (!elgg_substr_count($chararray, $letter)) { $letter = "*"; } if (!isset($users[$letter])) { @@ -162,11 +162,7 @@ if (!isset($vars['replacement'])) { // Initialise letters $chararray .= "*"; - if (is_callable('mb_substr')) { - $letter = mb_substr($chararray,0,1); - } else { - $letter = substr($chararray,0,1); - } + $letter = elgg_substr($chararray, 0, 1); $letpos = 0; while (1 == 1) { ?> @@ -190,9 +186,7 @@ if (!isset($vars['replacement'])) { $label = elgg_view_entity_icon($friend, 'tiny', array('use_hover' => false)); $options[$label] = $friend->getGUID(); - if ($vars['highlight'] == 'all' - && !in_array($letter,$activeletters)) { - + if ($vars['highlight'] == 'all' && !in_array($letter,$activeletters)) { $activeletters[] = $letter; } @@ -243,23 +237,14 @@ if (!isset($vars['replacement'])) { </div> </div> <?php - //if ($letter == 'Z') break; - if (is_callable('mb_substr')) { - $substr = mb_substr($chararray,strlen($chararray) - 1,1); - } else { - $substr = substr($chararray,strlen($chararray) - 1,1); - } + $substr = elgg_substr($chararray, elgg_strlen($chararray) - 1, 1); if ($letter == $substr) { break; } //$letter++; $letpos++; - if (is_callable('mb_substr')) { - $letter = mb_substr($chararray,$letpos,1); - } else { - $letter = substr($chararray,$letpos,1); - } + $letter = elgg_substr($chararray, $letpos, 1); } ?> @@ -319,7 +304,7 @@ $(document).ready(function () { if (sizeof($activeletters) > 0) //$chararray = elgg_echo('friendspicker:chararray'); foreach($activeletters as $letter) { - $tab = strpos($chararray, $letter) + 1; + $tab = elgg_strpos($chararray, $letter) + 1; ?> $("div#friends-picker-navigation<?php echo $friendspicker; ?> li.tab<?php echo $tab; ?> a").addClass("tabHasContent"); <?php diff --git a/views/default/js/elgg.php b/views/default/js/elgg.php index 133e128a4..6460e93d6 100644 --- a/views/default/js/elgg.php +++ b/views/default/js/elgg.php @@ -57,6 +57,7 @@ elgg.release = '<?php echo get_version(true); ?>'; elgg.config.wwwroot = '<?php echo elgg_get_site_url(); ?>'; elgg.security.interval = 5 * 60 * 1000; <?php //@todo make this configurable ?> elgg.config.domReady = false; +elgg.config.language = '<?php echo isset($CONFIG->language) ? $CONFIG->language : 'en'; ?>'; elgg.config.languageReady = false; //After the DOM is ready diff --git a/views/default/object/plugin/invalid.php b/views/default/object/plugin/invalid.php index f24e1836c..828bceaba 100644 --- a/views/default/object/plugin/invalid.php +++ b/views/default/object/plugin/invalid.php @@ -14,8 +14,7 @@ $plugin = $vars['entity']; $id = $plugin->getID(); $path = htmlspecialchars($plugin->getPath()); -$message = elgg_echo('admin:plugins:warning:invalid', array($id)); -$error = $plugin->getError(); +$message = elgg_echo('admin:plugins:warning:invalid', array($plugin->getError())); $css_id = preg_replace('/[^a-z0-9-]/i', '-', $plugin->getID()); ?> @@ -23,7 +22,8 @@ $css_id = preg_replace('/[^a-z0-9-]/i', '-', $plugin->getID()); <div class="elgg-state-draggable elgg-plugin elgg-state-inactive elgg-state-error" id="elgg-plugin-<?php echo $plugin->guid; ?>"> <div class="elgg-head"><h3><?php echo $id; ?></h3></div> <div class="elgg-body"> - <p><?php echo $message; ?></p> + <p class="elgg-state-error"><?php echo $message; ?></p> + <p><?php echo elgg_echo('admin:plugins:warning:invalid:check_docs'); ?></p> <div class="pts"> <?php @@ -37,7 +37,6 @@ $css_id = preg_replace('/[^a-z0-9-]/i', '-', $plugin->getID()); <div class="hidden elgg-plugin-more" id="elgg-plugin-manifest-<?php echo $css_id; ?>"> <p><?php echo elgg_echo('admin:plugins:label:location') . ": " . $path; ?></p> - <p><?php echo $error; ?></p> </div> </div> </div>
\ No newline at end of file diff --git a/views/default/river/elements/summary.php b/views/default/river/elements/summary.php index 4402c6f65..416bc708b 100644 --- a/views/default/river/elements/summary.php +++ b/views/default/river/elements/summary.php @@ -41,12 +41,12 @@ if ($container instanceof ElggGroup) { } // check summary translation keys. -// will use the $type:$subtype if that's defined, otherwise just uses $type +// will use the $type:$subtype if that's defined, otherwise just uses $type:default $key = "river:$action:$type:$subtype"; $summary = elgg_echo($key, array($subject_link, $object_link)); if ($summary == $key) { - $key = "river:$action:$type"; + $key = "river:$action:$type:default"; $summary = elgg_echo($key, array($subject_link, $object_link)); } diff --git a/views/json/export/entity.php b/views/json/export/entity.php index 52cd9d244..36af5eaef 100644 --- a/views/json/export/entity.php +++ b/views/json/export/entity.php @@ -19,4 +19,7 @@ foreach ($exportable_values as $v) { $export->url = $entity->getURL(); global $jsonexport; -$jsonexport[$entity->getType()][$entity->getSubtype()][] = $export;
\ No newline at end of file +$jsonexport[$entity->getType()][$entity->getSubtype()][] = $export; + +// @todo hack to fix #4504 +echo "Fix for bug #4504"; diff --git a/views/json/group/default.php b/views/json/group/default.php index 0b168fdb2..dd190d402 100644 --- a/views/json/group/default.php +++ b/views/json/group/default.php @@ -6,4 +6,4 @@ * @subpackage Core */ -elgg_view('export/entity', $vars);
\ No newline at end of file +echo elgg_view('export/entity', $vars); diff --git a/views/json/object/default.php b/views/json/object/default.php index d2e807621..8b88b3010 100644 --- a/views/json/object/default.php +++ b/views/json/object/default.php @@ -6,4 +6,4 @@ * @subpackage Core */ -elgg_view('export/entity', $vars);
\ No newline at end of file +echo elgg_view('export/entity', $vars); diff --git a/views/json/site/default.php b/views/json/site/default.php index 7efd46939..ee4eda489 100644 --- a/views/json/site/default.php +++ b/views/json/site/default.php @@ -6,4 +6,4 @@ * @subpackage Core */ -elgg_view('export/entity', $vars);
\ No newline at end of file +echo elgg_view('export/entity', $vars); diff --git a/views/json/user/default.php b/views/json/user/default.php index e23472252..4d44692c9 100644 --- a/views/json/user/default.php +++ b/views/json/user/default.php @@ -6,4 +6,4 @@ * @subpackage Core */ -elgg_view('export/entity', $vars);
\ No newline at end of file +echo elgg_view('export/entity', $vars); |