Commit 905fc12a authored by Nigel McNie's avatar Nigel McNie

Merge branch '0.8_STABLE' of git+ssh://git.catalyst.net.nz/git/public/mahara into 0.8_STABLE

parents d93170d3 3cca5602
mahara (0.8.6~testing) stable; urgency=low
* Testing release
-- Nigel McNie <nigel@catalyst.net.nz> Fri, 19 Oct 2007 15:58:03 +1300
mahara (0.8.5-1) stable; urgency=low
* Bugfix release
-- Nigel McNie <nigel@catalyst.net.nz> Fri, 19 Oct 2007 15:45:28 +1300
mahara (0.8.5~testing) unstable; urgency=low
* Testing release
-- Nigel McNie <nigel@catalyst.net.nz> Sat, 8 Sep 2007 19:08:04 +1200
mahara (0.8.4-1) unstable; urgency=low
* Bugfix release
-- Nigel McNie <nigel@catalyst.net.nz> Sat, 8 Sep 2007 19:03:29 +1200
mahara (0.8.4~testing) unstable; urgency=low
* Testing release
-- Nigel McNie <nigel@catalyst.net.nz> Tue, 28 Aug 2007 16:12:37 +1200
mahara (0.8.3-1) unstable; urgency=low
* Bugfix release
-- Nigel McNie <nigel@catalyst.net.nz> Tue, 28 Aug 2007 15:59:08 +1200
mahara (0.8.3~testing) unstable; urgency=low
* Bugfix release
-- Nigel McNie <nigel@catalyst.net.nz> Mon, 27 Aug 2007 14:45:01 +1200
mahara (0.8.2-1) unstable; urgency=low
* Bugfix release
......
......@@ -38,23 +38,21 @@
<pre>
# Mahara releases (uncomment the version you want)
#deb http://debian.mahara.org/ stable mahara
#deb http://debian.mahara.org/ unstable mahara
</pre>
#deb http://debian.mahara.org/ testing mahara
#deb http://debian.mahara.org/ unstable mahara</pre>
<h3>Archive GPG Fingerprint</h3>
<pre>
pub 1024D/1D18A55D 2007-03-12
Key fingerprint = F61D 631C ECFA 1E25 5B72 FEA7 922E 1C43 1D18 A55D
uid Mahara release key &lt;debian@mahara.org&gt;
sub 2048g/909016F5 2007-03-12
</pre>
sub 2048g/909016F5 2007-03-12</pre>
<h3>Installing the Key</h3>
<pre>
gpg --keyserver subkeys.pgp.net --recv-key 1D18A55D
gpg --fingerprint 1D18A55D
gpg --armor --export 1D18A55D | sudo apt-key add -
</pre>
gpg --armor --export 1D18A55D | sudo apt-key add -</pre>
<p>
or you can just grab this key here, and pipe it into &quot;apt-key add -&quot;
</p>
......@@ -88,8 +86,7 @@ y0kK5JcEegVUr5vyRLdG7/zYsM3pwOXgUAi8I6ll3grdk1w+s1lmGpGxez5c2xFr
AAoJEJIuHEMdGKVdA+4AoIasxsJXa8iniY5gxNicl3YlLU12AJwMDtHd8wVKeY9p
w2UYSs5vCWUYOg==
=zQ/c
-----END PGP PUBLIC KEY BLOCK-----
</pre>
-----END PGP PUBLIC KEY BLOCK-----</pre>
</div>
</div></div></div></div></div>
</div>
......
......@@ -60,6 +60,11 @@ $networkingform = pieform(
'name' => 'networkingform',
'jsform' => true,
'elements' => array(
'whatis' => array(
'type' => 'html',
'title' => get_string('whatisnetworking','admin'),
'value' => get_string('whatnetworkingis','admin')
),
'wwwroot' => array(
'type' => 'html',
'title' => get_string('wwwroot','admin'),
......
......@@ -32,18 +32,18 @@ class Dispatcher {
private $method = '';
private $response = '';
private $system_methods = array('system.listMethods' => 'listMethods',
'system/listMethods' => 'listMethods',
'system.methodSignature' => 'methodSignature',
'system/methodSignature' => 'methodSignature',
'system.methodHelp' => 'methodHelp',
'system/methodHelp' => 'methodHelp',
'system.listServices' => 'listServices',
'system/listServices' => 'listServices',
private $system_methods = array('system.listMethods' => 'list_methods',
'system/listMethods' => 'list_methods',
'system.methodSignature' => 'method_signature',
'system/methodSignature' => 'method_signature',
'system.methodHelp' => 'method_help',
'system/methodHelp' => 'method_help',
'system.listServices' => 'list_services',
'system/listServices' => 'list_services',
'system.keyswap' => 'keyswap',
'system/keyswap' => 'keyswap');
private $user_methods = array(
private $services = array(
'sso_in' => array(),
'sso_out' =>array(
'auth/mnet/auth.php/user_authorise' => 'user_authorise',
......@@ -51,6 +51,38 @@ class Dispatcher {
)
);
private $methodhelp = array(
'user_authorise' => 'Given an authentication token and a useragent hash, look for a record we\'ve created that associates those values with a single user. If we find it, return that user\'s details to the remote host',
'fetch_user_image' => 'Given a username, return the default profile icon for that user.'
);
private $methodsig = array(
'user_authorise' => array(
array(
array('type' => 'array',
'description' => '$userdata Array of user info for remote host'
),
array('type' => 'string',
'description' => 'token - The unique ID provided by remotehost.'
),
array('type' => 'string',
'description' => 'useragent - User Agent string.'
)
)
),
'fetch_user_image' => array(
array(
array('type' => 'string',
'description' => 'The encoded image.'
),
array('type' => 'string',
'description' => 'username - The id of the user.'
)
)
)
);
function __construct($payload, $payload_signed, $payload_encrypted) {
$this->payload = $payload;
......@@ -94,7 +126,7 @@ class Dispatcher {
throw new XmlrpcServerException('The function does not exist', 6011);
}
foreach ($this->user_methods as $container) {
foreach ($this->services as $container) {
if (array_key_exists($this->method, $container)) {
$xmlrpcserver = xmlrpc_server_create();
$bool = xmlrpc_server_register_method($xmlrpcserver, $this->method, 'api_dummy_method');
......@@ -139,6 +171,36 @@ class Dispatcher {
$openssl = OpenSslRepo::singleton();
return $openssl->certificate;
}
function list_methods($xmlrpc_method_name, $args = null) {
$list = array();
if (empty($args)) {
foreach ($this->services as $service => $methods) {
$list = array_merge($list, $methods);
}
return $list;
} else {
return $this->services[$args[0]];
}
}
function list_services() {
$list = array();
foreach ($this->services as $service => $methods) {
$list[] = array('name' => $service, 'apiversion' => 1, 'publish' => 1, 'subscribe' => 1);
}
return $list;
}
function method_signature($xmlrpc_method_name, $methodname) {
error_log(var_export(array('A',$xmlrpc_method_name, $methodname[0]),1));
return $this->methodsig[$methodname[0]];
}
function method_help($xmlrpc_method_name, $methodname) {
error_log(var_export(array('B',$xmlrpc_method_name, $methodname[0]),1));
return $this->methodhelp[$methodname[0]];
}
}
?>
......@@ -36,6 +36,7 @@ $id = param_integer('blogpost', 0);
if ($id) {
$blogpost = new ArtefactTypeBlogPost($id);
$blogpost->check_permission();
if (!$filelist = $blogpost->get_attached_files()) {
$filelist = array();
}
......
......@@ -50,13 +50,13 @@ if ($action == 'list') {
}
else if ($action == 'delete') {
$blog = artefact_instance_from_id($id);
if ($blog instanceof ArtefactTypeBlog && $blog->get('owner') == $USER->get('id')) {
if ($blog instanceof ArtefactTypeBlog) {
$blog->check_permission();
$blog->delete();
json_reply(false, get_string('blogdeleted', 'artefact.blog'));
}
echo json_encode(array(
'error' => false,
'message' => get_string('blogdeleted', 'artefact.blog'),
));
throw new ArtefactNotFoundException(get_string('blogdoesnotexist', 'artefact.blog'));
}
?>
......@@ -37,6 +37,7 @@ $string['attachments'] = 'Attachments';
$string['blogdesc'] = 'Description';
$string['blogdescdesc'] = 'e.g., ‘A record of Jill\'s experiences and reflections’.';
$string['blogdoesnotexist'] = 'You are trying to access a blog that does not exist';
$string['blogpostdoesnotexist'] = 'You are trying to access a blog post that does not exist';
$string['blogfilesdirdescription'] = 'Files uploaded as blog post attachments';
$string['blogfilesdirname'] = 'blogfiles';
$string['blogpost'] = 'blog post';
......
......@@ -135,7 +135,6 @@ class ArtefactTypeBlog extends ArtefactType {
* @param object
*/
public function __construct($id = 0, $data = null) {
global $USER;
parent::__construct($id, $data);
if (!$data) {
......@@ -157,9 +156,6 @@ class ArtefactTypeBlog extends ArtefactType {
if (empty($this->id)) {
$this->container = 1;
}
else if ($this->owner != $USER->get('id')) {
throw new AccessDeniedException(get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
}
}
public function is_container() {
......@@ -218,6 +214,19 @@ class ArtefactTypeBlog extends ArtefactType {
parent::delete();
}
/**
* Checks that the person viewing this blog is the owner. If not, throws an
* AccessDeniedException. Used in the blog section to ensure only the
* owners of the blogs can view or change them there. Other people see
* blogs when they are placed in views.
*/
public function check_permission() {
global $USER;
if ($USER->get('id') != $this->owner) {
throw new AccessDeniedException(get_string('youarenottheownerofthisblog', 'artefact.blog'));
}
}
/**
* This function overrides the default functionality for listing children,
* using a smarty template and tablerenderer stuff.
......@@ -435,7 +444,6 @@ class ArtefactTypeBlogPost extends ArtefactType {
* @param object
*/
public function __construct($id = 0, $data = null) {
global $USER;
parent::__construct($id, $data);
if (!$data) {
......@@ -453,10 +461,6 @@ class ArtefactTypeBlogPost extends ArtefactType {
}
}
}
if ($this->id && $this->owner != $USER->get('id')) {
throw new AccessDeniedException(get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
}
}
/**
......@@ -503,6 +507,19 @@ class ArtefactTypeBlogPost extends ArtefactType {
parent::delete();
}
/**
* Checks that the person viewing this blog is the owner. If not, throws an
* AccessDeniedException. Used in the blog section to ensure only the
* owners of the blogs can view or change them there. Other people see
* blogs when they are placed in views.
*/
public function check_permission() {
global $USER;
if ($USER->get('id') != $this->owner) {
throw new AccessDeniedException(get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
}
}
public function describe_size() {
return $this->count_attachments() . ' ' . get_string('attachments', 'artefact.blog');
......
......@@ -68,6 +68,7 @@ if (!$blogpost) {
}
else {
$blogpostobj = new ArtefactTypeBlogPost($blogpost);
$blogpostobj->check_permission();
$blog = $blogpostobj->get('parent');
$title = $blogpostobj->get('title');
$description = $blogpostobj->get('description');
......
......@@ -33,6 +33,7 @@ safe_require('artefact', 'blog');
$id = param_integer('id');
$blog = new ArtefactTypeBlog($id);
$blog->check_permission();
$form = pieform(array(
'name' => 'editblog',
......
......@@ -35,10 +35,7 @@ json_headers();
$id = param_integer('id');
$blogpost = new ArtefactTypeBlogPost($id);
if ($blogpost->get('owner') != $USER->get('id')) {
json_reply('local', get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
}
$blogpost->check_permission();
$blogpost->delete();
json_reply(false, get_string('blogpostdeleted', 'artefact.blog'));
......
......@@ -36,6 +36,7 @@ safe_require('artefact', 'blog');
$id = param_integer('id');
$blog = new ArtefactTypeBlog($id);
$blog->check_permission();
// This javascript is used to generate a list of blog posts.
$js = require('index.js.php');
......
......@@ -34,10 +34,8 @@ safe_require('artefact', 'blog');
$id = param_integer('id');
$blogpost = new ArtefactTypeBlogPost($id);
$blogpost->check_permission();
if ($blogpost->get('owner') != $USER->get('id')) {
json_reply('local', get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
}
if (!$blogpost->publish()) {
json_reply('local', get_string('publishfailed', 'artefact.blog'));
}
......
......@@ -670,6 +670,7 @@ function change_password_submit(Pieform $form, $values) {
redirect();
}
// TODO: Exception is the wrong type here!
throw new Exception('Attempt by "' . $USER->get('username') . '@'
. $USER->get('institution') . 'to change their password failed');
}
......
......@@ -376,7 +376,7 @@ class LiveUser extends User {
* @return bool
*/
public function login($username, $password, $institution) {
$users = get_records_select_array('usr', 'LOWER(username) = ? AND institution = ?', array($username, $institution), 'authinstance', '*');
$users = get_records_select_array('usr', 'LOWER(username) = ? AND institution = ?', array(strtolower($username), $institution), 'authinstance', '*');
if ($users == false) {
throw new AuthUnknownUserException("\"$username\" at \"$institution\" is not known");
......
......@@ -14,7 +14,6 @@
define('INTERNAL', 1);
define('PUBLIC', 1);
define('XMLRPC', 1);
......@@ -39,25 +38,53 @@ $remotewwwroot = param_variable('idp');
$wantsurl = param_variable('wantsurl', '/');
$institution = new Institution();
$institution->findByWwwroot($remotewwwroot);
try {
$institution->findByWwwroot($remotewwwroot);
} catch (ParamOutOfRangeException $e) {
throw new ParameterException(get_string('errnoxmlrcpwwwroot','auth'). htmlentities($remotewwwroot, ENT_QUOTES, 'UTF-8'));
}
$instances = auth_get_auth_instances_for_wwwroot($remotewwwroot);
if (empty($instances)) {
throw new ParameterException(get_string('errnoauthinstances','auth'). htmlentities($remotewwwroot, ENT_QUOTES, 'UTF-8'));
}
$rpcconfigured = false;
$res = false;
foreach($instances as $instance) {
if ($instance->authname == 'xmlrpc') {
$rpcconfigured = true;
try {
$auth = new AuthXmlrpc($instance->id);
$res = $auth->request_user_authorise($token, $remotewwwroot);
} catch (Exception $e) {
} catch (AccessDeniedException $e) {
continue;
// we don't care
// we don't care - a future plugin might accept the user
}
if ($res instanceof User) {
catch (Exception $e) {
log_info($e);
continue;
}
if ($res == true) {
break;
}
}
}
// confirm the MNET session
// redirect
redirect(get_config('wwwroot') . $wantsurl);
if ($res == true) {
// Everything's ok - we have an authenticated User object
// confirm the MNET session
// redirect
redirect(get_config('wwwroot') . $wantsurl);
// Redirect exits
}
if ($rpcconfigured === false) {
throw new UserNotFoundException(get_string('errnoxmlrcpinstances','auth').htmlentities($remotewwwroot, ENT_QUOTES, 'UTF-8'));
} else {
throw new UserNotFoundException(get_string('errnoxmlrcpuser','auth'));
}
?>
......@@ -148,7 +148,7 @@ class AuthXmlrpc extends Auth {
if ('1' == $this->config['updateuserinfoonlogin']) {
$update = true;
}
} catch (Exception $e) {
} catch (AuthUnknownUserException $e) {
if (!empty($this->config['weautocreateusers'])) {
$user = new User;
$create = true;
......
......@@ -134,6 +134,8 @@ $string['promiscuousmodedisabled'] = 'Auto-register has been disabled. ';
$string['promiscuousmodeenabled'] = 'Auto-register has been enabled. ';
$string['promiscuousmodedescription'] = 'Create an institution record for any host that connects to you, and allow its users to log on to Mahara';
$string['wwwroot'] = 'WWW Root';
$string['whatisnetworking'] = 'What is Networking?';
$string['whatnetworkingis'] = 'Mahara\'s networking features allow it to communicate with Mahara or Moodle sites running on the same or another machine. If networking is enabled, you can use it to configure single-sign-on for users who log in at either Moodle or Mahara.';
// Admin menu editor
//$string['menueditor'] = 'Menu editor';
......
......@@ -54,4 +54,9 @@ $string['wessoout'] = 'We SSO out';
$string['theyssoin'] = 'They SSO in';
$string['application'] = 'Application';
$string['cantretrievekey'] = 'An error occurred while retrieving the public key from the remote server.<br>Please ensure that the Application and WWW Root fields are correct, and that networking is enabled on the remote host.';
$string['errnoauthinstances'] = 'We don\'t seem to have any authentication plugin instances configured for the host at ';
$string['errnoxmlrcpinstances'] = 'We don\'t seem to have any XMLRPC authentication plugin instances configured for the host at ';
$string['errnoxmlrcpwwwroot'] = 'We don\'t have a record for any host at ';
$string['errnoxmlrcpuser'] = 'We were unable to authenticate you. Please ask your Mahara administrator to check Mahara\'s authentication plugin settings, and to check that either a user record exists for you on this Mahara, or that Mahara is configured to create new records for users from your Moodle.';
?>
......@@ -127,6 +127,7 @@ $string['youraccounthasbeenunsuspended'] = 'Your account has been unsuspeneded';
$string['changepassword'] = 'Change Password';
$string['changepasswordinfo'] = 'You are required to change your password before you can proceed.';
$string['confirmpassword'] = 'Confirm password';
$string['javascriptnotenabled'] = 'Your browser does not have javascript enabled for this site. Mahara requires javascript to be enabled before you can log in';
$string['cookiesnotenabled'] = 'Your browser does not have cookies enabled, or is blocking cookies from this site. Mahara requires cookies to be enabled before you can log in';
$string['institution'] = 'Institution';
$string['loggedoutok'] = 'You have been logged out successfully';
......
......@@ -88,14 +88,12 @@ function rebuild_artefact_parent_cache_dirty() {
function rebuild_artefact_parent_cache_complete() {
db_begin();
delete_records('artefact_parent_cache');
if ($artefacts = get_records_array('artefact')) {
foreach ($artefacts as $a) {
$parentids = array();
$current = $a->id;
$parentids = array_keys(artefact_get_parents_for_cache($current));
if ($artefactids = get_column('artefact', 'id')) {
foreach ($artefactids as $id) {
$parentids = array_keys(artefact_get_parents_for_cache($id));
foreach ($parentids as $p) {
$apc = new StdClass;
$apc->artefact = $a->id;
$apc->artefact = $id;
$apc->parent = $p;
$apc->dirty = 0;
insert_record('artefact_parent_cache', $apc);
......
......@@ -405,7 +405,7 @@ function xmldb_core_upgrade($oldversion=0) {
}
if ($oldversion < 2008080700) {
if ($oldversion < 2008080700 && is_postgres()) {
// Drop DEFAULT '' from many columns that should not have had them
// *nigel looks angrily at xmldb
execute_sql('
......
......@@ -336,7 +336,8 @@ function get_dataroot_image_path($path, $id, $size) {
list($width, $height) = explode('x', $size);
switch (get_mime_type($originalimage)) {
$originalmimetype = get_mime_type($originalimage);
switch ($originalmimetype) {
case 'image/jpeg':
case 'image/jpg':
$oldih = imagecreatefromjpeg($originalimage);
......@@ -384,8 +385,27 @@ function get_dataroot_image_path($path, $id, $size) {
}
$newih = imagecreatetruecolor($newx, $newy);
imagecopyresized($newih, $oldih, 0, 0, 0, 0, $newx, $newy, $oldx, $oldy);
imageinterlace($newih);
if ($originalmimetype == 'image/png' || $originalmimetype == 'image/gif') {
// Create a new destination image which is completely
// transparent and turn off alpha blending for it, so that when
// the PNG source file is copied, the alpha channel is retained.
// Thanks to http://alexle.net/archives/131
$background = imagecolorallocate($newih, 0, 0, 0);
imagecolortransparent($newih, $background);
imagealphablending($newih, false);
imagecopyresampled($newih, $oldih, 0, 0, 0, 0, $newx, $newy, $oldx, $oldy);
imagesavealpha($newih, true);
}
else {
// imagecopyresized is faster, but results in noticeably worse image quality.
// Given the images are resized only once each time they're
// made, I suggest you just leave the good quality one in place
imagecopyresampled($newih, $oldih, 0, 0, 0, 0, $newx, $newy, $oldx, $oldy);
//imagecopyresized($newih, $oldih, 0, 0, 0, 0, $newx, $newy, $oldx, $oldy);
}
$newpath = $imagepath . "/$size/" . ($id % 256);
check_dir_exists($newpath);
$newpath .= "/$id";
......
......@@ -477,12 +477,15 @@ function core_install_defaults() {
$user->lastname = 'User';
$user->email = 'root@example.org';
$user->quota = get_config_plugin('artefact', 'file', 'defaultquota');
$newid = insert_record('usr', $user);
$user->authinstance = $auth_instance->id;
if ($newid > 0 && get_config('dbtype') == 'mysql') { // gratuitous mysql workaround
if (get_config('dbtype') == 'mysql') { // gratuitous mysql workaround
$newid = insert_record('usr', $user, 'id', true);
set_field('usr', 'id', 0, 'id', $newid);
}
else {
insert_record('usr', $user);
}
// Insert the admin user
$user = new StdClass;
$user->username = 'admin';
......
......@@ -27,8 +27,8 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2007080702;
$config->release = '0.8.2';
$config->version = 2007080705;
$config->release = '0.8.6testing';
$config->minupgradefrom = 2007011600;
$config->minupgraderelease = '0.4.0 (build tag BUILD_20070122)';
$config->disablelogin = true;
......
......@@ -361,7 +361,7 @@ $elements['captcha'] = array(
'title' => get_string('captchatitle'),
'description' => get_string('captchadescription'),
'value' => '<img src="' . get_config('wwwroot') . 'captcha.php" alt="' . get_string('captchaimage') . '" style="padding: 2px 0;"><br>'
. '<input type="text" class="text required" name="captcha" style="width: 137px;" tabindex="3">',
. '<input type="text" class="text required" name="captcha" style="width: 137px;" tabindex="4">',
'rules' => array('required' => true)
);
......
......@@ -525,7 +525,7 @@ div.sidebar p {
padding: 0;
}
#column-right #login_login_institution_container select {
width: 200px;
width: 190px;
}
#column-right #login label {
color: #547c22;
......
#!/bin/bash
#
# Builds and releases Mahara to the debian repo
#
# This script can release just one version (stable|testing|unstable), or all at
# once
#
set -e
BUILDDIR="/tmp/mahara_release"
REPODIR="/tmp/mahara_repo"
ARCHLIST="i386 amd64"
DATE="`date`"