diff options
-rw-r--r-- | CHANGES.txt | 5 | ||||
-rw-r--r-- | engine/classes/ElggDiskFilestore.php | 20 | ||||
-rw-r--r-- | engine/lib/database.php | 4 | ||||
-rw-r--r-- | engine/lib/output.php | 25 | ||||
-rw-r--r-- | engine/tests/regression/trac_bugs.php | 52 | ||||
-rw-r--r-- | mod/embed/start.php | 20 | ||||
-rw-r--r-- | mod/groups/actions/groups/membership/invite.php | 73 | ||||
-rw-r--r-- | mod/htmlawed/start.php | 4 | ||||
-rw-r--r-- | mod/htmlawed/tests/tags.php | 78 | ||||
-rw-r--r-- | version.php | 2 | ||||
-rw-r--r-- | views/default/css/admin.php | 3 |
11 files changed, 185 insertions, 101 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index c23d30fd2..fcdc97969 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,5 @@ Version 1.8.15 -(April xx, 2013 from https://github.com/Elgg/Elgg/tree/1.8) +(April 23, 2013 from https://github.com/Elgg/Elgg/tree/1.8) Contributing Developers: * Cash Costello * Ismayil Khayredinov @@ -21,13 +21,14 @@ Version 1.8.15 Enhancements: * Added browser caching of language JS files + * Adding nofollow on user posted URLs for spam deterrence (thanks to Hellekin) * Auto-registering views for simplecache when their URL is requested * Display helpful message for those who have site URL configuration issues * Can revert to a previous revision with pages plugin * Site owners can turn off posting wire messages to Twitter * Search results are sorted by relevance - Dropped Support: + Dropped Plugins: * Twitter widget due to changes in Twitter API and terms of service * OAuth API plugin due to conflicts with the Twitter API plugin diff --git a/engine/classes/ElggDiskFilestore.php b/engine/classes/ElggDiskFilestore.php index ded653436..6e2354012 100644 --- a/engine/classes/ElggDiskFilestore.php +++ b/engine/classes/ElggDiskFilestore.php @@ -194,7 +194,9 @@ class ElggDiskFilestore extends ElggFilestore { } /** - * Returns the filename as saved on disk for an ElggFile object + * Get the filename as saved on disk for an ElggFile object + * + * Returns an empty string if no filename set * * @param ElggFile $file File object * @@ -213,7 +215,12 @@ class ElggDiskFilestore extends ElggFilestore { throw new InvalidParameterException($msg); } - return $this->dir_root . $this->makefileMatrix($owner_guid) . $file->getFilename(); + $filename = $file->getFilename(); + if (!$filename) { + return ''; + } + + return $this->dir_root . $this->makeFileMatrix($owner_guid) . $filename; } /** @@ -221,7 +228,7 @@ class ElggDiskFilestore extends ElggFilestore { * * @param ElggFile $file File object * - * @return mixed + * @return string */ public function grabFile(ElggFile $file) { return file_get_contents($file->getFilenameOnFilestore()); @@ -235,6 +242,9 @@ class ElggDiskFilestore extends ElggFilestore { * @return bool */ public function exists(ElggFile $file) { + if (!$file->getFilename()) { + return false; + } return file_exists($this->getFilenameOnFilestore($file)); } @@ -248,7 +258,7 @@ class ElggDiskFilestore extends ElggFilestore { */ public function getSize($prefix = '', $container_guid) { if ($container_guid) { - return get_dir_size($this->dir_root . $this->makefileMatrix($container_guid) . $prefix); + return get_dir_size($this->dir_root . $this->makeFileMatrix($container_guid) . $prefix); } else { return false; } @@ -335,7 +345,7 @@ class ElggDiskFilestore extends ElggFilestore { protected function make_file_matrix($identifier) { elgg_deprecated_notice('ElggDiskFilestore::make_file_matrix() is deprecated by ::makeFileMatrix()', 1.8); - return $this->makefileMatrix($identifier); + return $this->makeFileMatrix($identifier); } // @codingStandardsIgnoreEnd diff --git a/engine/lib/database.php b/engine/lib/database.php index 3553d787d..37dfb8f8d 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -473,7 +473,7 @@ function insert_data($query) { } /** - * Update a row in the database. + * Update the database. * * @note Altering the DB invalidates all queries in {@link $DB_QUERY_CACHE}. * @@ -498,7 +498,7 @@ function update_data($query) { } /** - * Remove a row from the database. + * Remove data from the database. * * @note Altering the DB invalidates all queries in {@link $DB_QUERY_CACHE}. * diff --git a/engine/lib/output.php b/engine/lib/output.php index c5a04989b..6905b9b71 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -13,28 +13,33 @@ * @param string $text The input string * * @return string The output string with formatted links - **/ + */ function parse_urls($text) { + + // URI specification: http://www.ietf.org/rfc/rfc3986.txt + // This varies from the specification in the following ways: + // * Supports non-ascii characters + // * Does not allow parentheses and single quotes + // * Cuts off commas, exclamation points, and periods off as last character + // @todo this causes problems with <attr = "val"> // must be in <attr="val"> format (no space). // By default htmlawed rewrites tags to this format. // if PHP supported conditional negative lookbehinds we could use this: // $r = preg_replace_callback('/(?<!=)(?<![ ])?(?<!["\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\'\!\(\),]+)/i', - // - // we can put , in the list of excluded char but need to keep . because of domain names. - // it is removed in the callback. - $r = preg_replace_callback('/(?<!=)(?<!["\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\'\!\(\),]+)/i', + $r = preg_replace_callback('/(?<!=)(?<!["\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\'\(\)]+)/i', create_function( '$matches', ' $url = $matches[1]; - $period = \'\'; - if (substr($url, -1, 1) == \'.\') { - $period = \'.\'; - $url = trim($url, \'.\'); + $punc = \'\'; + $last = substr($url, -1, 1); + if (in_array($last, array(".", "!", ","))) { + $punc = $last; + $url = rtrim($url, ".!,"); } $urltext = str_replace("/", "/<wbr />", $url); - return "<a href=\"$url\">$urltext</a>$period"; + return "<a href=\"$url\" rel=\"nofollow\">$urltext</a>$punc"; ' ), $text); diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 58444dd39..4de9c306b 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -236,4 +236,56 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { $this->assertIdentical($expected, $friendly_title); } } + + /** + * Test #5369 -- parse_urls() + * https://github.com/Elgg/Elgg/issues/5369 + */ + public function test_parse_urls() { + + $cases = array( + 'no.link.here' => + 'no.link.here', + 'simple link http://example.org test' => + 'simple link <a href="http://example.org" rel="nofollow">http:/<wbr />/<wbr />example.org</a> test', + 'non-ascii http://ñew.org/ test' => + 'non-ascii <a href="http://ñew.org/" rel="nofollow">http:/<wbr />/<wbr />ñew.org/<wbr /></a> test', + + // section 2.1 + 'percent encoded http://example.org/a%20b test' => + 'percent encoded <a href="http://example.org/a%20b" rel="nofollow">http:/<wbr />/<wbr />example.org/<wbr />a%20b</a> test', + // section 2.2: skipping single quote and parenthese + 'reserved characters http://example.org/:/?#[]@!$&*+,;= test' => + 'reserved characters <a href="http://example.org/:/?#[]@!$&*+,;=" rel="nofollow">http:/<wbr />/<wbr />example.org/<wbr />:/<wbr />?#[]@!$&*+,;=</a> test', + // section 2.3 + 'unreserved characters http://example.org/a1-._~ test' => + 'unreserved characters <a href="http://example.org/a1-._~" rel="nofollow">http:/<wbr />/<wbr />example.org/<wbr />a1-._~</a> test', + + 'parameters http://example.org/?val[]=1&val[]=2 test' => + 'parameters <a href="http://example.org/?val[]=1&val[]=2" rel="nofollow">http:/<wbr />/<wbr />example.org/<wbr />?val[]=1&val[]=2</a> test', + 'port http://example.org:80/ test' => + 'port <a href="http://example.org:80/" rel="nofollow">http:/<wbr />/<wbr />example.org:80/<wbr /></a> test', + + 'parentheses (http://www.google.com) test' => + 'parentheses (<a href="http://www.google.com" rel="nofollow">http:/<wbr />/<wbr />www.google.com</a>) test', + 'comma http://elgg.org, test' => + 'comma <a href="http://elgg.org" rel="nofollow">http:/<wbr />/<wbr />elgg.org</a>, test', + 'period http://elgg.org. test' => + 'period <a href="http://elgg.org" rel="nofollow">http:/<wbr />/<wbr />elgg.org</a>. test', + 'exclamation http://elgg.org! test' => + 'exclamation <a href="http://elgg.org" rel="nofollow">http:/<wbr />/<wbr />elgg.org</a>! test', + + 'already anchor <a href="http://twitter.com/">twitter</a> test' => + 'already anchor <a href="http://twitter.com/">twitter</a> test', + + 'ssl https://example.org/ test' => + 'ssl <a href="https://example.org/" rel="nofollow">https:/<wbr />/<wbr />example.org/<wbr /></a> test', + 'ftp ftp://example.org/ test' => + 'ftp <a href="ftp://example.org/" rel="nofollow">ftp:/<wbr />/<wbr />example.org/<wbr /></a> test', + + ); + foreach ($cases as $input => $output) { + $this->assertEqual($output, parse_urls($input)); + } + } } diff --git a/mod/embed/start.php b/mod/embed/start.php index e8a3f8c14..e14e0efd4 100644 --- a/mod/embed/start.php +++ b/mod/embed/start.php @@ -13,6 +13,7 @@ elgg_register_event_handler('init', 'system', 'embed_init'); */ function embed_init() { elgg_extend_view('css/elgg', 'embed/css'); + elgg_extend_view('css/admin', 'embed/css'); elgg_register_plugin_hook_handler('register', 'menu:longtext', 'embed_longtext_menu'); elgg_register_plugin_hook_handler('register', 'menu:embed', 'embed_select_tab', 1000); @@ -20,7 +21,9 @@ function embed_init() { // Page handler for the modal media embed elgg_register_page_handler('embed', 'embed_page_handler'); - elgg_register_js('elgg.embed', 'js/embed/embed.js', 'footer'); + $embed_js = elgg_get_simplecache_url('js', 'embed/embed'); + elgg_register_simplecache_view('js/embed/embed'); + elgg_register_js('elgg.embed', $embed_js, 'footer'); } /** @@ -39,10 +42,12 @@ function embed_longtext_menu($hook, $type, $items, $vars) { } $url = 'embed'; - if (elgg_get_page_owner_guid()) { - $url = 'embed?container_guid=' . elgg_get_page_owner_guid(); + + $page_owner = elgg_get_page_owner_entity(); + if (elgg_instanceof($page_owner, 'group') && $page_owner->isMember()) { + $url = 'embed?container_guid=' . $page_owner->getGUID(); } - + $items[] = ElggMenuItem::factory(array( 'name' => 'embed', 'href' => $url, @@ -95,7 +100,12 @@ function embed_page_handler($page) { $container_guid = (int)get_input('container_guid'); if ($container_guid) { - elgg_set_page_owner_guid($container_guid); + $container = get_entity($container_guid); + + if (elgg_instanceof($container, 'group') && $container->isMember()) { + // embedding inside a group so save file to group files + elgg_set_page_owner_guid($container_guid); + } } echo elgg_view('embed/layout'); diff --git a/mod/groups/actions/groups/membership/invite.php b/mod/groups/actions/groups/membership/invite.php index db90ecf3a..a96165b0e 100644 --- a/mod/groups/actions/groups/membership/invite.php +++ b/mod/groups/actions/groups/membership/invite.php @@ -7,43 +7,48 @@ $logged_in_user = elgg_get_logged_in_user_entity(); -$user_guid = get_input('user_guid'); -if (!is_array($user_guid)) { - $user_guid = array($user_guid); +$user_guids = get_input('user_guid'); +if (!is_array($user_guids)) { + $user_guids = array($user_guids); } $group_guid = get_input('group_guid'); +$group = get_entity($group_guid); -if (sizeof($user_guid)) { - foreach ($user_guid as $u_id) { - $user = get_entity($u_id); - $group = get_entity($group_guid); - - if ($user && $group && ($group instanceof ElggGroup) && $group->canEdit()) { - - if (!check_entity_relationship($group->guid, 'invited', $user->guid)) { - - // Create relationship - add_entity_relationship($group->guid, 'invited', $user->guid); - - // Send email - $url = elgg_normalize_url("groups/invitations/$user->username"); - $result = notify_user($user->getGUID(), $group->owner_guid, - elgg_echo('groups:invite:subject', array($user->name, $group->name)), - elgg_echo('groups:invite:body', array( - $user->name, - $logged_in_user->name, - $group->name, - $url, - )), - NULL); - if ($result) { - system_message(elgg_echo("groups:userinvited")); - } else { - register_error(elgg_echo("groups:usernotinvited")); - } - } else { - register_error(elgg_echo("groups:useralreadyinvited")); - } +if (count($user_guids) > 0 && elgg_instanceof($group, 'group') && $group->canEdit()) { + foreach ($user_guids as $guid) { + $user = get_user($guid); + if (!$user) { + continue; + } + + if (check_entity_relationship($group->guid, 'invited', $user->guid)) { + register_error(elgg_echo("groups:useralreadyinvited")); + continue; + } + + if (check_entity_relationship($user->guid, 'member', $group->guid)) { + // @todo add error message + continue; + } + + // Create relationship + add_entity_relationship($group->guid, 'invited', $user->guid); + + // Send notification + $url = elgg_normalize_url("groups/invitations/$user->username"); + $result = notify_user($user->getGUID(), $group->owner_guid, + elgg_echo('groups:invite:subject', array($user->name, $group->name)), + elgg_echo('groups:invite:body', array( + $user->name, + $logged_in_user->name, + $group->name, + $url, + )), + NULL); + if ($result) { + system_message(elgg_echo("groups:userinvited")); + } else { + register_error(elgg_echo("groups:usernotinvited")); } } } diff --git a/mod/htmlawed/start.php b/mod/htmlawed/start.php index 12b6470a3..25a70a4aa 100644 --- a/mod/htmlawed/start.php +++ b/mod/htmlawed/start.php @@ -156,10 +156,8 @@ function htmlawed_tag_post_processor($element, $attributes = false) { * Runs unit tests for htmlawed * * @return array - * */ + */ function htmlawed_test($hook, $type, $value, $params) { - global $CONFIG; - $value[] = dirname(__FILE__) . '/tests/tags.php'; return $value; } diff --git a/mod/htmlawed/tests/tags.php b/mod/htmlawed/tests/tags.php index b3914a9d6..05fe829f4 100644 --- a/mod/htmlawed/tests/tags.php +++ b/mod/htmlawed/tests/tags.php @@ -1,45 +1,47 @@ <?php + /** * Dupplicated tags in htmlawed */ class HtmLawedDuplicateTagsTest extends ElggCoreUnitTest { - /** - * Called before each test object. - */ - public function __construct() { - parent::__construct(); - } - - /** - * Called before each test method. - */ - public function setUp() { - } - - /** - * Called after each test method. - */ - public function tearDown() { - // do not allow SimpleTest to interpret Elgg notices as exceptions - $this->swallowErrors(); - } - - /** - * Called after each test object. - */ - public function __destruct() { - elgg_set_ignore_access($this->ia); - // all __destruct() code should go above here - parent::__destruct(); - } - - public function testNotDuplicateTags() { - $filter_html = '<ul><li>item</li></ul>'; - set_input('test', $filter_html); - - $expected = $filter_html; - $result = get_input('test'); - $this->assertEqual($result, $expected); - } + /** + * Called before each test object. + */ + public function __construct() { + parent::__construct(); + } + + /** + * Called before each test method. + */ + public function setUp() { + + } + + /** + * Called after each test method. + */ + public function tearDown() { + // do not allow SimpleTest to interpret Elgg notices as exceptions + $this->swallowErrors(); + } + + /** + * Called after each test object. + */ + public function __destruct() { + // all __destruct() code should go above here + parent::__destruct(); + } + + public function testNotDuplicateTags() { + $filter_html = '<ul><li>item</li></ul>'; + set_input('test', $filter_html); + + $expected = $filter_html; + $result = get_input('test'); + $this->assertEqual($result, $expected); + } + }
\ No newline at end of file diff --git a/version.php b/version.php index b5822b371..c5fc817d4 100644 --- a/version.php +++ b/version.php @@ -14,4 +14,4 @@ $version = 2013030600; // Human-friendly version name -$release = '1.8.14'; +$release = '1.8.15'; diff --git a/views/default/css/admin.php b/views/default/css/admin.php index 8197f29de..3896ded5d 100644 --- a/views/default/css/admin.php +++ b/views/default/css/admin.php @@ -446,7 +446,8 @@ input { .elgg-input-text, .elgg-input-tags, .elgg-input-url, -.elgg-input-plaintext { +.elgg-input-plaintext, +.elgg-input-longtext { width: 98%; } textarea { |