diff options
Diffstat (limited to 'engine/tests')
| -rw-r--r-- | engine/tests/api/access_collections.php | 3 | ||||
| -rw-r--r-- | engine/tests/api/annotations.php | 80 | ||||
| -rw-r--r-- | engine/tests/api/entity_getter_functions.php | 68 | ||||
| -rw-r--r-- | engine/tests/api/helpers.php | 103 | ||||
| -rw-r--r-- | engine/tests/api/metadata.php | 16 | ||||
| -rw-r--r-- | engine/tests/api/metadata_cache.php | 7 | ||||
| -rw-r--r-- | engine/tests/api/metastrings.php | 33 | ||||
| -rw-r--r-- | engine/tests/api/plugins.php | 4 | ||||
| -rw-r--r-- | engine/tests/objects/entities.php | 2 | ||||
| -rw-r--r-- | engine/tests/objects/objects.php | 2 | ||||
| -rw-r--r-- | engine/tests/objects/users.php | 21 | ||||
| -rw-r--r-- | engine/tests/regression/trac_bugs.php | 190 | ||||
| -rw-r--r-- | engine/tests/test_files/plugin_18/manifest.xml | 2 | ||||
| -rw-r--r-- | engine/tests/test_files/xxe/external_entity.txt | 1 | ||||
| -rw-r--r-- | engine/tests/test_files/xxe/request.xml | 8 | 
15 files changed, 513 insertions, 27 deletions
| diff --git a/engine/tests/api/access_collections.php b/engine/tests/api/access_collections.php index ebcd7d318..4acfae596 100644 --- a/engine/tests/api/access_collections.php +++ b/engine/tests/api/access_collections.php @@ -54,7 +54,6 @@ class ElggCoreAccessCollectionsTest extends ElggCoreUnitTest {  	}  	public function testCreateGetDeleteACL() { -		global $DB_QUERY_CACHE;  		$acl_name = 'test access collection';  		$acl_id = create_access_collection($acl_name); @@ -67,8 +66,6 @@ class ElggCoreAccessCollectionsTest extends ElggCoreUnitTest {  		$this->assertEqual($acl->id, $acl_id);  		if ($acl) { -			$DB_QUERY_CACHE = array(); -			  			$this->assertEqual($acl->name, $acl_name);  			$result = delete_access_collection($acl_id); diff --git a/engine/tests/api/annotations.php b/engine/tests/api/annotations.php index 947292970..c0b0687cc 100644 --- a/engine/tests/api/annotations.php +++ b/engine/tests/api/annotations.php @@ -65,6 +65,86 @@ class ElggCoreAnnotationAPITest extends ElggCoreUnitTest {  		$annotations = elgg_get_annotations($options);  		$this->assertTrue(empty($annotations)); +		// nothing to delete so null returned +		$this->assertNull(elgg_delete_annotations($options)); + +		$this->assertTrue($e->delete()); +	} + +	public function testElggDisableAnnotations() { +		$e = new ElggObject(); +		$e->save(); + +		for ($i=0; $i<30; $i++) { +			$e->annotate('test_annotation', rand(0,10000)); +		} + +		$options = array( +			'guid' => $e->getGUID(), +			'limit' => 0 +		); + +		$this->assertTrue(elgg_disable_annotations($options)); + +		$annotations = elgg_get_annotations($options); +		$this->assertTrue(empty($annotations)); + +		access_show_hidden_entities(true); +		$annotations = elgg_get_annotations($options); +		$this->assertIdentical(30, count($annotations)); +		access_show_hidden_entities(false); + +		$this->assertTrue($e->delete()); +	} + +	public function testElggEnableAnnotations() { +		$e = new ElggObject(); +		$e->save(); + +		for ($i=0; $i<30; $i++) { +			$e->annotate('test_annotation', rand(0,10000)); +		} + +		$options = array( +			'guid' => $e->getGUID(), +			'limit' => 0 +		); + +		$this->assertTrue(elgg_disable_annotations($options)); + +		// cannot see any annotations so returns null +		$this->assertNull(elgg_enable_annotations($options)); + +		access_show_hidden_entities(true); +		$this->assertTrue(elgg_enable_annotations($options)); +		access_show_hidden_entities(false); + +		$annotations = elgg_get_annotations($options); +		$this->assertIdentical(30, count($annotations)); + +		$this->assertTrue($e->delete()); +	} + +	public function testElggAnnotationExists() { +		$e = new ElggObject(); +		$e->save(); +		$guid = $e->getGUID(); + +		$this->assertFalse(elgg_annotation_exists($guid, 'test_annotation')); + +		$e->annotate('test_annotation', rand(0, 10000)); +		$this->assertTrue(elgg_annotation_exists($guid, 'test_annotation')); +		// this metastring should always exist but an annotation of this name should not +		$this->assertFalse(elgg_annotation_exists($guid, 'email')); + +		$options = array( +			'guid' => $guid, +			'limit' => 0 +		); +		$this->assertTrue(elgg_disable_annotations($options)); +		$this->assertTrue(elgg_annotation_exists($guid, 'test_annotation')); +  		$this->assertTrue($e->delete()); +		$this->assertFalse(elgg_annotation_exists($guid, 'test_annotation'));  	}  } diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index 9db248de9..fef9dc0c5 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -2648,7 +2648,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest {  			$name = 'test_annotation_' . rand(0, 9999);  			$values = array();  			$options = array( -				'types' => 'object', +				'type' => 'object',  				'subtypes' => $subtypes,  				'limit' => 5  			); @@ -2687,7 +2687,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest {  			$order = array_keys($values);  			$options = array( -				'types' => 'object', +				'type' => 'object',  				'subtypes' => $subtypes,  				'limit' => 5,  				'annotation_name' => $name, @@ -2729,6 +2729,36 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest {  		}  	} +	public function testElggGetEntitiesFromAnnotationCalculationCount() { +		// add two annotations with a unique name to an entity +		// then count the number of entities with that annotation name + +		$subtypes = $this->getRandomValidSubtypes(array('object'), 1); +		$name = 'test_annotation_' . rand(0, 9999); +		$values = array(); +		$options = array( +			'type' => 'object', +			'subtypes' => $subtypes, +			'limit' => 1 +		); +		$es = elgg_get_entities($options); +		$entity = $es[0]; +		$value = rand(0, 9999); +		$entity->annotate($name, $value); +		$value = rand(0, 9999); +		$entity->annotate($name, $value); + +		$options = array( +			'type' => 'object', +			'subtypes' => $subtypes, +			'annotation_name' => $name, +			'calculation' => 'count', +			'count' => true, +		); +		$count = elgg_get_entities_from_annotation_calculation($options); +		$this->assertEqual(1, $count); +	} +  	public function testElggGetAnnotationsAnnotationNames() {  		$options = array('annotation_names' => array());  		$a_e_map = array(); @@ -2817,4 +2847,38 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest {  		$entities = elgg_get_entities($options);  		$this->assertFalse($entities);  	} + +	public function testEGEEmptySubtypePlurality() { +		$options = array( +			'type' => 'user', +			'subtypes' => '' +		); + +		$entities = elgg_get_entities($options); +		$this->assertTrue(is_array($entities)); + +		$options = array( +			'type' => 'user', +			'subtype' => '' +		); + +		$entities = elgg_get_entities($options); +		$this->assertTrue(is_array($entities)); + +		$options = array( +			'type' => 'user', +			'subtype' => array('') +		); + +		$entities = elgg_get_entities($options); +		$this->assertTrue(is_array($entities)); + +		$options = array( +			'type' => 'user', +			'subtypes' => array('') +		); + +		$entities = elgg_get_entities($options); +		$this->assertTrue(is_array($entities)); +	}  } diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php index 62e4471e0..414fb4145 100644 --- a/engine/tests/api/helpers.php +++ b/engine/tests/api/helpers.php @@ -519,7 +519,7 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		$this->assertIdentical($elements_sorted_string, $test_elements);  	} -	// see http://trac.elgg.org/ticket/4288 +	// see https://github.com/elgg/elgg/issues/4288  	public function testElggBatchIncOffset() {  		// normal increment  		$options = array( @@ -578,6 +578,107 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		$this->assertEqual(11, $j);  	} +	public function testElggBatchReadHandlesBrokenEntities() { +		$num_test_entities = 8; +		$guids = array(); +		for ($i = $num_test_entities; $i > 0; $i--) { +			$entity = new ElggObject(); +			$entity->type = 'object'; +			$entity->subtype = 'test_5357_subtype'; +			$entity->access_id = ACCESS_PUBLIC; +			$entity->save(); +			$guids[] = $entity->guid; +			_elgg_invalidate_cache_for_entity($entity->guid); +		} + +		// break entities such that the first fetch has one incomplete +		// and the second and third fetches have only incompletes! +		$db_prefix = elgg_get_config('dbprefix'); +		delete_data(" +			DELETE FROM {$db_prefix}objects_entity +			WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}, {$guids[4]}, {$guids[5]}) +		"); + +		$options = array( +			'type' => 'object', +			'subtype' => 'test_5357_subtype', +			'order_by' => 'e.guid', +		); + +		$entities_visited = array(); +		$batch = new ElggBatch('elgg_get_entities', $options, null, 2); +		/* @var ElggEntity[] $batch */ +		foreach ($batch as $entity) { +			$entities_visited[] = $entity->guid; +		} + +		// The broken entities should not have been visited +		$this->assertEqual($entities_visited, array($guids[0], $guids[6], $guids[7])); + +		// cleanup (including leftovers from previous tests) +		$entity_rows = elgg_get_entities(array_merge($options, array( +			'callback' => '', +			'limit' => false, +		))); +		$guids = array(); +		foreach ($entity_rows as $row) { +			$guids[] = $row->guid; +		} +		delete_data("DELETE FROM {$db_prefix}entities WHERE guid IN (" . implode(',', $guids) . ")"); +		delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid IN (" . implode(',', $guids) . ")"); +	} + +	public function testElggBatchDeleteHandlesBrokenEntities() { +		$num_test_entities = 8; +		$guids = array(); +		for ($i = $num_test_entities; $i > 0; $i--) { +			$entity = new ElggObject(); +			$entity->type = 'object'; +			$entity->subtype = 'test_5357_subtype'; +			$entity->access_id = ACCESS_PUBLIC; +			$entity->save(); +			$guids[] = $entity->guid; +			_elgg_invalidate_cache_for_entity($entity->guid); +		} + +		// break entities such that the first fetch has one incomplete +		// and the second and third fetches have only incompletes! +		$db_prefix = elgg_get_config('dbprefix'); +		delete_data(" +			DELETE FROM {$db_prefix}objects_entity +			WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}, {$guids[4]}, {$guids[5]}) +		"); + +		$options = array( +			'type' => 'object', +			'subtype' => 'test_5357_subtype', +			'order_by' => 'e.guid', +		); + +		$entities_visited = array(); +		$batch = new ElggBatch('elgg_get_entities', $options, null, 2, false); +		/* @var ElggEntity[] $batch */ +		foreach ($batch as $entity) { +			$entities_visited[] = $entity->guid; +			$entity->delete(); +		} + +		// The broken entities should not have been visited +		$this->assertEqual($entities_visited, array($guids[0], $guids[6], $guids[7])); + +		// cleanup (including leftovers from previous tests) +		$entity_rows = elgg_get_entities(array_merge($options, array( +			'callback' => '', +			'limit' => false, +		))); +		$guids = array(); +		foreach ($entity_rows as $row) { +			$guids[] = $row->guid; +		} +		delete_data("DELETE FROM {$db_prefix}entities WHERE guid IN (" . implode(',', $guids) . ")"); +		delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid IN (" . implode(',', $guids) . ")"); +	} +  	static function elgg_batch_callback_test($options, $reset = false) {  		static $count = 1; diff --git a/engine/tests/api/metadata.php b/engine/tests/api/metadata.php index 825290d80..d23510c6a 100644 --- a/engine/tests/api/metadata.php +++ b/engine/tests/api/metadata.php @@ -123,9 +123,23 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest {  		$e->delete();  	} +	/** +	 * https://github.com/Elgg/Elgg/issues/4867 +	 */ +	public function testElggGetEntityMetadataWhereSqlWithFalseValue() { +		$pair = array('name' => 'test' , 'value' => false); +		$result = elgg_get_entity_metadata_where_sql('e', 'metadata', null, null, $pair); +		$where = preg_replace( '/\s+/', ' ', $result['wheres'][0]); +		$this->assertTrue(strpos($where, "msn1.string = 'test' AND BINARY msv1.string = 0") > 0); + +		$result = elgg_get_entity_metadata_where_sql('e', 'metadata', array('test'), array(false)); +		$where = preg_replace( '/\s+/', ' ', $result['wheres'][0]); +		$this->assertTrue(strpos($where, "msn.string IN ('test')) AND ( BINARY msv.string IN ('0')")); +	} +  	// Make sure metadata with multiple values is correctly deleted when re-written  	// by another user -	// http://trac.elgg.org/ticket/2776 +	// https://github.com/elgg/elgg/issues/2776  	public function test_elgg_metadata_multiple_values() {  		$u1 = new ElggUser();  		$u1->username = rand(); diff --git a/engine/tests/api/metadata_cache.php b/engine/tests/api/metadata_cache.php index 846116a7b..7fb328169 100644 --- a/engine/tests/api/metadata_cache.php +++ b/engine/tests/api/metadata_cache.php @@ -166,4 +166,11 @@ class ElggCoreMetadataCacheTest extends ElggCoreUnitTest {  		$actual = $this->cache->filterMetadataHeavyEntities($guids, 6000);  		$this->assertIdentical($actual, $expected);  	} + +	public function testCreateMetadataInvalidates() { +		$this->obj1->foo = 1; +		create_metadata($this->guid1, 'foo', 2, '', elgg_get_logged_in_user_guid(), ACCESS_FRIENDS); + +		$this->assertEqual($this->obj1->foo, 2); +	}  } diff --git a/engine/tests/api/metastrings.php b/engine/tests/api/metastrings.php index 0a8945084..5efdab972 100644 --- a/engine/tests/api/metastrings.php +++ b/engine/tests/api/metastrings.php @@ -55,8 +55,11 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest {  	 * Called after each test method.  	 */  	public function tearDown() { -		// do not allow SimpleTest to interpret Elgg notices as exceptions -		$this->swallowErrors(); +		access_show_hidden_entities(true); +		elgg_delete_annotations(array( +			'guid' => $this->object->guid, +		)); +		access_show_hidden_entities(false);  	}  	/** @@ -98,6 +101,31 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest {  		}  	} +	public function testGetMetastringObjectFromIDWithDisabledAnnotation() { +		$name = 'test_annotation_name' . rand(); +		$value = 'test_annotation_value' . rand(); +		$id = create_annotation($this->object->guid, $name, $value); +		$annotation = elgg_get_annotation_from_id($id); +		$this->assertTrue($annotation->disable()); + +		$test = elgg_get_metastring_based_object_from_id($id, 'annotation'); +		$this->assertEqual(false, $test); +	} + +	public function testGetMetastringBasedObjectWithDisabledAnnotation() { +		$name = 'test_annotation_name' . rand(); +		$value = 'test_annotation_value' . rand(); +		$id = create_annotation($this->object->guid, $name, $value); +		$annotation = elgg_get_annotation_from_id($id); +		$this->assertTrue($annotation->disable()); + +		$test = elgg_get_metastring_based_objects(array( +			'metastring_type' => 'annotations', +			'guid' => $this->object->guid, +		)); +		$this->assertEqual(array(), $test); +	} +  	public function testEnableDisableByID() {  		$db_prefix = elgg_get_config('dbprefix');  		$annotations = $this->createAnnotations(1); @@ -119,7 +147,6 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest {  			// enable  			$ashe = access_get_show_hidden_status();  			access_show_hidden_entities(true); -			flush();  			$this->assertTrue(elgg_set_metastring_based_object_enabled_by_id($id, 'yes', $type));  			$test = get_data($q); diff --git a/engine/tests/api/plugins.php b/engine/tests/api/plugins.php index 114f3991b..d0f111c48 100644 --- a/engine/tests/api/plugins.php +++ b/engine/tests/api/plugins.php @@ -69,7 +69,7 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest {  			'description' => 'A longer, more interesting description.',  			'website' => 'http://www.elgg.org/',  			'repository' => 'https://github.com/Elgg/Elgg', -			'bugtracker' => 'http://trac.elgg.org', +			'bugtracker' => 'https://github.com/elgg/elgg/issues',  			'donations' => 'http://elgg.org/supporter.php',  			'copyright' => '(C) Elgg Foundation 2011',  			'license' => 'GNU General Public License version 2', @@ -174,7 +174,7 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest {  	}  		public function testElggPluginManifestGetBugtracker() { -		$this->assertEqual($this->manifest18->getBugTrackerURL(), 'http://trac.elgg.org'); +		$this->assertEqual($this->manifest18->getBugTrackerURL(), 'https://github.com/elgg/elgg/issues');  		$this->assertEqual($this->manifest17->getBugTrackerURL(), '');  	} diff --git a/engine/tests/objects/entities.php b/engine/tests/objects/entities.php index 248b85c9e..bac72079e 100644 --- a/engine/tests/objects/entities.php +++ b/engine/tests/objects/entities.php @@ -271,7 +271,7 @@ class ElggCoreEntityTest extends ElggCoreUnitTest {  		$this->save_entity();  		// test deleting incorrectly -		// @link http://trac.elgg.org/ticket/2273 +		// @link https://github.com/elgg/elgg/issues/2273  		$this->assertNull($this->entity->deleteMetadata('impotent'));  		$this->assertEqual($this->entity->important, 'indeed!'); diff --git a/engine/tests/objects/objects.php b/engine/tests/objects/objects.php index 915594e0a..263ab2414 100644 --- a/engine/tests/objects/objects.php +++ b/engine/tests/objects/objects.php @@ -194,7 +194,7 @@ class ElggCoreObjectTest extends ElggCoreUnitTest {  		$old = elgg_set_ignore_access(true);  	} -	// see http://trac.elgg.org/ticket/1196 +	// see https://github.com/elgg/elgg/issues/1196  	public function testElggEntityRecursiveDisableWhenLoggedOut() {  		$e1 = new ElggObject();  		$e1->access_id = ACCESS_PUBLIC; diff --git a/engine/tests/objects/users.php b/engine/tests/objects/users.php index a3573acb6..8a1033ac4 100644 --- a/engine/tests/objects/users.php +++ b/engine/tests/objects/users.php @@ -65,6 +65,9 @@ class ElggCoreUserTest extends ElggCoreUnitTest {  		$attributes['code'] = NULL;  		$attributes['banned'] = 'no';  		$attributes['admin'] = 'no'; +		$attributes['prev_last_action'] = NULL; +		$attributes['last_login'] = NULL; +		$attributes['prev_last_login'] = NULL;  		ksort($attributes);  		$entity_attributes = $this->user->expose_attributes(); @@ -142,7 +145,7 @@ class ElggCoreUserTest extends ElggCoreUnitTest {  	}  	public function testElggUserNameCache() { -		// Trac #1305 +		// issue https://github.com/elgg/elgg/issues/1305  		// very unlikely a user would have this username  		$name = (string)time(); @@ -156,6 +159,22 @@ class ElggCoreUserTest extends ElggCoreUnitTest {  		$this->assertFalse($user);  	} +	public function testGetUserByUsernameAcceptsUrlEncoded() { +		$username = (string)time(); +		$this->user->username = $username; +		$guid = $this->user->save(); + +		// percent encode first letter +		$first_letter = $username[0]; +		$first_letter = str_pad('%' . dechex(ord($first_letter)), 2, '0', STR_PAD_LEFT); +		$username =   $first_letter . substr($username, 1); + +		$user = get_user_by_username($username); +		$this->assertTrue((bool) $user); +		$this->assertEqual($guid, $user->guid); + +		$this->user->delete(); +	}  	public function testElggUserMakeAdmin() {  		global $CONFIG; diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 691433a41..689275661 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -1,7 +1,7 @@  <?php  /** - * Elgg Regression Tests -- Trac Bugfixes - * Any bugfixes from Trac that require testing belong here. + * Elgg Regression Tests -- GitHub Bugfixes + * Any bugfixes from GitHub that require testing belong here.   *   * @package Elgg   * @subpackage Test @@ -201,26 +201,28 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest {  	}  	/** -	 * http://trac.elgg.org/ticket/3210 - Don't remove -s in friendly titles -	 * http://trac.elgg.org/ticket/2276 - improve char encoding +	 * https://github.com/elgg/elgg/issues/3210 - Don't remove -s in friendly titles +	 * https://github.com/elgg/elgg/issues/2276 - improve char encoding  	 */  	public function test_friendly_title() {  		$cases = array( +			// acid test +			"B&N > Amazon, OK? <bold> 'hey!' $34" +			=> "bn-amazon-ok-bold-hey-34", +  			// hyphen, underscore and ASCII whitespace replaced by separator,  			// other non-alphanumeric ASCII removed -			"a-a_a a\na\ra\ta\va!a\"a#a\$a%a&a'a(a)a*a+a,a.a/a:a;a<a=a>a?a@a[a\\a]a^a`a{a|a}a~a" -			=> "a-a-a-a-a-a-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - +			"a-a_a a\na\ra\ta\va!a\"a#a\$a%aa'a(a)a*a+a,a.a/a:a;a=a?a@a[a\\a]a^a`a{a|a}a~a" +			=> "a-a-a-a-a-a-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +			  			// separators trimmed -			"-_ hello _-" => "hello", +			"-_ hello _-" +			=> "hello",  			// accents removed, lower case, other multibyte chars are URL encoded  			"I\xC3\xB1t\xC3\xABrn\xC3\xA2ti\xC3\xB4n\xC3\xA0liz\xC3\xA6ti\xC3\xB8n, AND \xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E"  				// Iñtërnâtiônàlizætiøn, AND 日本語  			=> 'internationalizaetion-and-%E6%97%A5%E6%9C%AC%E8%AA%9E', - -			// some HTML entity replacements -			"Me & You" => 'me-and-you',  		);  		// where available, string is converted to NFC before transliteration @@ -234,4 +236,170 @@ 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', + +			'web archive anchor <a href="http://web.archive.org/web/20000229040250/http://www.google.com/">google</a>' => +				'web archive anchor <a href="http://web.archive.org/web/20000229040250/http://www.google.com/">google</a>', + +			'single quotes already anchor <a href=\'http://www.yahoo.com\'>yahoo</a>' => +				'single quotes already anchor <a href=\'http://www.yahoo.com\'>yahoo</a>', + +			'unquoted already anchor <a href=http://www.yahoo.com>yahoo</a>' => +				'unquoted already anchor <a href=http://www.yahoo.com>yahoo</a>', + +			'parens in uri http://thedailywtf.com/Articles/A-(Long-Overdue)-BuildMaster-Introduction.aspx' => +				'parens in uri <a href="http://thedailywtf.com/Articles/A-(Long-Overdue)-BuildMaster-Introduction.aspx" rel="nofollow">http:/<wbr />/<wbr />thedailywtf.com/<wbr />Articles/<wbr />A-(Long-Overdue)-BuildMaster-Introduction.aspx</a>' +		); +		foreach ($cases as $input => $output) { +			$this->assertEqual($output, parse_urls($input)); +		} +	} +	 +	/** +	 * Ensure additional select columns do not end up in entity attributes. +	 * +	 * https://github.com/Elgg/Elgg/issues/5538 +	 */ +	public function test_extra_columns_dont_appear_in_attributes() { +		global $ENTITY_CACHE; + +		// may not have groups in DB - let's create one +		$group = new ElggGroup(); +		$group->name = 'test_group'; +		$group->access_id = ACCESS_PUBLIC; +		$this->assertTrue($group->save() !== false); +		 +		// entity cache interferes with our test +		$ENTITY_CACHE = array(); +		 +		foreach (array('site', 'user', 'group', 'object') as $type) { +			$entities = elgg_get_entities(array( +				'type' => $type, +				'selects' => array('1 as _nonexistent_test_column'), +				'limit' => 1, +			)); +			if (!$this->assertTrue($entities, "Query for '$type' did not return an entity.")) { +				continue; +			} +			$entity = $entities[0]; +			$this->assertNull($entity->_nonexistent_test_column, "Additional select columns are leaking to attributes for '$type'"); +		} +		 +		$group->delete(); +	} + +	/** +	 * Ensure that ElggBatch doesn't go into infinite loop when disabling annotations recursively when show hidden is enabled. +	 * +	 * https://github.com/Elgg/Elgg/issues/5952 +	 */ +	public function test_disabling_annotations_infinite_loop() { + +		//let's have some entity +		$group = new ElggGroup(); +		$group->name = 'test_group'; +		$group->access_id = ACCESS_PUBLIC; +		$this->assertTrue($group->save() !== false); + +		$total = 51; +		//add some annotations +		for ($cnt = 0; $cnt < $total; $cnt++) { +			$group->annotate('test_annotation', 'value_' . $total); +		} + +		//disable them +		$show_hidden = access_get_show_hidden_status(); +		access_show_hidden_entities(true); +		$options = array( +			'guid' => $group->guid, +			'limit' => $total, //using strict limit to avoid real infinite loop and just see ElggBatch limiting on it before finishing the work +		); +		elgg_disable_annotations($options); +		access_show_hidden_entities($show_hidden); + +		//confirm all being disabled +		$annotations = $group->getAnnotations(array( +			'limit' => $total, +		)); +		foreach ($annotations as $annotation) { +			$this->assertTrue($annotation->enabled == 'no'); +		} + +		//delete group and annotations +		$group->delete(); +	} + +	public function test_ElggXMLElement_does_not_load_external_entities() { +		$elLast = libxml_disable_entity_loader(false); + +		// build payload that should trigger loading of external entity +		$payload = file_get_contents(dirname(dirname(__FILE__)) . '/test_files/xxe/request.xml'); +		$path = realpath(dirname(dirname(__FILE__)) . '/test_files/xxe/external_entity.txt'); +		$path = str_replace('\\', '/', $path); +		if ($path[0] != '/') { +			$path = '/' . $path; +		} +		$path = 'file://' . $path; +		$payload = sprintf($payload, $path); + +		// make sure we can actually this in this environment +		$element = new SimpleXMLElement($payload); +		$can_load_entity = preg_match('/secret/', (string)$element->methodName); + +		$this->skipUnless($can_load_entity, "XXE vulnerability cannot be tested on this system"); + +		if ($can_load_entity) { +			$el = new ElggXMLElement($payload); +			$chidren = $el->getChildren(); +			$content = $chidren[0]->getContent(); +			$this->assertNoPattern('/secret/', $content); +		} + +		libxml_disable_entity_loader($elLast); +	}  } diff --git a/engine/tests/test_files/plugin_18/manifest.xml b/engine/tests/test_files/plugin_18/manifest.xml index 5d788616a..c8b407511 100644 --- a/engine/tests/test_files/plugin_18/manifest.xml +++ b/engine/tests/test_files/plugin_18/manifest.xml @@ -7,7 +7,7 @@  	<description>A longer, more interesting description.</description>  	<website>http://www.elgg.org/</website>  	<repository>https://github.com/Elgg/Elgg</repository> -	<bugtracker>http://trac.elgg.org</bugtracker> +	<bugtracker>https://github.com/elgg/elgg/issues</bugtracker>  	<donations>http://elgg.org/supporter.php</donations>  	<copyright>(C) Elgg Foundation 2011</copyright>  	<license>GNU General Public License version 2</license> diff --git a/engine/tests/test_files/xxe/external_entity.txt b/engine/tests/test_files/xxe/external_entity.txt new file mode 100644 index 000000000..536aca34d --- /dev/null +++ b/engine/tests/test_files/xxe/external_entity.txt @@ -0,0 +1 @@ +secret
\ No newline at end of file diff --git a/engine/tests/test_files/xxe/request.xml b/engine/tests/test_files/xxe/request.xml new file mode 100644 index 000000000..4390f9db2 --- /dev/null +++ b/engine/tests/test_files/xxe/request.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<!DOCTYPE foo [ +<!ELEMENT methodName ANY > +<!ENTITY xxe SYSTEM "%s" > +]> +<methodCall> +    <methodName>test&xxe;test</methodName> +</methodCall> | 
