Browse Source

moved from https://github.com/epsylon/Elgg-Lorea-Hydra

psy 1 year ago
parent
commit
e48014c2e0
100 changed files with 47893 additions and 2 deletions
  1. 1 0
      .gitignore
  2. 17 0
      .mailmap
  3. 23 0
      .scripts/fix_style.php
  4. 57 0
      .scripts/move_namespaces_to_top.php
  5. 84 0
      .scripts/release.php
  6. 44 0
      .scripts/travis/check_commit_msgs.sh
  7. 151 0
      .scripts/validate_commit_msg.php
  8. 22 0
      .scripts/write-changelog.js
  9. 27 0
      .scrutinizer.yml
  10. 254 0
      .tx/config
  11. 2492 0
      CHANGELOG.md
  12. 1 0
      CODING.txt
  13. 11 0
      CONTRIBUTING.md
  14. 30 0
      CONTRIBUTORS.txt
  15. 14 0
      COPYRIGHT.txt
  16. 42438 0
      ChangeLog
  17. 16 0
      Gruntfile.js
  18. 1 0
      INSTALL.txt
  19. 280 0
      LICENSE.txt
  20. 25 2
      README.md
  21. 1 0
      UPGRADE.txt
  22. 9 0
      _graphics/SPRITES_LICENSE.TXT
  23. BIN
      _graphics/admin_sprites.png
  24. BIN
      _graphics/ajax_loader.gif
  25. BIN
      _graphics/ajax_loader_bw.gif
  26. BIN
      _graphics/button_background.gif
  27. BIN
      _graphics/button_graduation.png
  28. BIN
      _graphics/elgg_logo.png
  29. BIN
      _graphics/elgg_sprites.png
  30. BIN
      _graphics/elgg_toolbar_logo.gif
  31. BIN
      _graphics/favicon-128.png
  32. BIN
      _graphics/favicon-16.png
  33. BIN
      _graphics/favicon-32.png
  34. BIN
      _graphics/favicon-64.png
  35. BIN
      _graphics/favicon.ico
  36. 84 0
      _graphics/favicon.svg
  37. BIN
      _graphics/friendspicker.png
  38. BIN
      _graphics/header_shadow.png
  39. BIN
      _graphics/icons/default/large.png
  40. BIN
      _graphics/icons/default/medium.png
  41. BIN
      _graphics/icons/default/small.png
  42. BIN
      _graphics/icons/default/tiny.png
  43. BIN
      _graphics/icons/default/topbar.png
  44. BIN
      _graphics/icons/user/defaultlarge.gif
  45. BIN
      _graphics/icons/user/defaultmaster.gif
  46. BIN
      _graphics/icons/user/defaultmedium.gif
  47. BIN
      _graphics/icons/user/defaultsmall.gif
  48. BIN
      _graphics/icons/user/defaulttiny.gif
  49. BIN
      _graphics/icons/user/defaulttopbar.gif
  50. BIN
      _graphics/powered_by_elgg_badge_drk_bckgnd.gif
  51. BIN
      _graphics/powered_by_elgg_badge_light_bckgnd.gif
  52. BIN
      _graphics/sidebar_background.gif
  53. BIN
      _graphics/spacer.gif
  54. BIN
      _graphics/toptoolbar_background.gif
  55. BIN
      _graphics/two_sidebar_background.gif
  56. BIN
      _graphics/walled_garden/one_column_bottom.png
  57. BIN
      _graphics/walled_garden/one_column_middle.png
  58. BIN
      _graphics/walled_garden/one_column_top.png
  59. BIN
      _graphics/walled_garden/two_column_bottom.png
  60. BIN
      _graphics/walled_garden/two_column_middle.png
  61. BIN
      _graphics/walled_garden/two_column_top.png
  62. 13 0
      actions/admin/delete_admin_notice.php
  63. 34 0
      actions/admin/menu/save.php
  64. 67 0
      actions/admin/plugins/activate.php
  65. 59 0
      actions/admin/plugins/activate_all.php
  66. 52 0
      actions/admin/plugins/deactivate.php
  67. 32 0
      actions/admin/plugins/deactivate_all.php
  68. 38 0
      actions/admin/plugins/set_priority.php
  69. 10 0
      actions/admin/site/flush_cache.php
  70. 19 0
      actions/admin/site/set_maintenance_mode.php
  71. 14 0
      actions/admin/site/set_robots.php
  72. 12 0
      actions/admin/site/unlock_upgrade.php
  73. 103 0
      actions/admin/site/update_advanced.php
  74. 37 0
      actions/admin/site/update_basic.php
  75. 167 0
      actions/admin/upgrades/upgrade_comments.php
  76. 79 0
      actions/admin/upgrades/upgrade_comments_access.php
  77. 101 0
      actions/admin/upgrades/upgrade_datadirs.php
  78. 165 0
      actions/admin/upgrades/upgrade_discussion_replies.php
  79. 30 0
      actions/admin/user/ban.php
  80. 40 0
      actions/admin/user/delete.php
  81. 27 0
      actions/admin/user/makeadmin.php
  82. 27 0
      actions/admin/user/removeadmin.php
  83. 39 0
      actions/admin/user/resetpassword.php
  84. 27 0
      actions/admin/user/unban.php
  85. 78 0
      actions/avatar/crop.php
  86. 36 0
      actions/avatar/remove.php
  87. 68 0
      actions/avatar/upload.php
  88. 22 0
      actions/comment/delete.php
  89. 107 0
      actions/comment/save.php
  90. 22 0
      actions/entities/delete.php
  91. 24 0
      actions/friends/add.php
  92. 31 0
      actions/friends/collections/add.php
  93. 23 0
      actions/friends/collections/delete.php
  94. 23 0
      actions/friends/collections/edit.php
  95. 25 0
      actions/friends/remove.php
  96. 23 0
      actions/import/opendd.php
  97. 76 0
      actions/login.php
  98. 18 0
      actions/logout.php
  99. 43 0
      actions/plugins/settings/save.php
  100. 0 0
      actions/plugins/usersettings/save.php

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+engine/settings.php

+ 17 - 0
.mailmap

@@ -0,0 +1,17 @@
+Aday Talavera <aday.talavera@gmail.com>
+András Szepesházi <szepeshazi@gmail.com>
+Ben Werdmuller <ben@benwerd.com> <ben@36083f99-b078-4883-b0ff-0f9b5a30f544>
+Brett Profitt <brett.profitt@gmail.com> <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>
+Cash Costello <cash.costello@gmail.com> <cash@36083f99-b078-4883-b0ff-0f9b5a30f544>
+Cash Costello <cash.costello@gmail.com>
+Evan Winslow <evan@elgg.org>
+Evan Winslow <evan@elgg.org> <evan.b.winslow@gmail.com>
+Evan Winslow <evan@elgg.org> <ewinslow@36083f99-b078-4883-b0ff-0f9b5a30f544>
+Ismayil Khayredinov <ismayil.khayredinov@hypejunction.com> <ismayil.khayredinov@gmail.com>
+Ismayil Khayredinov <ismayil.khayredinov@hypejunction.com>
+Jeff Tilson <jrtilson@gmail.com> <jtilson@thinkglobalschool.com>
+Jerôme Bakker <jeabakker@coldtrick.com>
+Matt Beckett <beck24@gmail.com>
+Marcus Povey <marcus@marcus-povey.co.uk> <marcus@36083f99-b078-4883-b0ff-0f9b5a30f544>
+Paweł Sroka <srokap@gmail.com>
+Steve Clay <steve@mrclay.org> <sclay@ufl.edu>

+ 23 - 0
.scripts/fix_style.php

@@ -0,0 +1,23 @@
+<?php
+
+if (php_sapi_name() !== "cli") {
+	die('CLI only');
+}
+
+$root = dirname(__DIR__);
+if (!is_writable($root)) {
+	echo "$root is not writable.\n";
+	exit(1);
+}
+
+require "$root/engine/classes/Elgg/Project/CodeStyle.php";
+
+$style = new Elgg\Project\CodeStyle();
+
+$report = $style->fixDirectory($root);
+if (!$report) {
+	exit;
+}
+
+$json_opts = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
+echo json_encode($report, $json_opts) . "\n";

+ 57 - 0
.scripts/move_namespaces_to_top.php

@@ -0,0 +1,57 @@
+<?php
+
+// for each file that has a namespace declaration
+$dir = __DIR__;
+$filesWithNamespaceDeclaration = explode("\n", `grep -r '^namespace' $dir --include=*.php --exclude=vendor -l`);
+
+// echo implode("\n", $filesWithNamespaceDeclaration);
+
+foreach ($filesWithNamespaceDeclaration as $file) {
+	moveNamespaceToTop($file);
+}
+
+function moveNamespaceToTop($file) {
+	if (!is_file($file)) {
+		return;
+	}
+	
+	$contents = file_get_contents($file);
+	$lines = explode("\n", $contents);
+	
+	$nsDeclarationPosition = findPositionOfNamespaceDeclaration($lines);
+	
+	if ($nsDeclarationPosition == -1) {
+		return;
+	}
+	
+	$declaration = $lines[$nsDeclarationPosition];
+	
+	// echo "$declaration\n";
+	
+	unset($lines[$nsDeclarationPosition]);
+	
+	array_splice($lines, 1, 0, $declaration);
+	
+	$newContents = implode("\n", $lines) . "\n";
+	
+	file_put_contents($file, $newContents);
+}
+
+function findPositionOfNamespaceDeclaration($lines) {
+	$position = -1;
+	foreach ($lines as $pos => $lineContent) {
+		if (isNamespaceDeclaration($lineContent)) {
+			$position = $pos;
+		}
+	}
+	
+	return $position;
+}
+
+function isNamespaceDeclaration($lineContent) {
+	return strpos($lineContent, "namespace ") === 0;
+}
+// get the contents of that file and split into lines
+// find the line with the namespace declaration and remove it
+// insert it into the second position
+// write all the lines back to the file

+ 84 - 0
.scripts/release.php

@@ -0,0 +1,84 @@
+<?php
+
+if (!isset($argv[1]) || $argv[1] == '--help') {
+	echo "Usage: php .scripts/release.php <semver>\n";
+	exit;
+}
+
+$version = $argv[1];
+
+// Verify that $version is a valid semver string
+// Performing check according to: https://getcomposer.org/doc/04-schema.md#version
+$regexp = '/^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:dev|rc\.[0-9]+))?$/';
+
+if (!preg_match($regexp, $version, $matches)) {
+	echo "Bad version format. You must follow the format of X.Y.Z with an optional suffix of -dev,"
+		. " or -rc.N (where N is a number).\n";
+	exit(1);
+}
+
+require_once dirname(__DIR__) . '/vendor/autoload.php';
+
+function run_commands($commands) {
+	foreach ($commands as $command) {
+		echo "$command\n";
+		passthru($command, $return_val);
+		if ($return_val !== 0) {
+			echo "Error executing command! Interrupting!\n";
+			exit(2);
+		}
+	}
+}
+
+$elgg_path = dirname(__DIR__);
+
+$branch = "release-$version";
+
+
+// Setup. Version checks are here so we fail early if any deps are missing
+run_commands([
+	"tx --version",
+	"git --version",
+	"npm --version",
+	"node --version",
+	"sphinx-build --version",
+
+	"cd $elgg_path",
+	"git checkout -B $branch",
+]);
+
+// Update translations
+run_commands([
+	"tx pull -af --minimum-perc=95",
+]);
+
+// Clean translations
+$cleaner = new Elgg\I18n\ReleaseCleaner();
+$cleaner->cleanInstallation(dirname(__DIR__));
+foreach ($cleaner->log as $msg) {
+	echo "ReleaseCleaner: $msg\n";
+}
+
+run_commands([
+	"sphinx-build -b gettext docs docs/locale/pot",
+	"sphinx-intl build --locale-dir=docs/locale/",
+	"git add .",
+	"git commit -am \"chore(i18n): update translations\"",
+]);
+
+// Update version in composer.json
+$encoding = new \Elgg\Json\EmptyKeyEncoding();
+
+$composer_path = "$elgg_path/composer.json";
+$composer_config = $encoding->decode(file_get_contents($composer_path));
+$composer_config->version = $version;
+$json = $encoding->encode($composer_config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
+file_put_contents($composer_path, $json);
+
+// Generate changelog
+run_commands(array(
+	"npm install && npm update",
+	"node .scripts/write-changelog.js",
+	"git add .",
+	"git commit -am \"chore(release): v$version\"",
+));

+ 44 - 0
.scripts/travis/check_commit_msgs.sh

@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# Checks the commits msgs in the range of commits travis is testing.
+# Based heavily on
+# https://github.com/JensRantil/angular.js/blob/ffe93bb368037049820ac05ef62f8cc7ed379d98/test-commit-msgs.sh
+
+# Travis's docs are misleading.
+# Check for either a commit or a range (which apparently isn't always a range) and fix as needed.
+if [ "$#" -gt 0 ]; then
+	RANGE=$1
+elif [ "$TRAVIS_COMMIT_RANGE" != "" ]; then
+	RANGE=$TRAVIS_COMMIT_RANGE
+elif [ "$TRAVIS_COMMIT" != "" ]; then
+	RANGE=$TRAVIS_COMMIT
+fi
+
+
+if [ "$RANGE" == "" ]; then
+	echo -n "RANGE is empty!"
+	exit 1
+fi
+
+# Travis sends the ranges with 3 dots. Git only wants 2.
+if [[ "$RANGE" == *...* ]]; then
+	RANGE=`echo $TRAVIS_COMMIT_RANGE | sed 's/\.\.\./../'`
+elif [[ "$RANGE" != *..* ]]; then
+	RANGE="$RANGE~..$RANGE"
+fi
+
+EXIT=0
+for sha in `git log --format=oneline "$RANGE" | cut '-d ' -f1`
+do
+    echo -n "Checking commit message for $sha ... "
+	git log --format=%B -n 1 $sha | php ./.scripts/validate_commit_msg.php
+
+	VALUE=$?
+
+	if [ "$VALUE" -gt 0 ]; then
+		echo -n "./.scripts/validate_commit_msg.php exited with error!"
+		EXIT=$VALUE
+	fi
+done
+
+exit $EXIT

+ 151 - 0
.scripts/validate_commit_msg.php

@@ -0,0 +1,151 @@
+#!/usr/bin/php
+<?php
+/**
+ * Validates the text of a commit message.
+ *
+ * Text should be passed as the only argument, the path to a file (compatibility
+ * with commit-msg git hook), or through stdin.
+ *
+ * Writes any errors to stdout.
+ * Exits with 0 on success, > = 0 on failure.
+ *
+ * Can't pass multiple msgs at once.
+ *
+ * To use as a git commit hook, make sure the PHP path is correct, then
+ * copy or symlink to .git/hooks/commit-msg.
+ *
+ */
+ 
+ $rootDir = dirname(__DIR__);
+ 
+ require_once "$rootDir/vendor/autoload.php";
+
+$is_file = false;
+
+if ($argc === 2) {
+	// check file or msg itself
+	$arg = $argv[1];
+	
+	if (file_exists($arg)) {
+		$is_file = true;
+		$msg_tmp = file_get_contents($arg);
+	} else {
+		$msg_tmp = $arg;
+	}
+} else {
+	// check for std in
+	$msg_tmp = file_get_contents("php://stdin");
+}
+
+$msg = new Elgg\CommitMessage($msg_tmp);
+
+if (!$msg->getMsg()) {
+	usage();
+}
+
+if ($msg->shouldIgnore()) {
+	output("Ignoring commit.", 'notice');
+	exit(0);
+}
+
+// basic format
+// don't continue if not correct
+if (!$msg->isValidFormat()) {
+	output("Fail.", 'error');
+	output("Not in the format `type(component): summary`", 'error');
+	output($msg, 'error');
+	if ($is_file) {
+		output("\nCommit message saved in " . $argv[1]);
+	}
+	exit(1);
+}
+
+$errors = array();
+
+// line lengths
+if (!$msg->isValidLineLength()) {
+	$max = $msg->getMaxLineLength();
+	foreach ($msg->getLengthyLines() as $line_num) {
+		$errors[] = "Longer than $max characters at line $line_num";
+	}
+}
+
+// type
+if (!$msg->isValidType()) {
+	$errors[] = "Invalid type at line 1: `{$msg->getPart('type')}`. Not one of "
+		. implode(', ', $msg->getValidTypes()) . '.';
+}
+
+// component
+// @todo only checking for existence right now via regex
+
+// @todo check for fixes, refs, etc only in body and not in summary?
+// @todo check for correct syntax for breaks and deprecates?
+
+if ($errors) {
+	output('Fail', 'error');
+	foreach ($errors as $error) {
+		output($error, 'error');
+	}
+	$arg = escapeshellarg($msg);
+	
+	$cmd = "printf '%s' $arg | nl -ba";
+	$output = shell_exec($cmd);
+	output($output, 'error', false);
+	if ($is_file) {
+		output("\nCommit message saved in " . $argv[1]);
+	}
+	exit(1);
+} else {
+	// only if we're not in a git commit
+	if (!$is_file) {
+		output('Ok', 'success');
+	}
+	exit(0);
+}
+
+
+/**
+ * Output a msg followed by a \n
+ *
+ * @param string $msg   The message to output
+ * @param bool   $error If true, the message is in red.
+ */
+function output($msg, $type = 'message', $trailing_return = true) {
+	$colors = array(
+		'red' => '0;31',
+		'green' => '0;32',
+		'yellow' => '0;33'
+	);
+
+	$types = array(
+		'message' => '',
+		'error' => 'red',
+		'notice' => 'yellow',
+		'success' => 'green'
+	);
+
+	$n = $trailing_return ? "\n" : '';
+
+	switch ($type) {
+		case 'error':
+		case 'notice':
+		case 'success':
+			$color = $colors[$types[$type]];
+			echo "\033[{$color}m$msg\033[0m{$n}";
+			break;
+
+		case 'message':
+		default;
+			echo "$msg{$n}";
+			break;
+	}
+}
+
+/**
+ * Print usage and exit with error.
+ */
+function usage() {
+	output("Pass a commit message text or a file containing the text of a commit message as the only argument.");
+	exit(1);
+}

+ 22 - 0
.scripts/write-changelog.js

@@ -0,0 +1,22 @@
+#!/usr/bin/env node
+
+var pkg = require('../composer.json');
+var fs = require('fs');
+var changelog = require('elgg-conventional-changelog');
+
+changelog({
+  version: pkg.version,
+  repository: 'https://github.com/Elgg/Elgg',
+  types: {
+      feature: 'Features',
+      perf: 'Performance',
+      docs: 'Documentation',
+      fix: 'Bug Fixes',
+      deprecate: 'Deprecations',
+      breaks: 'Breaking Changes',
+  }
+}, function(err, log) {
+  if (err) throw new Error(err);
+  fs.writeFileSync('CHANGELOG.md', log);
+});
+

+ 27 - 0
.scrutinizer.yml

@@ -0,0 +1,27 @@
+filter:
+    excluded_paths:
+        - 'vendors/*'
+        - '*/vendors/*'
+        - '*/tests/*'
+        - '*/vendor/*'
+tools:
+    external_code_coverage: true
+    js_hint:
+        filter:
+            excluded_paths: ['vendors/*','*/vendors/*','*/tests/*','*/vendor/*']
+    php_mess_detector:
+        filter:
+            excluded_paths: ['vendors/*','*/vendors/*','*/tests/*','*/vendor/*']
+    sensiolabs_security_checker: true
+    php_pdepend:
+        excluded_dirs:
+            - vendors
+            - vendor
+    external_code_coverage:
+        timeout: '1200'
+    php_hhvm: true
+    php_sim: true
+
+    # PHP Similarity Analyzer and Copy/paste Detector cannot be used at
+    # the same time right now. Make sure to either remove, or disable one.
+    php_cpd: false

+ 254 - 0
.tx/config

@@ -0,0 +1,254 @@
+[main]
+host = https://www.transifex.com
+
+[elgg-core.engine]
+file_filter = languages/<lang>.php
+source_file = languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.install]
+file_filter = install/languages/<lang>.php
+source_file = install/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.blog]
+file_filter = mod/blog/languages/<lang>.php
+source_file = mod/blog/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.bookmarks]
+file_filter = mod/bookmarks/languages/<lang>.php
+source_file = mod/bookmarks/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.categories]
+file_filter = mod/categories/languages/<lang>.php
+source_file = mod/categories/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.ckeditor]
+file_filter = mod/ckeditor/languages/<lang>.php
+source_file = mod/ckeditor/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.custom_index]
+file_filter = mod/custom_index/languages/<lang>.php
+source_file = mod/custom_index/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.developers]
+file_filter = mod/developers/languages/<lang>.php
+source_file = mod/developers/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.diagnostics]
+file_filter = mod/diagnostics/languages/<lang>.php
+source_file = mod/diagnostics/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.embed]
+file_filter = mod/embed/languages/<lang>.php
+source_file = mod/embed/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.externalpages]
+file_filter = mod/externalpages/languages/<lang>.php
+source_file = mod/externalpages/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.file]
+file_filter = mod/file/languages/<lang>.php
+source_file = mod/file/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.garbagecollector]
+file_filter = mod/garbagecollector/languages/<lang>.php
+source_file = mod/garbagecollector/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.groups]
+file_filter = mod/groups/languages/<lang>.php
+source_file = mod/groups/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.invitefriends]
+file_filter = mod/invitefriends/languages/<lang>.php
+source_file = mod/invitefriends/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.legacy_urls]
+file_filter = mod/legacy_urls/languages/<lang>.php
+source_file = mod/legacy_urls/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.likes]
+file_filter = mod/likes/languages/<lang>.php
+source_file = mod/likes/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.logbrowser]
+file_filter = mod/logbrowser/languages/<lang>.php
+source_file = mod/logbrowser/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.logrotate]
+file_filter = mod/logrotate/languages/<lang>.php
+source_file = mod/logrotate/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.members]
+file_filter = mod/members/languages/<lang>.php
+source_file = mod/members/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.messageboard]
+file_filter = mod/messageboard/languages/<lang>.php
+source_file = mod/messageboard/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.messages]
+file_filter = mod/messages/languages/<lang>.php
+source_file = mod/messages/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.notifications]
+file_filter = mod/notifications/languages/<lang>.php
+source_file = mod/notifications/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.pages]
+file_filter = mod/pages/languages/<lang>.php
+source_file = mod/pages/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.profile]
+file_filter = mod/profile/languages/<lang>.php
+source_file = mod/profile/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.reportedcontent]
+file_filter = mod/reportedcontent/languages/<lang>.php
+source_file = mod/reportedcontent/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.search]
+file_filter = mod/search/languages/<lang>.php
+source_file = mod/search/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.site_notifications]
+file_filter = mod/site_notifications/languages/<lang>.php
+source_file = mod/web_services/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.tagcloud]
+file_filter = mod/tagcloud/languages/<lang>.php
+source_file = mod/tagcloud/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.thewire]
+file_filter = mod/thewire/languages/<lang>.php
+source_file = mod/thewire/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.twitter_api]
+file_filter = mod/twitter_api/languages/<lang>.php
+source_file = mod/twitter_api/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.uservalidationbyemail]
+file_filter = mod/uservalidationbyemail/languages/<lang>.php
+source_file = mod/uservalidationbyemail/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.web_services]
+file_filter = mod/web_services/languages/<lang>.php
+source_file = mod/web_services/languages/en.php
+source_lang = en
+type = PHP_ARRAY
+
+[elgg-core.docs-design]
+file_filter = docs/locale/<lang>/LC_MESSAGES/design.po
+source_file = docs/locale/pot/design.pot
+source_lang = en
+type = PO
+
+[elgg-core.docs-tutorials]
+file_filter = docs/locale/<lang>/LC_MESSAGES/tutorials.po
+source_file = docs/locale/pot/tutorials.pot
+source_lang = en
+type = PO
+
+[elgg-core.docs-about]
+file_filter = docs/locale/<lang>/LC_MESSAGES/about.po
+source_file = docs/locale/pot/about.pot
+source_lang = en
+type = PO
+
+[elgg-core.docs-index]
+file_filter = docs/locale/<lang>/LC_MESSAGES/index.po
+source_file = docs/locale/pot/index.pot
+source_lang = en
+type = PO
+
+[elgg-core.docs-admin]
+file_filter = docs/locale/<lang>/LC_MESSAGES/admin.po
+source_file = docs/locale/pot/admin.pot
+source_lang = en
+type = PO
+
+[elgg-core.docs-contribute]
+file_filter = docs/locale/<lang>/LC_MESSAGES/contribute.po
+source_file = docs/locale/pot/contribute.pot
+source_lang = en
+type = PO
+
+[elgg-core.docs-appendix]
+file_filter = docs/locale/<lang>/LC_MESSAGES/appendix.po
+source_file = docs/locale/pot/appendix.pot
+source_lang = en
+type = PO
+
+[elgg-core.docs-intro]
+file_filter = docs/locale/<lang>/LC_MESSAGES/intro.po
+source_file = docs/locale/pot/intro.pot
+source_lang = en
+type = PO
+
+[elgg-core.docs-guides]
+file_filter = docs/locale/<lang>/LC_MESSAGES/guides.po
+source_file = docs/locale/pot/guides.pot
+source_lang = en
+type = PO

File diff suppressed because it is too large
+ 2492 - 0
CHANGELOG.md


+ 1 - 0
CODING.txt

@@ -0,0 +1 @@
+See http://learn.elgg.org/en/stable/contribute/code.html

+ 11 - 0
CONTRIBUTING.md

@@ -0,0 +1,11 @@
+## DISCLAIMERS
+
+ * **SECURITY ISSUES SHOULD BE REPORTED TO security @ elgg . org!** Please do not post any security issues on github.
+ * Support requests belong on the [Community site][2]. Tickets with support requests will be closed. 
+ * We cannot make any guarantees as to when your ticket will be resolved or your PR merged. 
+ * **By submitting a pull request you are agreeing to license the code under a [GPLv2 license][3] and [MIT license][4].**
+ * For more information visit http://learn.elgg.org/en/stable/contribute/index.html
+
+ [2]: http://community.elgg.org
+ [3]: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ [4]: http://en.wikipedia.org/wiki/MIT_License

+ 30 - 0
CONTRIBUTORS.txt

@@ -0,0 +1,30 @@
+The following have made notable contributions to the Elgg Project.
+(List in alphabetical order.)
+
+Steve Clay - http://www.mrclay.org/, https://twitter.com/mrclay_org
+
+Cash Costello - cash@elgg.org, http://cashcostello.com/
+
+Pete Harris - http://www.peteharris.co.uk/
+
+Kevin Jardine - http://radagast.biz/
+
+Jon Maul - MITRE http://www.mitre.org/
+
+Marcus Povey - http://marcuspovey.co.uk/
+
+Brett Profitt - brett@elgg.org, http://twitter.com/brettprofitt
+
+Nathan Rackliffe - MITRE http://mitre.org/
+
+Tom Read - MITRE http://mitre.org/
+
+Justin Richer - MITRE http://mitre.org/
+
+Dave Tosh - http://twitter.com/davetosh
+
+Ben Werdmuller - http://werd.io/
+
+Nicholas Whitt - nick.whitt@gmail.com, http://twitter.com/nogoodnick
+
+Evan Winslow - evan@elgg.org

+ 14 - 0
COPYRIGHT.txt

@@ -0,0 +1,14 @@
+The follow individuals, companies, or entities have contributed significant 
+code to the Elgg project and share the copyright. (In alphabetical order.)
+
+Organizations:
+The MITRE Corportation (jricher@mitre.org)
+Curverider Ltd (info@elgg.com)
+
+Individuals:
+Steve Clay (steve@mrclay.org)
+Cash Costello (cash.costello@gmail.com)
+Brett Profitt (brett.profitt@gmail.com)
+Dave Tosh (davidgtosh@gmail.com)
+Ben Werdmuller (ben@benwerd.com)
+Evan Winslow (evan.b.winslow@gmail.com)

File diff suppressed because it is too large
+ 42438 - 0
ChangeLog


+ 16 - 0
Gruntfile.js

@@ -0,0 +1,16 @@
+module.exports = function(grunt) {
+
+  require('load-grunt-config')(grunt);
+
+  grunt.registerTask('build', [
+    'clean:docs',
+    'exec:build_docs'
+  ]);
+  grunt.registerTask('default', [
+    'clean:docs',
+    'exec:build_docs',
+    'connect:docs',
+    'open:docs',
+    'watch:docs'
+  ]);
+};

+ 1 - 0
INSTALL.txt

@@ -0,0 +1 @@
+See http://learn.elgg.org/en/stable/intro/install.html

+ 280 - 0
LICENSE.txt

@@ -0,0 +1,280 @@
+		    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS

File diff suppressed because it is too large
+ 25 - 2
README.md


+ 1 - 0
UPGRADE.txt

@@ -0,0 +1 @@
+See http://learn.elgg.org/en/stable/admin/upgrading.html

+ 9 - 0
_graphics/SPRITES_LICENSE.TXT

@@ -0,0 +1,9 @@
+The Sprites are copyright © GentleFace http://www.gentleface.com/
+
+They are licensed under Creative Commons
+Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-NC-ND 3.0) with special
+permission to distribute and use with the Elgg open source framework. For uses
+outside of Elgg, please see the license and/or contact the author at
+design@gentleface.com
+
+http://creativecommons.org/licenses/by-nc-nd/3.0/

BIN
_graphics/admin_sprites.png


BIN
_graphics/ajax_loader.gif


BIN
_graphics/ajax_loader_bw.gif


BIN
_graphics/button_background.gif


BIN
_graphics/button_graduation.png


BIN
_graphics/elgg_logo.png


BIN
_graphics/elgg_sprites.png


BIN
_graphics/elgg_toolbar_logo.gif


BIN
_graphics/favicon-128.png


BIN
_graphics/favicon-16.png


BIN
_graphics/favicon-32.png


BIN
_graphics/favicon-64.png


BIN
_graphics/favicon.ico


+ 84 - 0
_graphics/favicon.svg

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+	<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+	<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+	<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+	<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+]>
+<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+	 x="0px" y="0px" width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+	<g>
+		<g>
+			<g>
+				<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M248.088,467.688c-57.687,0-113.955-24.633-154.377-67.582
+					C53.083,356.938,32.68,300.67,36.259,241.665c2.301-37.963,14.747-74.502,35.993-105.667
+					c19.855-29.125,46.819-52.99,77.976-69.016c22.231-11.421,48.757-18.809,76.717-21.368c3.902-0.361,16.521-1.3,27.749-1.3
+					c3.479,0,6.599,0.091,9.276,0.27c60.055,4.029,115.646,35.096,152.522,85.234c0.961,1.302,2.054,2.739,3.219,4.272
+					c10.719,14.106,26.916,35.423,23.116,56.083c-3.096,16.971-25.462,28.547-52.178,40.861c-4.026,1.856-7.504,3.459-9.597,4.575
+					c-24.723,13.185-48.05,25.249-70.609,36.915c-24.788,12.82-50.422,26.076-77.805,40.773c-1.52,0.816-3.049,1.686-4.593,2.563
+					c-8.668,4.918-19.455,11.041-33.043,11.041c-0.798,0-1.602-0.021-2.415-0.064c-13.265-0.682-25.19-6.744-33.55-17.072
+					c-8.611-10.639-12.279-24.682-10.063-38.531c3.608-22.567,22.705-32.376,38.05-40.258c1.644-0.844,3.285-1.687,4.902-2.542
+					c18.365-9.688,35.179-18.399,51.438-26.823c18.978-9.832,38.601-19.999,61.11-31.933c0.625-0.33,1.296-0.677,2.014-1.048
+					c1.553-0.803,4.665-2.413,7.24-3.98c-2.728-2.202-7.988-5.527-18.135-10.198l-0.383-0.176
+					c-14.701-6.788-30.088-10.228-45.742-10.228c-44.755,0-81.777,27.807-97.235,53.643c-16.558,27.659-19.835,68.216-7.97,98.632
+					c13.376,34.262,47.19,70.877,101.975,70.877c6.7,0,13.645-0.564,20.645-1.68c53.468-8.523,75.782-49.512,81.349-61.871
+					c2.694-5.963,4.704-12.502,6.647-18.824c6.04-19.648,13.557-44.099,45.003-47.897c2.067-0.251,4.17-0.379,6.238-0.379
+					c24.451,0,45.815,17.899,49.693,41.636c2.879,17.314-4.756,39.166-10.75,54.094c-20.08,50.014-59.889,92.941-106.487,114.828
+					C309.538,460.76,279.091,467.688,248.088,467.688z"/>
+				<path fill="#4D4C4D" d="M254.694,57.954c2.965,0,5.824,0.069,8.366,0.239c61.64,4.136,111.62,37.797,142.444,79.706
+					c8.814,11.945,26.968,33.167,23.907,49.805c-2.613,14.329-42.825,29.493-54.778,35.869
+					c-51.862,27.66-96.09,49.607-148.445,77.705c-9.498,5.104-19.149,11.982-31.186,11.982c-0.557,0-1.119-0.016-1.687-0.045
+					c-20.177-1.035-34.107-19.604-30.872-39.828c2.821-17.644,20.384-24.712,35.86-32.896
+					c39.605-20.895,70.596-36.514,112.561-58.763c5.929-3.131,18.408-8.973,18.935-14.95c1.004-11.315-20.751-21.149-28.88-24.895
+					c-17.335-8.004-34.739-11.478-51.45-11.479c-47.695-0.003-89.796,28.284-108.94,60.28c-17.523,29.27-23.03,74.558-8.972,110.593
+					c15.82,40.523,55.435,79.561,114.683,79.561c7.303,0,14.896-0.592,22.789-1.848c48.675-7.762,78.573-40.721,91.643-69.744
+					c11.618-25.707,10.169-55.073,40.849-58.778c1.56-0.189,3.095-0.281,4.603-0.281c19.077,0,33.69,14.644,36.231,30.196
+					c2.343,14.088-4.846,34.107-9.946,46.809c-18.87,47.002-56.196,87.166-99.628,107.564
+					c-28.155,13.242-56.873,19.291-84.691,19.291c-109.629,0-205.351-93.912-198.213-211.556
+					c4.542-74.94,49.655-134.093,106.592-163.379c19.731-10.137,44.729-17.444,71.721-19.915
+					C231.701,58.873,243.904,57.954,254.694,57.954 M254.699,30.672v27.282l-0.001-27.282c-14.155,0-28.874,1.346-29.021,1.359
+					C196.018,34.747,167.766,42.636,144,54.845c-33.184,17.069-61.888,42.472-83.019,73.469
+					c-22.631,33.197-35.888,72.107-38.338,112.526c-1.941,31.992,2.71,63.232,13.825,92.845
+					c10.563,28.145,26.479,53.637,47.309,75.768c42.989,45.678,102.878,71.875,164.311,71.875c33.025,0,65.426-7.363,96.302-21.885
+					c49.629-23.311,92.002-68.951,113.335-122.088c7.156-17.82,14.934-40.898,11.552-61.383
+					c-2.299-14.051-9.683-27.184-20.793-36.982c-5.981-5.274-12.812-9.344-20.125-12.07c10.93-6.844,24.851-17.65,27.892-34.321
+					c4.882-26.543-13.508-50.746-25.678-66.762c-1.143-1.503-2.222-2.924-3.116-4.136c-39.237-53.348-98.501-86.429-162.57-90.728
+					C261.902,30.773,258.477,30.672,254.699,30.672L254.699,30.672z M152.446,237.351c1.995-11.907,5.862-23.251,11.49-32.653
+					c13.55-22.647,46.093-47.015,85.531-47.012c12.026,0,23.893,2.335,35.346,6.948c-17.08,8.987-32.607,17.032-47.724,24.863
+					c-16.282,8.436-33.118,17.158-51.515,26.864c-1.545,0.817-3.117,1.625-4.782,2.479
+					C172.273,223.217,161.458,228.771,152.446,237.351L152.446,237.351z M197.756,340.477c15.838-0.73,28.006-7.637,37.022-12.754
+					c1.534-0.871,2.983-1.693,4.321-2.412c27.281-14.643,52.867-27.873,77.61-40.67c9.407-4.865,18.95-9.801,28.672-14.857
+					c-1.281,3.686-2.416,7.377-3.539,11.029c-1.903,6.191-3.701,12.039-6.032,17.199c-4.872,10.818-24.35,46.586-71.078,54.037
+					c-6.283,1-12.509,1.508-18.493,1.508C227.196,353.557,211.045,348.482,197.756,340.477L197.756,340.477z"/>
+			</g>
+			<g>
+				<path fill-rule="evenodd" clip-rule="evenodd" fill="#6ECEEC" d="M429.157,462.092c-6.948,0-13.942-1.311-20.79-3.893
+					c-21.58-8.117-34.464-30.52-32.052-55.746c2.367-24.758,19.123-43.354,42.688-47.375c3.9-0.664,7.768-1.002,11.498-1.002
+					c25.78,0,46.068,16.029,51.688,40.836c3.748,16.539-0.119,33.557-10.608,46.689C461.18,454.623,445.717,462.092,429.157,462.092
+					z"/>
+				<path fill="#4D4C4D" d="M430.501,363.17c23.395,0,38.622,15.225,42.818,33.75c6.606,29.156-15.398,56.078-44.162,56.078
+					c-5.655,0-11.567-1.041-17.58-3.309c-37.63-14.15-35.493-78.063,8.956-85.648C424,363.451,427.327,363.17,430.501,363.17
+					 M430.504,344.982v18.188V344.982c-4.245,0-8.626,0.381-13.023,1.129c-27.739,4.734-47.448,26.51-50.218,55.477
+					c-1.257,13.143,1.316,26.576,7.246,37.824c6.782,12.867,17.386,22.307,30.666,27.301c7.86,2.965,15.935,4.473,23.982,4.473
+					c19.34,0,37.393-8.715,49.528-23.908c12.225-15.305,16.734-35.125,12.372-54.377c-3.006-13.268-10.187-25.236-20.219-33.701
+					C459.818,349.898,445.87,344.982,430.504,344.982L430.504,344.982z"/>
+			</g>
+		</g>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>

BIN
_graphics/friendspicker.png


BIN
_graphics/header_shadow.png


BIN
_graphics/icons/default/large.png


BIN
_graphics/icons/default/medium.png


BIN
_graphics/icons/default/small.png


BIN
_graphics/icons/default/tiny.png


BIN
_graphics/icons/default/topbar.png


BIN
_graphics/icons/user/defaultlarge.gif


BIN
_graphics/icons/user/defaultmaster.gif


BIN
_graphics/icons/user/defaultmedium.gif


BIN
_graphics/icons/user/defaultsmall.gif


BIN
_graphics/icons/user/defaulttiny.gif


BIN
_graphics/icons/user/defaulttopbar.gif


BIN
_graphics/powered_by_elgg_badge_drk_bckgnd.gif


BIN
_graphics/powered_by_elgg_badge_light_bckgnd.gif


BIN
_graphics/sidebar_background.gif


BIN
_graphics/spacer.gif


BIN
_graphics/toptoolbar_background.gif


BIN
_graphics/two_sidebar_background.gif


BIN
_graphics/walled_garden/one_column_bottom.png


BIN
_graphics/walled_garden/one_column_middle.png


BIN
_graphics/walled_garden/one_column_top.png


BIN
_graphics/walled_garden/two_column_bottom.png


BIN
_graphics/walled_garden/two_column_middle.png


BIN
_graphics/walled_garden/two_column_top.png


+ 13 - 0
actions/admin/delete_admin_notice.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Removes an admin notice.
+ */
+
+$guid = get_input('guid');
+$notice = get_entity($guid);
+
+if (!(elgg_instanceof($notice, 'object', 'admin_notice') && $notice->delete())) {
+	register_error(elgg_echo("admin:notices:could_not_delete"));
+}
+
+forward(REFERER);

+ 34 - 0
actions/admin/menu/save.php

@@ -0,0 +1,34 @@
+<?php
+/**
+ * Save menu items.
+ *
+ * @package Elgg
+ * @subpackage Core
+ */
+
+// featured menu items
+$featured_names = get_input('featured_menu_names', array());
+$featured_names = array_unique($featured_names);
+if (in_array(' ', $featured_names)) {
+	unset($featured_names[array_search(' ', $featured_names)]);
+}
+elgg_save_config('site_featured_menu_names', $featured_names);
+
+// custom menu items
+$custom_menu_titles = get_input('custom_menu_titles', array());
+$custom_menu_urls = get_input('custom_menu_urls', array());
+$num_menu_items = count($custom_menu_titles);
+$custom_menu_items = array();
+for ($i = 0; $i < $num_menu_items; $i++) {
+	if (trim($custom_menu_urls[$i]) && trim($custom_menu_titles[$i])) {
+		$url = $custom_menu_urls[$i];
+		$title = $custom_menu_titles[$i];
+		$custom_menu_items[$title] = $url;
+	}
+}
+elgg_save_config('site_custom_menu_items', $custom_menu_items);
+
+
+system_message(elgg_echo('admin:menu_items:saved'));
+
+forward(REFERER);

+ 67 - 0
actions/admin/plugins/activate.php

@@ -0,0 +1,67 @@
+<?php
+/**
+ * Activate a plugin or plugins.
+ *
+ * Plugins to be activated are passed via $_REQUEST['plugin_guids'] as GUIDs.
+ * After activating the plugin(s), the views cache and simplecache are invalidated.
+ *
+ * @uses mixed $_GET['plugin_guids'] The GUIDs of the plugin to activate. Can be an array.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.Plugins
+ */
+
+$plugin_guids = get_input('plugin_guids');
+
+if (!is_array($plugin_guids)) {
+	$plugin_guids = array($plugin_guids);
+}
+
+$activated_guids = array();
+foreach ($plugin_guids as $guid) {
+	$plugin = get_entity($guid);
+
+	if (!($plugin instanceof ElggPlugin)) {
+		register_error(elgg_echo('admin:plugins:activate:no', array($guid)));
+		continue;
+	}
+
+	if ($plugin->activate()) {
+		$activated_guids[] = $guid;
+		$ids = array(
+			'cannot_start' . $plugin->getID(),
+			'invalid_and_deactivated_' . $plugin->getID()
+		);
+
+		foreach ($ids as $id) {
+			elgg_delete_admin_notice($id);
+		}
+
+	} else {
+		$msg = $plugin->getError();
+		$string = ($msg) ? 'admin:plugins:activate:no_with_msg' : 'admin:plugins:activate:no';
+		register_error(elgg_echo($string, array($plugin->getFriendlyName(), $plugin->getError())));
+	}
+}
+
+// don't regenerate the simplecache because the plugin won't be
+// loaded until next run.  Just invalidate and let it regenerate as needed
+elgg_flush_caches();
+
+if (count($activated_guids) === 1) {
+	$url = 'admin/plugins';
+	$query = (string)parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY);
+	if ($query) {
+		$url .= "?$query";
+	}
+	$plugin = get_entity($plugin_guids[0]);
+	$id = $css_id = preg_replace('/[^a-z0-9-]/i', '-', $plugin->getID());
+	forward("$url#$id");
+} else {
+	// forward to top of page with a failure so remove any #foo
+	$url = $_SERVER['HTTP_REFERER'];
+	if (strpos($url, '#')) {
+		$url = substr(0, strpos($url, '#'));
+	}
+	forward($url);
+}

+ 59 - 0
actions/admin/plugins/activate_all.php

@@ -0,0 +1,59 @@
+<?php
+/**
+ * Activates all specified installed and inactive plugins.
+ *
+ * All specified plugins in the mod/ directory that aren't active are activated and the views
+ * cache and simplecache are invalidated.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.Plugins
+ */
+
+$guids = get_input('guids');
+$guids = explode(',', $guids);
+
+$plugins = array();
+foreach ($guids as $guid) {
+	$plugin = get_entity($guid);
+	if (!$plugin->isActive()) {
+		$plugins[$plugin->getId()] = $plugin;
+	}
+}
+
+do {
+	$additional_plugins_activated = false;
+	foreach ($plugins as $key => $plugin) {
+		if ($plugin->activate()) {
+
+			$ids = array(
+				'cannot_start' . $plugin->getID(),
+				'invalid_and_deactivated_' . $plugin->getID()
+			);
+
+			foreach ($ids as $id) {
+				elgg_delete_admin_notice($id);
+			}
+
+			$additional_plugins_activated = true;
+			unset($plugins[$key]);
+		}
+	}
+	if (!$additional_plugins_activated) {
+		// no updates in this pass, break the loop
+		break;
+	}
+} while (count($plugins) > 0);
+
+if (count($plugins) > 0) {
+	foreach ($plugins as $key => $plugin) {
+		$msg = $plugin->getError();
+		$string = ($msg) ? 'admin:plugins:activate:no_with_msg' : 'admin:plugins:activate:no';
+		register_error(elgg_echo($string, array($plugin->getFriendlyName(), $plugin->getError())));
+	}
+}
+
+// don't regenerate the simplecache because the plugin won't be
+// loaded until next run.  Just invalidate and let it regnerate as needed
+elgg_flush_caches();
+
+forward(REFERER);

+ 52 - 0
actions/admin/plugins/deactivate.php

@@ -0,0 +1,52 @@
+<?php
+/**
+ * Deactivate a plugin or plugins.
+ *
+ * Plugins to be deactivated are passed via $_REQUEST['plugin_guids'] as GUIDs.
+ * After deactivating the plugin(s), the views cache and simplecache are invalidated.
+ *
+ * @uses mixed $_GET['plugin_guids'] The GUIDs of the plugin to deactivate. Can be an array.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.Plugins
+ */
+
+$plugin_guids = get_input('plugin_guids');
+
+if (!is_array($plugin_guids)) {
+	$plugin_guids = array($plugin_guids);
+}
+
+foreach ($plugin_guids as $guid) {
+	$plugin = get_entity($guid);
+
+	if (!($plugin instanceof ElggPlugin)) {
+		register_error(elgg_echo('admin:plugins:deactivate:no', array($guid)));
+		continue;
+	}
+
+	if ($plugin->deactivate()) {
+		//system_message(elgg_echo('admin:plugins:deactivate:yes', array($plugin->getManifest()->getName())));
+	} else {
+		$msg = $plugin->getError();
+		$string = ($msg) ? 'admin:plugins:deactivate:no_with_msg' : 'admin:plugins:deactivate:no';
+		register_error(elgg_echo($string, array($plugin->getFriendlyName(), $plugin->getError())));
+	}
+}
+
+// don't regenerate the simplecache because the plugin won't be
+// loaded until next run.  Just invalidate and let it regnerate as needed
+elgg_flush_caches();
+
+if (count($plugin_guids) == 1) {
+	$url = 'admin/plugins';
+	$query = (string)parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY);
+	if ($query) {
+		$url .= "?$query";
+	}
+	$plugin = get_entity($plugin_guids[0]);
+	$id = preg_replace('/[^a-z0-9-]/i', '-', $plugin->getID());
+	forward("$url#$id");
+} else {
+	forward(REFERER);
+}

+ 32 - 0
actions/admin/plugins/deactivate_all.php

@@ -0,0 +1,32 @@
+<?php
+/**
+ * Disable all specified installed plugins.
+ *
+ * Specified plugins in the mod/ directory are disabled and the views cache and simplecache
+ * are reset.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.Plugins
+ */
+
+$guids = get_input('guids');
+$guids = explode(',', $guids);
+
+foreach ($guids as $guid) {
+	$plugin = get_entity($guid);
+	if ($plugin->isActive()) {
+		if ($plugin->deactivate()) {
+			//system_message(elgg_echo('admin:plugins:activate:yes', array($plugin->getManifest()->getName())));
+		} else {
+			$msg = $plugin->getError();
+			$string = ($msg) ? 'admin:plugins:deactivate:no_with_msg' : 'admin:plugins:deactivate:no';
+			register_error(elgg_echo($string, array($plugin->getFriendlyName(), $plugin->getError())));
+		}
+	}
+}
+
+// don't regenerate the simplecache because the plugin won't be
+// loaded until next run.  Just invalidate and let it regnerate as needed
+elgg_flush_caches();
+
+forward(REFERER);

+ 38 - 0
actions/admin/plugins/set_priority.php

@@ -0,0 +1,38 @@
+<?php
+/**
+ * Changes the load priority of a plugin.
+ *
+ * Plugin priority affects view, action, and page handler
+ * overriding as well as the order of view extensions.  Plugins with higher
+ * priority are loaded after and override plugins with lower priorities.
+ *
+ * NOTE: When viewing the plugin admin page, plugins LOWER on the page
+ * have HIGHER priority and will override views, etc from plugins above them.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.Plugins
+ */
+
+$plugin_guid = get_input('plugin_guid');
+$priority = get_input('priority');
+
+$plugin = get_entity($plugin_guid);
+
+if (!($plugin instanceof ElggPlugin)) {
+	register_error(elgg_echo('admin:plugins:set_priority:no', array($plugin_guid)));
+	forward(REFERER);
+}
+
+if ($plugin->setPriority($priority)) {
+	//system_message(elgg_echo('admin:plugins:set_priority:yes', array($plugin->getManifest()->getName())));
+} else {
+	$msg = $plugin->getError();
+	$string = ($msg) ? 'admin:plugins:set_priority:no_with_msg' : 'admin:plugins:set_priority:no';
+	register_error(elgg_echo($string, array($plugin->getFriendlyName(), $plugin->getError())));
+}
+
+// don't regenerate the simplecache because the plugin won't be
+// loaded until next run.  Just invalidate and let it regnerate as needed
+elgg_flush_caches();
+
+forward(REFERER);

+ 10 - 0
actions/admin/site/flush_cache.php

@@ -0,0 +1,10 @@
+<?php
+/**
+ * Flush all the caches
+ */
+
+elgg_flush_caches();
+_elgg_services()->autoloadManager->deleteCache();
+
+system_message(elgg_echo('admin:cache:flushed'));
+forward(REFERER);

+ 19 - 0
actions/admin/site/set_maintenance_mode.php

@@ -0,0 +1,19 @@
+<?php
+/**
+ * Configure site maintenance mode
+ */
+
+$mode = (int)get_input('mode');
+$message = get_input('message');
+
+$site = elgg_get_site_entity();
+
+$result = elgg_save_config('elgg_maintenance_mode', $mode, null);
+
+$result = $result && $site->setPrivateSetting('elgg_maintenance_message', $message);
+
+if ($result) {
+	system_message(elgg_echo('admin:maintenance_mode:saved'));
+} else {
+	register_error(elgg_echo('save:fail'));
+}

+ 14 - 0
actions/admin/site/set_robots.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * Set robots.txt action
+ */
+
+$content = get_input('text');
+
+$site = elgg_get_site_entity();
+
+if ($site->setPrivateSetting('robots.txt', $content)) {
+	system_message(elgg_echo('save:success'));
+} else {
+	register_error(elgg_echo('save:fail'));
+}

+ 12 - 0
actions/admin/site/unlock_upgrade.php

@@ -0,0 +1,12 @@
+<?php
+/**
+ * Unlocks the upgrade script 
+ */
+
+$upgrader = new Elgg\UpgradeService();
+
+if ($upgrader->isUpgradeLocked()) {
+	$upgrader->releaseUpgradeMutex();
+}
+system_message(elgg_echo('upgrade:unlock:success'));
+forward(REFERER);

+ 103 - 0
actions/admin/site/update_advanced.php

@@ -0,0 +1,103 @@
+<?php
+/**
+ * Updates the advanced settings for the primary site object.
+ *
+ * Options are saved among metadata on the site object, entries
+ * in the datalist table, and entries in the config table.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.Site
+ */
+
+$site = elgg_get_site_entity();
+if (!$site) {
+	throw new InstallationException("The system is missing an ElggSite entity!");
+}
+if (!($site instanceof ElggSite)) {
+	throw new InstallationException("Passing a non-ElggSite to an ElggSite constructor!");
+}
+
+$site->url = rtrim(get_input('wwwroot', '', false), '/') . '/';
+
+datalist_set('path', sanitise_filepath(get_input('path', '', false)));
+$dataroot = sanitise_filepath(get_input('dataroot', '', false));
+
+// check for relative paths
+if (stripos(PHP_OS, 'win') === 0) {
+	if (strpos($dataroot, ':') !== 1) {
+		$msg = elgg_echo('admin:configuration:dataroot:relative_path', array($dataroot));
+		register_error($msg);
+		forward(REFERER);
+	}
+} else {
+	if (strpos($dataroot, '/') !== 0) {
+		$msg = elgg_echo('admin:configuration:dataroot:relative_path', array($dataroot));
+		register_error($msg);
+		forward(REFERER);
+	}
+}
+
+datalist_set('dataroot', $dataroot);
+
+if ('on' === get_input('simplecache_enabled')) {
+	elgg_enable_simplecache();
+} else {
+	elgg_disable_simplecache();
+}
+
+set_config('simplecache_minify_js', 'on' === get_input('simplecache_minify_js'), $site->getGUID());
+set_config('simplecache_minify_css', 'on' === get_input('simplecache_minify_css'), $site->getGUID());
+
+if ('on' === get_input('system_cache_enabled')) {
+	elgg_enable_system_cache();
+} else {
+	elgg_disable_system_cache();
+}
+
+set_config('default_access', get_input('default_access', ACCESS_PRIVATE), $site->getGUID());
+
+$user_default_access = ('on' === get_input('allow_user_default_access'));
+set_config('allow_user_default_access', $user_default_access, $site->getGUID());
+
+$debug = get_input('debug');
+if ($debug) {
+	set_config('debug', $debug, $site->getGUID());
+} else {
+	unset_config('debug', $site->getGUID());
+}
+
+// allow new user registration?
+$allow_registration = ('on' === get_input('allow_registration', false));
+set_config('allow_registration', $allow_registration, $site->getGUID());
+
+// setup walled garden
+$walled_garden = ('on' === get_input('walled_garden', false));
+set_config('walled_garden', $walled_garden, $site->getGUID());
+
+if ('on' === get_input('https_login')) {
+	set_config('https_login', 1, $site->getGUID());
+} else {
+	unset_config('https_login', $site->getGUID());
+}
+
+$regenerate_site_secret = get_input('regenerate_site_secret', false);
+if ($regenerate_site_secret) {
+	// if you cancel this even you should present a message to the user
+	if (elgg_trigger_before_event('regenerate_site_secret', 'system')) {
+		init_site_secret();
+		elgg_reset_system_cache();
+		elgg_trigger_after_event('regenerate_site_secret', 'system');
+
+		system_message(elgg_echo('admin:site:secret_regenerated'));
+
+		elgg_delete_admin_notice('weak_site_key');
+	}
+}
+
+if ($site->save()) {
+	system_message(elgg_echo("admin:configuration:success"));
+} else {
+	register_error(elgg_echo("admin:configuration:fail"));
+}
+
+forward(REFERER);

+ 37 - 0
actions/admin/site/update_basic.php

@@ -0,0 +1,37 @@
+<?php
+/**
+ * Updates the basic settings for the primary site object.
+ *
+ * Basic site settings are saved as metadata on the site object,
+ * with the exception of the default language, which is saved in
+ * the config table.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.Site
+ */
+
+$site = elgg_get_site_entity();
+if (!$site) {
+	throw new InstallationException("The system is missing an ElggSite entity!");
+}
+if (!($site instanceof ElggSite)) {
+	throw new InstallationException("Passing a non-ElggSite to an ElggSite constructor!");
+}
+
+$site->description = get_input('sitedescription');
+$site->name = strip_tags(get_input('sitename'));
+$site->email = get_input('siteemail');
+$site->save();
+
+set_config('language', get_input('language'), $site->guid);
+
+$default_limit = (int)get_input('default_limit');
+if ($default_limit < 1) {
+	register_error(elgg_echo('admin:configuration:default_limit'));
+	forward(REFERER);
+}
+
+set_config('default_limit', $default_limit, $site->guid);
+
+system_message(elgg_echo('admin:configuration:success'));
+forward(REFERER);

+ 167 - 0
actions/admin/upgrades/upgrade_comments.php

@@ -0,0 +1,167 @@
+<?php
+/**
+ * Convert comment annotations to entities
+ * 
+ * Run for 2 seconds per request as set by $batch_run_time_in_secs. This includes
+ * the engine loading time.
+ */
+
+// from engine/start.php
+global $START_MICROTIME;
+$batch_run_time_in_secs = 2;
+
+// if upgrade has run correctly, mark it done
+if (get_input('upgrade_completed')) {
+	// set the upgrade as completed
+	$factory = new ElggUpgrade();
+	$upgrade = $factory->getUpgradeFromPath('admin/upgrades/comments');
+	if ($upgrade instanceof ElggUpgrade) {
+		$upgrade->setCompleted();
+	}
+
+	return true;
+}
+
+// Offset is the total amount of errors so far. We skip these
+// comments to prevent them from possibly repeating the same error.
+$offset = get_input('offset', 0);
+$limit = 50;
+
+$access_status = access_get_show_hidden_status();
+access_show_hidden_entities(true);
+
+// don't want any event or plugin hook handlers from plugins to run
+$original_events = _elgg_services()->events;
+$original_hooks = _elgg_services()->hooks;
+_elgg_services()->events = new Elgg\EventsService();
+_elgg_services()->hooks = new Elgg\PluginHooksService();
+elgg_register_plugin_hook_handler('permissions_check', 'all', 'elgg_override_permissions');
+elgg_register_plugin_hook_handler('container_permissions_check', 'all', 'elgg_override_permissions');
+
+$success_count = 0;
+$error_count = 0;
+
+do {
+	$annotations_to_delete = array();
+	$container_guids = array();
+	$annotations = elgg_get_annotations(array(
+		'annotation_names' => 'generic_comment',
+		'limit' => $limit,
+		'offset' => $offset,
+		'order_by' => 'n_table.id DESC',
+	));
+
+	if (!$annotations) {
+		// no annotations left
+		break;
+	}
+
+	$db_prefix = elgg_get_config('dbprefix');
+
+	// Create a new object for each annotation
+	foreach ($annotations as $annotation) {
+		$object = new ElggComment();
+		$object->owner_guid = $annotation->owner_guid;
+		$object->container_guid = $annotation->entity_guid;
+		$object->description = $annotation->value;
+		$object->access_id = $annotation->access_id;
+		// make sure disabled comments stay disabled
+		$object->enabled = $annotation->enabled;
+		$object->time_created = $annotation->time_created;
+		$object->save(false);
+
+		$guid = $object->getGUID();
+
+		if ($guid) {
+			/**
+			 * Update the entry in river table for this comment
+			 *
+			 * - Update the view path
+			 * - Remove annotation id
+			 * - Save comment guid to the object_guid column
+			 */
+			$query = "
+				UPDATE {$db_prefix}river
+				SET view = 'river/object/comment/create',
+					type = 'object',
+					subtype = 'comment',
+					annotation_id = 0,
+					object_guid = $guid,
+					target_guid = $object->container_guid
+				WHERE action_type = 'comment'
+				  AND annotation_id = $annotation->id
+			";
+
+			if (!update_data($query)) {
+				register_error(elgg_echo('upgrade:comments:river_update_failed', array($annotation->id)));
+				$error_count++;
+				continue;
+			}
+
+			// set the time_updated and last_action for this comment
+			// to the original time_created
+			$fix_ts_query = "
+				UPDATE {$db_prefix}entities
+				SET time_updated = time_created,
+					last_action = time_created
+				WHERE guid = $guid
+			";
+
+			if (update_data($fix_ts_query)) {
+				// It's now safe to delete the annotation
+				$annotations_to_delete[] = $annotation->id;
+				$container_guids[] = $object->container_guid;
+				$success_count++;
+			} else {
+				register_error(elgg_echo('upgrade:comments:timestamp_update_fail', array($annotation->id)));
+				$error_count++;
+			}
+		} else {
+			register_error(elgg_echo('upgrade:comments:create_failed', array($annotation->id)));
+			$error_count++;
+		}
+	}
+
+	if ($annotations_to_delete) {
+		$annotation_ids = implode(",", $annotations_to_delete);
+		$delete_query = "DELETE FROM {$db_prefix}annotations WHERE id IN ($annotation_ids)";
+		delete_data($delete_query);
+	}
+
+	// update the last action on containers to be the max of all its comments
+	// or its own last action
+	$comment_subtype_id = get_subtype_id('object', 'comment');
+
+	foreach (array_unique($container_guids) as $guid) {
+		// can't use a subquery in an update clause without hard to read tricks.
+		$max = get_data_row("SELECT MAX(time_updated) as max_time_updated
+					FROM {$db_prefix}entities e
+					WHERE e.container_guid = $guid
+					AND e.subtype = $comment_subtype_id");
+
+		$query = "
+		UPDATE {$db_prefix}entities
+			SET last_action = '$max->max_time_updated'
+			WHERE guid = $guid
+			AND last_action < '$max->max_time_updated'
+		";
+
+		update_data($query);
+	}
+
+} while ((microtime(true) - $START_MICROTIME) < $batch_run_time_in_secs);
+
+access_show_hidden_entities($access_status);
+
+// replace events and hooks
+_elgg_services()->events = $original_events;
+_elgg_services()->hooks = $original_hooks;
+
+// remove the admin notice 
+elgg_delete_admin_notice('comment_upgrade_needed');
+
+// Give some feedback for the UI
+echo json_encode(array(
+	'numSuccess' => $success_count,
+	'numErrors' => $error_count,
+));

+ 79 - 0
actions/admin/upgrades/upgrade_comments_access.php

@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * Convert comment annotations to entities
+ * 
+ * Run for 2 seconds per request as set by $batch_run_time_in_secs. This includes
+ * the engine loading time.
+ */
+// from engine/start.php
+global $START_MICROTIME;
+$batch_run_time_in_secs = 2;
+
+// if upgrade has run correctly, mark it done
+if (get_input('upgrade_completed')) {
+	// set the upgrade as completed
+	$factory = new ElggUpgrade();
+	$upgrade = $factory->getUpgradeFromPath('admin/upgrades/commentaccess');
+	if ($upgrade instanceof ElggUpgrade) {
+		$upgrade->setCompleted();
+	}
+
+	return true;
+}
+
+// Offset is the total amount of errors so far. We skip these
+// comments to prevent them from possibly repeating the same error.
+$offset = get_input('offset', 0);
+$limit = 50;
+
+$access_status = access_get_show_hidden_status();
+access_show_hidden_entities(true);
+
+$success_count = 0;
+$error_count = 0;
+
+do {
+	$dbprefix = elgg_get_config('dbprefix');
+	$options = array(
+		'type' => 'object',
+		'subtype' => 'comment',
+		'joins' => array(
+			"JOIN {$dbprefix}entities e2 ON e.container_guid = e2.guid"
+		),
+		'wheres' => array(
+			"e.access_id != e2.access_id"
+		),
+		'offset' => $offset,
+		'limit' => $limit,
+		'preload_containers' => true
+	);
+			
+	$comments = elgg_get_entities($options);
+	
+	foreach ($comments as $comment) {
+		$container = $comment->getContainerEntity();
+		
+		if (!$container) {
+			$error_count++;
+			continue;
+		}		
+		
+		$comment->access_id = $container->access_id;
+		
+		if ($comment->save()) {
+			$success_count++;
+		} else {
+			$error_count++;
+		}
+	}
+	
+} while ((microtime(true) - $START_MICROTIME) < $batch_run_time_in_secs);
+
+access_show_hidden_entities($access_status);
+
+// Give some feedback for the UI
+echo json_encode(array(
+	'numSuccess' => $success_count,
+	'numErrors' => $error_count,
+));

+ 101 - 0
actions/admin/upgrades/upgrade_datadirs.php

@@ -0,0 +1,101 @@
+<?php
+/**
+ * Move user data directories
+ * 
+ * Run for 2 seconds per request as set by $batch_run_time_in_secs. This includes
+ * the engine loading time.
+ */
+
+// Migrate also directories that belong to hidden users
+$access_status = access_get_show_hidden_status();
+access_show_hidden_entities(true);
+
+$helper = new Elgg\Upgrades\Helper2013022000(
+	elgg_get_site_entity()->guid,
+	elgg_get_config('dbprefix')
+);
+
+// from engine/start.php
+global $START_MICROTIME;
+$batch_run_time_in_secs = 2;
+
+$data_root = elgg_get_config('dataroot');
+$cleanup_years = array();
+$num_successes = 0;
+$num_errors = 0;
+$is_complete = true;
+
+_elgg_services()->db->disableQueryCache();
+
+$batch = new ElggBatch('elgg_get_entities', $helper->getBatchOptions(), null, 50, false);
+
+foreach ($batch as $user_row) {
+	if ((microtime(true) - $START_MICROTIME) > $batch_run_time_in_secs) {
+		$is_complete = false;
+		break;
+	}
+
+	$guid = $user_row->guid;
+	$from = $data_root . $helper->makeMatrix($user_row);
+	$bucket_dir = $data_root . $helper->getLowerBucketBound($guid);
+	$to = "$bucket_dir/$guid";
+
+	if (!is_dir($from)) {
+		$num_successes += 1;
+		$helper->markSuccess($guid);
+		continue;
+	}
+
+	// make sure bucket dir exists
+	if (!is_dir($bucket_dir)) {
+		// same perms as ElggDiskFilestore.
+		if (!mkdir($bucket_dir, 0700, true)) {
+			register_error("[$guid] Failed creating `$bucket_dir`");
+			$num_errors += 1;
+			$helper->markFailure($guid);
+			continue;
+		}
+	}
+
+	if (!rename($from, $to)) {
+		register_error("[$guid] Failed moving `$from` to `$to`");
+		$num_errors += 1;
+		$helper->markFailure($guid);
+	} else {
+		$num_successes += 1;
+		$helper->markSuccess($guid);
+	}
+
+	// store the year for cleanup
+	$year = date('Y', $user_row->time_created);
+	if (!in_array($year, $cleanup_years)) {
+		$cleanup_years[] = $year;
+	}
+}
+
+// remove all dirs that are empty.
+// @todo this could take some time, so we may want to lower the batch run time to compensate.
+foreach ($cleanup_years as $year) {
+	$helper->removeDirIfEmpty($data_root . $year);
+}
+
+if ($is_complete && !$helper->hasFailures()) {
+	// migration has completed, lets clean up
+	$helper->forgetSuccesses();
+
+	// set the upgrade as completed
+	$factory = new ElggUpgrade();
+	$upgrade = $factory->getUpgradeFromPath('admin/upgrades/datadirs');
+	if ($upgrade instanceof ElggUpgrade) {
+		$upgrade->setCompleted();
+	}
+}
+
+access_show_hidden_entities($access_status);
+
+_elgg_services()->db->enableQueryCache();
+
+echo json_encode(array(
+	'numSuccess' => $num_successes,
+	'numErrors' => $num_errors,
+));

+ 165 - 0
actions/admin/upgrades/upgrade_discussion_replies.php

@@ -0,0 +1,165 @@
+<?php
+/**
+ * Convert discussion replies from annotations to entities
+ *
+ * Run for 2 seconds per request as set by $batch_run_time_in_secs. This includes
+ * the engine loading time.
+ */
+
+// from engine/start.php
+global $START_MICROTIME;
+$batch_run_time_in_secs = 2;
+
+if (get_input('upgrade_completed')) {
+	// set the upgrade as completed
+	$factory = new ElggUpgrade();
+	$upgrade = $factory->getUpgradeFromPath('admin/upgrades/discussion_replies');
+	if ($upgrade instanceof ElggUpgrade) {
+		$upgrade->setCompleted();
+	}
+
+	return true;
+}
+
+// Offset is the total amount of errors so far. We skip these
+// annotations to prevent them from possibly repeating the same error.
+$offset = get_input('offset', 0);
+$limit = 50;
+
+$access_status = access_get_show_hidden_status();
+access_show_hidden_entities(true);
+
+// don't want any event or plugin hook handlers from plugins to run
+$original_events = _elgg_services()->events;
+$original_hooks = _elgg_services()->hooks;
+_elgg_services()->events = new Elgg\EventsService();
+_elgg_services()->hooks = new Elgg\PluginHooksService();
+elgg_register_plugin_hook_handler('permissions_check', 'all', 'elgg_override_permissions');
+elgg_register_plugin_hook_handler('container_permissions_check', 'all', 'elgg_override_permissions');
+
+$success_count = 0;
+$error_count = 0;
+
+do {
+	$annotations_to_delete = array();
+	$annotations = elgg_get_annotations(array(
+		'annotation_names' => 'group_topic_post',
+		'limit' => $limit,
+		'offset' => $offset,
+		'order_by' => 'n_table.id DESC',
+	));
+
+	if (!$annotations) {
+		// no annotations left
+		break;
+	}
+
+	$db_prefix = elgg_get_config('dbprefix');
+	$container_guids = array();
+
+	// Create a new object for each annotation
+	foreach ($annotations as $annotation) {
+		$object = new ElggDiscussionReply();
+		$object->owner_guid = $annotation->owner_guid;
+		$object->container_guid = $annotation->entity_guid;
+		$object->description = $annotation->value;
+		$object->access_id = $annotation->access_id;
+		// make sure disabled replies stay disabled
+		$object->enabled = $annotation->enabled;
+		$object->time_created = $annotation->time_created;
+		$object->save(false);
+
+		$container_guids[] = $object->container_guid;
+
+		$guid = $object->getGUID();
+
+		if ($guid) {
+			/**
+			 * Update the entry in river table for this reply
+			 *
+			 * - Update the view path
+			 * - Remove annotation id
+			 * - Save reply guid to the object_guid column
+			 */
+			$query = "
+				UPDATE {$db_prefix}river
+				SET view = 'river/object/discussion_reply/create',
+					type = 'object',
+					subtype = 'discussion_reply',
+					action_type = 'reply',
+					annotation_id = 0,
+					object_guid = $guid,
+					target_guid = $object->container_guid
+				WHERE action_type = 'reply'
+				  AND annotation_id = $annotation->id
+			";
+
+			if (!update_data($query)) {
+				register_error(elgg_echo('upgrade:river_update_failed', array($annotation->id)));
+				$error_count++;
+			}
+
+			// set the time_updated and last_action for this reply
+			// to the original time_created
+			$fix_ts_query = "
+				UPDATE {$db_prefix}entities
+				SET time_updated = time_created,
+					last_action = time_created
+				WHERE guid = $guid
+			";
+
+			if (update_data($fix_ts_query)) {
+				// It's now safe to delete the annotation
+				$annotations_to_delete[] = $annotation->id;
+				$success_count++;
+			} else {
+				register_error(elgg_echo('upgrade:timestamp_update_failed', array($annotation->id)));
+				$error_count++;
+			}
+
+		} else {
+			register_error(elgg_echo('discussion:upgrade:replies:create_failed', array($annotation->id)));
+			$error_count++;
+		}
+	}
+
+	if ($annotations_to_delete) {
+		$annotation_ids = implode(",", $annotations_to_delete);
+		$delete_query = "DELETE FROM {$db_prefix}annotations WHERE id IN ($annotation_ids)";
+		delete_data($delete_query);
+	}
+
+	// update the last action on containers to be the max of all its replies
+	// or its own last action
+	$reply_subtype_id = get_subtype_id('object', 'discussion_reply');
+
+	foreach (array_unique($container_guids) as $guid) {
+		// can't use a subquery in an update clause without hard to read tricks.
+		$max = get_data_row("SELECT MAX(time_updated) as max_time_updated
+					FROM {$db_prefix}entities e
+					WHERE e.container_guid = $guid
+					AND e.subtype = $reply_subtype_id");
+
+		$query = "
+		UPDATE {$db_prefix}entities
+			SET last_action = '$max->max_time_updated'
+			WHERE guid = $guid
+			AND last_action < '$max->max_time_updated'
+		";
+
+		update_data($query);
+	}
+
+} while ((microtime(true) - $START_MICROTIME) < $batch_run_time_in_secs);
+
+access_show_hidden_entities($access_status);
+
+// replace events and hooks
+_elgg_services()->events = $original_events;
+_elgg_services()->hooks = $original_hooks;
+
+// Give some feedback for the UI
+echo json_encode(array(
+	'numSuccess' => $success_count,
+	'numErrors' => $error_count,
+));

+ 30 - 0
actions/admin/user/ban.php

@@ -0,0 +1,30 @@
+<?php
+/**
+ * Bans a user.
+ *
+ * User entities are banned by setting the 'banned' column
+ * to 'yes' in the users_entity table.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.User
+ */
+
+$guid = get_input('guid');
+$user = get_entity($guid);
+
+if ($guid == elgg_get_logged_in_user_guid()) {
+	register_error(elgg_echo('admin:user:self:ban:no'));
+	forward(REFERER);
+}
+
+if (($user instanceof ElggUser) && ($user->canEdit())) {
+	if ($user->ban('banned')) {
+		system_message(elgg_echo('admin:user:ban:yes'));
+	} else {
+		register_error(elgg_echo('admin:user:ban:no'));
+	}
+} else {
+	register_error(elgg_echo('admin:user:ban:no'));
+}
+
+forward(REFERER);

+ 40 - 0
actions/admin/user/delete.php

@@ -0,0 +1,40 @@
+<?php
+/**
+ * Delete a user.
+ *
+ * The user will be deleted recursively, meaning all entities
+ * owned or contained by the user will also be removed.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.User
+ */
+
+// Get the user
+$guid = get_input('guid');
+$user = get_entity($guid);
+
+if ($guid == elgg_get_logged_in_user_guid()) {
+	register_error(elgg_echo('admin:user:self:delete:no'));
+	forward(REFERER);
+}
+
+$name = $user->name;
+$username = $user->username;
+
+if (($user instanceof ElggUser) && ($user->canEdit())) {
+	if ($user->delete()) {
+		system_message(elgg_echo('admin:user:delete:yes', array($name)));
+	} else {
+		register_error(elgg_echo('admin:user:delete:no'));
+	}
+} else {
+	register_error(elgg_echo('admin:user:delete:no'));
+}
+
+// forward to user administration if on a user's page as it no longer exists
+$forward = REFERER;
+if (strpos($_SERVER['HTTP_REFERER'], $username) != FALSE) {
+	$forward = "admin/users/newest";
+}
+
+forward($forward);

+ 27 - 0
actions/admin/user/makeadmin.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * Grants admin privileges to a user.
+ *
+ * In >=1.7.1, admin is flagged by setting the admin
+ * column in the users_entity table.
+ *
+ * In <1.7.1, admin is a piece of metadata on the user object.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.User
+ */
+
+$guid = get_input('guid');
+$user = get_entity($guid);
+
+if (($user instanceof ElggUser) && ($user->canEdit())) {
+	if ($user->makeAdmin()) {
+		system_message(elgg_echo('admin:user:makeadmin:yes'));
+	} else {
+		register_error(elgg_echo('admin:user:makeadmin:no'));
+	}
+} else {
+	register_error(elgg_echo('admin:user:makeadmin:no'));
+}
+
+forward(REFERER);

+ 27 - 0
actions/admin/user/removeadmin.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * Revokes admin privileges from a user.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.User
+ */
+
+$guid = get_input('guid');
+$user = get_entity($guid);
+
+if ($guid == elgg_get_logged_in_user_guid()) {
+	register_error(elgg_echo('admin:user:self:removeadmin:no'));
+	forward(REFERER);
+}
+
+if (($user instanceof ElggUser) && ($user->canEdit())) {
+	if ($user->removeAdmin()) {
+		system_message(elgg_echo('admin:user:removeadmin:yes'));
+	} else {
+		register_error(elgg_echo('admin:user:removeadmin:no'));
+	}
+} else {
+	register_error(elgg_echo('admin:user:removeadmin:no'));
+}
+
+forward(REFERER);

+ 39 - 0
actions/admin/user/resetpassword.php

@@ -0,0 +1,39 @@
+<?php
+/**
+ * Reset a user's password.
+ *
+ * This is an admin action that generates a new salt and password
+ * for a user, then emails the password to the user's registered
+ * email address.
+ *
+ * NOTE: This is different to the "reset password" link users
+ * can use in that it does not first email the user asking if
+ * they want to have their password reset.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.User
+ */
+
+$guid = get_input('guid');
+$user = get_entity($guid);
+
+if (($user instanceof ElggUser) && ($user->canEdit())) {
+	$password = generate_random_cleartext_password();
+
+	if (force_user_password_reset($user->guid, $password)) {
+		system_message(elgg_echo('admin:user:resetpassword:yes'));
+
+		notify_user($user->guid,
+			elgg_get_site_entity()->guid,
+			elgg_echo('email:resetpassword:subject', array(), $user->language),
+			elgg_echo('email:resetpassword:body', array($user->username, $password), $user->language),
+			array(),
+			'email');
+	} else {
+		register_error(elgg_echo('admin:user:resetpassword:no'));
+	}
+} else {
+	register_error(elgg_echo('admin:user:resetpassword:no'));
+}
+
+forward(REFERER);

+ 27 - 0
actions/admin/user/unban.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * Unbans a user.
+ *
+ * @package Elgg.Core
+ * @subpackage Administration.User
+ */
+
+$access_status = access_get_show_hidden_status();
+access_show_hidden_entities(true);
+
+$guid = get_input('guid');
+$user = get_entity($guid);
+
+if (($user instanceof ElggUser) && ($user->canEdit())) {
+	if ($user->unban()) {
+		system_message(elgg_echo('admin:user:unban:yes'));
+	} else {
+		register_error(elgg_echo('admin:user:unban:no'));
+	}
+} else {
+	register_error(elgg_echo('admin:user:unban:no'));
+}
+
+access_show_hidden_entities($access_status);
+
+forward(REFERER);

+ 78 - 0
actions/avatar/crop.php

@@ -0,0 +1,78 @@
+<?php
+/**
+ * Avatar crop action
+ *
+ */
+
+$guid = get_input('guid');
+$owner = get_entity($guid);
+
+if (!$owner || !($owner instanceof ElggUser) || !$owner->canEdit()) {
+	register_error(elgg_echo('avatar:crop:fail'));
+	forward(REFERER);
+}
+
+$x1 = (int) get_input('x1', 0);
+$y1 = (int) get_input('y1', 0);
+$x2 = (int) get_input('x2', 0);
+$y2 = (int) get_input('y2', 0);
+
+$filehandler = new ElggFile();
+$filehandler->owner_guid = $owner->getGUID();
+$filehandler->setFilename("profile/" . $owner->guid . "master" . ".jpg");
+$filename = $filehandler->getFilenameOnFilestore();
+
+// ensuring the avatar image exists in the first place
+if (!file_exists($filename)) {
+	register_error(elgg_echo('avatar:crop:fail'));
+	forward(REFERER);
+}
+
+$icon_sizes = elgg_get_config('icon_sizes');
+unset($icon_sizes['master']);
+
+// get the images and save their file handlers into an array
+// so we can do clean up if one fails.
+$files = array();
+foreach ($icon_sizes as $name => $size_info) {
+	$resized = get_resized_image_from_existing_file($filename, $size_info['w'], $size_info['h'], $size_info['square'], $x1, $y1, $x2, $y2, $size_info['upscale']);
+
+	if ($resized) {
+		//@todo Make these actual entities.  See exts #348.
+		$file = new ElggFile();
+		$file->owner_guid = $guid;
+		$file->setFilename("profile/{$guid}{$name}.jpg");
+		$file->open('write');
+		$file->write($resized);
+		$file->close();
+		$files[] = $file;
+	} else {
+		// cleanup on fail
+		foreach ($files as $file) {
+			$file->delete();
+		}
+
+		register_error(elgg_echo('avatar:resize:fail'));
+		forward(REFERER);
+	}
+}
+
+$owner->icontime = time();
+
+$owner->x1 = $x1;
+$owner->x2 = $x2;
+$owner->y1 = $y1;
+$owner->y2 = $y2;
+
+system_message(elgg_echo('avatar:crop:success'));
+$view = 'river/user/default/profileiconupdate';
+elgg_delete_river(array('subject_guid' => $owner->guid, 'view' => $view));
+elgg_create_river_item(array(
+	'view' => $view,
+	'action_type' => 'update',
+	'subject_guid' => $owner->guid,
+	'object_guid' => $owner->guid,
+));
+
+
+forward(REFERER);

+ 36 - 0
actions/avatar/remove.php

@@ -0,0 +1,36 @@
+<?php
+/**
+ * Avatar remove action
+ */
+
+$user_guid = get_input('guid');
+$user = get_user($user_guid);
+
+if (!$user || !$user->canEdit()) {
+	register_error(elgg_echo('avatar:remove:fail'));
+	forward(REFERER);
+}
+
+// Delete all icons from diskspace
+$icon_sizes = elgg_get_config('icon_sizes');
+foreach ($icon_sizes as $name => $size_info) {
+	$file = new ElggFile();
+	$file->owner_guid = $user_guid;
+	$file->setFilename("profile/{$user_guid}{$name}.jpg");
+	$filepath = $file->getFilenameOnFilestore();
+	if (!$file->delete()) {
+		elgg_log("Avatar file remove failed. Remove $filepath manually, please.", 'WARNING');
+	}
+}
+
+// Remove crop coords
+unset($user->x1);
+unset($user->x2);
+unset($user->y1);
+unset($user->y2);
+
+// Remove icon
+unset($user->icontime);
+
+system_message(elgg_echo('avatar:remove:success'));
+forward(REFERER);

+ 68 - 0
actions/avatar/upload.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Avatar upload action
+ */
+
+$guid = get_input('guid');
+$owner = get_entity($guid);
+
+if (!$owner || !($owner instanceof ElggUser) || !$owner->canEdit()) {
+	register_error(elgg_echo('avatar:upload:fail'));
+	forward(REFERER);
+}
+
+$error = elgg_get_friendly_upload_error($_FILES['avatar']['error']);
+if ($error) {
+	register_error($error);
+	forward(REFERER);
+}
+
+$icon_sizes = elgg_get_config('icon_sizes');
+
+// get the images and save their file handlers into an array
+// so we can do clean up if one fails.
+$files = array();
+foreach ($icon_sizes as $name => $size_info) {
+	$resized = get_resized_image_from_uploaded_file('avatar', $size_info['w'], $size_info['h'], $size_info['square'], $size_info['upscale']);
+
+	if ($resized) {
+		//@todo Make these actual entities.  See exts #348.
+		$file = new ElggFile();
+		$file->owner_guid = $guid;
+		$file->setFilename("profile/{$guid}{$name}.jpg");
+		$file->open('write');
+		$file->write($resized);
+		$file->close();
+		$files[] = $file;
+	} else {
+		// cleanup on fail
+		foreach ($files as $file) {
+			$file->delete();
+		}
+
+		register_error(elgg_echo('avatar:resize:fail'));
+		forward(REFERER);
+	}
+}
+
+// reset crop coordinates
+$owner->x1 = 0;
+$owner->x2 = 0;
+$owner->y1 = 0;
+$owner->y2 = 0;
+
+$owner->icontime = time();
+if (elgg_trigger_event('profileiconupdate', $owner->type, $owner)) {
+	system_message(elgg_echo("avatar:upload:success"));
+
+	$view = 'river/user/default/profileiconupdate';
+	elgg_delete_river(array('subject_guid' => $owner->guid, 'view' => $view));
+	elgg_create_river_item(array(
+		'view' => $view,
+		'action_type' => 'update',
+		'subject_guid' => $owner->guid,
+		'object_guid' => $owner->guid,
+	));
+}
+
+forward(REFERER);

+ 22 - 0
actions/comment/delete.php

@@ -0,0 +1,22 @@
+<?php
+/**
+ * Delete comment entity
+ *
+ * @package Elgg.Core
+ * @subpackage Comments
+ */
+
+$comment_guid = get_input('guid');
+$comment = get_entity($comment_guid);
+
+if (elgg_instanceof($comment, 'object', 'comment') && $comment->canEdit()) {
+	if ($comment->delete()) {
+		system_message(elgg_echo('generic_comment:deleted'));
+	} else {
+		register_error(elgg_echo('generic_comment:notdeleted'));
+	}
+} else {
+	register_error(elgg_echo('generic_comment:notfound'));
+}
+
+forward(REFERER);

+ 107 - 0
actions/comment/save.php

@@ -0,0 +1,107 @@
+<?php
+/**
+ * Action for adding and editing comments
+ *
+ * @package Elgg.Core
+ * @subpackage Comments
+ */
+
+$entity_guid = (int) get_input('entity_guid', 0, false);
+$comment_guid = (int) get_input('comment_guid', 0, false);
+$comment_text = get_input('generic_comment');
+$is_edit_page = (bool) get_input('is_edit_page', false, false);
+
+if (empty($comment_text)) {
+	register_error(elgg_echo("generic_comment:blank"));
+	forward(REFERER);
+}
+
+if ($comment_guid) {
+	// Edit an existing comment
+	$comment = get_entity($comment_guid);
+
+	if (!elgg_instanceof($comment, 'object', 'comment')) {
+		register_error(elgg_echo("generic_comment:notfound"));
+		forward(REFERER);
+	}
+	if (!$comment->canEdit()) {
+		register_error(elgg_echo("actionunauthorized"));
+		forward(REFERER);
+	}
+
+	$comment->description = $comment_text;
+	if ($comment->save()) {
+		system_message(elgg_echo('generic_comment:updated'));
+
+		if (elgg_is_xhr()) {
+			// @todo move to its own view object/comment/content in 1.x
+			echo elgg_view('output/longtext', array(
+				'value' => $comment->description,
+				'class' => 'elgg-inner',
+				'data-role' => 'comment-text',
+			));
+		}
+	} else {
+		register_error(elgg_echo('generic_comment:failure'));
+	}
+} else {
+	// Create a new comment on the target entity
+	$entity = get_entity($entity_guid);
+	if (!$entity) {
+		register_error(elgg_echo("generic_comment:notfound"));
+		forward(REFERER);
+	}
+
+	$user = elgg_get_logged_in_user_entity();
+
+	$comment = new ElggComment();
+	$comment->description = $comment_text;
+	$comment->owner_guid = $user->getGUID();
+	$comment->container_guid = $entity->getGUID();
+	$comment->access_id = $entity->access_id;
+	$guid = $comment->save();
+
+	if (!$guid) {
+		register_error(elgg_echo("generic_comment:failure"));
+		forward(REFERER);
+	}
+
+	// Notify if poster wasn't owner
+	if ($entity->owner_guid != $user->guid) {
+		$owner = $entity->getOwnerEntity();
+
+		notify_user($owner->guid,
+			$user->guid,
+			elgg_echo('generic_comment:email:subject', array(), $owner->language),
+			elgg_echo('generic_comment:email:body', array(
+				$entity->title,
+				$user->name,
+				$comment_text,
+				$comment->getURL(),
+				$user->name,
+				$user->getURL()
+			), $owner->language),
+			array(