Commit 7350a50f authored by Donal McMullan's avatar Donal McMullan
parents 2784eac6 90e80da5
......@@ -3,7 +3,7 @@
DocumentRoot /var/www/mahara
CustomLog __APACHELOGDIR__/mahara.access.log full
CustomLog __APACHELOGDIR__/mahara.access.log combined
ErrorLog __APACHELOGDIR__/mahara.error.log
php_value upload_max_filesize 5M
......
......@@ -10,7 +10,7 @@ Architecture: all
Depends: ${misc:Depends}, apache, libapache-mod-php5, php5-json | libapache-mod-php5 (>= 5.2), php5-pgsql, php5-cli, php5-gd, file, cron
Conflicts: mahara-apache2
Recommends: postgresql-8.1, clamav, clamav-daemon
Suggests: php5-imagick
Suggests: php5-imagick, libfile-slurp-perl, libtext-diff-perl
Pre-Depends: m4, perl, postgresql-client-8.1
Description: Mahara is an electronic portfolio, weblog, and resume builder
Established in 2006, Mahara is the result of a collaborative venture funded by
......@@ -44,7 +44,7 @@ Architecture: all
Depends: ${misc:Depends}, apache2, libapache2-mod-php5, php5-json | libapache2-mod-php5 (>= 5.2), php5-pgsql, php5-cli, php5-gd, file, cron
Conflicts: mahara-apache
Recommends: postgresql-8.1, clamav, clamav-daemon
Suggests: php5-imagick
Suggests: php5-imagick, libfile-slurp-perl, libtext-diff-perl
Pre-Depends: m4, perl, postgresql-client-8.1
Description: Mahara is an electronic portfolio, weblog, and resume builder
Established in 2006, Mahara is the result of a collaborative venture funded by
......
config.php
/config.php
tests
......@@ -90,7 +90,7 @@ function installtemplate(name) {
else {
message = '{$failurestring}';
}
$(name).innerHTML = '<img src="{$failureicon}" alt=":(" /> ' + message;
$(name + '.message').innerHTML = '<img src="{$failureicon}" alt=":(" /> ' + message;
}
},
function () {
......
......@@ -55,11 +55,11 @@ $siteoptionform = pieform(array(
'defaultvalue' => get_config('sitename'),
'help' => true,
),
'language' => array(
'lang' => array(
'type' => 'select',
'title' => get_string('language','admin'),
'description' => get_string('sitelanguagedescription','admin'),
'defaultvalue' => get_config('language'),
'defaultvalue' => get_config('lang'),
'collapseifoneoption' => true,
'options' => $langoptions,
'help' => true,
......@@ -138,7 +138,7 @@ function siteoptions_fail(Pieform $form, $field) {
}
function siteoptions_submit(Pieform $form, $values) {
$fields = array('sitename','language','theme','pathtofile', 'pathtoclam',
$fields = array('sitename','lang','theme','pathtofile', 'pathtoclam',
'allowpublicviews','artefactviewinactivitytime', 'searchplugin');
foreach ($fields as $field) {
if (!set_config($field, $values[$field])) {
......
......@@ -48,18 +48,18 @@ $loadingicon = theme_get_url('images/loading.gif');
$successicon = theme_get_url('images/success.gif');
$failureicon = theme_get_url('images/failure.gif');
$loadingstring = get_string('upgradeloading', 'admin');
$installsuccessstring = get_string('installsuccess', 'admin');
$successstring = get_string('upgradesuccesstoversion', 'admin');
$failurestring = get_string('upgradefailure', 'admin');
$coresuccess = get_string('coredatasuccess', 'admin');
$loadingstring = json_encode(get_string('upgradeloading', 'admin'));
$installsuccessstring = json_encode(get_string('installsuccess', 'admin'));
$successstring = json_encode(get_string('upgradesuccesstoversion', 'admin'));
$failurestring = json_encode(get_string('upgradefailure', 'admin'));
$coresuccess = json_encode(get_string('coredatasuccess', 'admin'));
// Check if Mahara is being installed. An extra hook is required to insert core
// data if so.
if (!empty($upgrades['core']->install)) {
$smarty->assign('install', true);
$installjs =<<< EOJS
$('coredata').innerHTML = '<img src="{$loadingicon}" alt="{$loadingstring}" />';
$('coredata').innerHTML = '<img src="{$loadingicon}" alt="' + {$loadingstring} + '" />';
sendjsonrequest(
'upgrade.json.php',
......@@ -67,7 +67,7 @@ if (!empty($upgrades['core']->install)) {
'GET',
function (data) {
if ( !data.error ) {
var message = '{$coresuccess}';
var message = {$coresuccess};
if (data.message) {
message += ' (' + data.message + ')';
}
......@@ -80,13 +80,13 @@ if (!empty($upgrades['core']->install)) {
message = data.message;
}
else {
message = '{$failurestring}';
message = {$failurestring};
}
$('coredata').innerHTML = '<img src="{$failureicon}" alt=":(" /> ' + message;
}
},
function () {
$('coredata').innerHTML = '<img src="{$failureicon}" alt=":(" /> {$failurestring}';
$('coredata').innerHTML = '<img src="{$failureicon}" alt=":(" /> ' + {$failurestring};
},
true); // quiet.
......@@ -106,16 +106,16 @@ $js .= <<< EOJS
return;
}
$(element).innerHTML = '<img src="{$loadingicon}" alt="{$loadingstring}" />';
$(element).innerHTML = '<img src="{$loadingicon}" alt="' + {$loadingstring} + '" />';
sendjsonrequest('upgrade.json.php', { 'name': element }, 'GET', function (data) {
if ( !data.error ) {
var message;
if (data.install) {
message = '{$installsuccessstring}';
message = {$installsuccessstring};
}
else {
message = '{$successstring}';
message = {$successstring};
}
message += data.newversion;
$(data.key).innerHTML = '<img src="{$successicon}" alt=":)" /> ' + message;
......@@ -126,14 +126,14 @@ $js .= <<< EOJS
message = data.errormessage;
}
else {
message = '{$failurestring}';
message = {$failurestring};
}
$(data.key).innerHTML = '<img src="{$failureicon}" alt=":(" /> ' + message;
}
processNext();
},
function () {
$(element).innerHTML = '<img src="{$failureicon}" alt=":(" /> {$failurestring}';
$(element).innerHTML = '<img src="{$failureicon}" alt=":(" /> ' + {$failurestring};
},
true);
}
......
......@@ -33,6 +33,9 @@ define('TITLE', get_string('uploadcsv', 'admin'));
require_once('pieforms/pieform.php');
safe_require('artefact', 'internal');
// Turn on autodetecting of line endings, so mac newlines (\r) will work
ini_set('auto_detect_line_endings', 1);
$FORMAT = array();
$ALLOWEDKEYS = array(
'username',
......@@ -181,7 +184,7 @@ function uploadcsv_validate(Pieform $form, $values) {
$conf = File_CSV::discoverFormat($values['file']['tmp_name']);
$i = 0;
while ($line = @File_CSV::readQuoted($values['file']['tmp_name'], $conf)) {
while ($line = File_CSV::readQuoted($values['file']['tmp_name'], $conf)) {
$i++;
if (!is_array($line)) {
// Note: the CSV parser returns true on some errors and false on
......@@ -263,6 +266,11 @@ function uploadcsv_validate(Pieform $form, $values) {
$form->set_error('file', get_string('uploadcsverrornorecords', 'admin'));
return;
}
if ($CSVDATA === null) {
// Oops! Couldn't get CSV data for some reason
$form->set_error('file', get_string('uploadcsverrorunspecifiedproblem', 'admin'));
}
}
/**
......
......@@ -27,11 +27,17 @@
define('INTERNAL', 1);
define('JSON', 1);
if (isset($_POST['view'])) {
define('PUBLIC', 1);
}
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
safe_require('artefact', 'resume');
$limit = param_integer('limit', 10);
$offset = param_integer('offset', 0);
$type = param_alpha('type');
$view = param_integer('view', 0);
$data = array();
$count = 0;
......@@ -39,14 +45,30 @@ $count = 0;
$prefix = get_config('dbprefix');
$othertable = 'artefact_resume_' . $type;
$owner = $USER->get('id');
$sql = 'SELECT ar.*, a.owner
FROM ' . $prefix . 'artefact a
JOIN ' . $prefix . $othertable . ' ar ON ar.artefact = a.id
WHERE a.owner = ? AND a.artefacttype = ?
ORDER BY ' . call_static_method(generate_artefact_class_name($type), 'get_order_field') . ' DESC
LIMIT ' . $limit . ' OFFSET ' . $offset;
if (!$data = get_records_sql_array($sql, array($USER->get('id'), $type))) {
if (!empty($view)) {
if (!can_view_view($view)) {
throw new AccessDeniedException();
}
require_once('view.php');
$v = new View($view);
$owner = $v->get('owner');
}
if (!$data = get_records_sql_array($sql, array($owner, $type))) {
$data = array();
}
$count = count_records('artefact', 'owner', $owner, 'artefacttype', $type);
foreach ($data as &$row) {
foreach (array('date', 'startdate', 'enddate') as $key) {
if (array_key_exists($key, $row)) {
......@@ -54,7 +76,6 @@ foreach ($data as &$row) {
}
}
}
$count = count_records('artefact', 'owner', $USER->get('id'), 'artefacttype', $type);
echo json_encode(array(
'data' => $data,
'limit' => $limit,
......
......@@ -26,7 +26,7 @@
defined('INTERNAL') || die();
$string['myresume'] = 'My Résumé';
$string['myresume'] = 'My Resumé';
$string['mygoals'] = 'My Goals';
$string['myskills'] = 'My skills';
$string['coverletter'] = 'Cover Letter';
......@@ -41,8 +41,8 @@ $string['female'] = 'Female';
$string['male'] = 'Male';
$string['gender'] = 'Gender';
$string['maritalstatus'] = 'Marital Status';
$string['resumesaved'] = 'Resume saved';
$string['resumesavefailed'] = 'Failed to update your resume';
$string['resumesaved'] = 'Resumé saved';
$string['resumesavefailed'] = 'Failed to update your resumé';
$string['educationhistory'] = 'Education History';
$string['employmenthistory'] = 'Employment History';
$string['certification'] = 'Certifications, Accreditations, and Awards';
......@@ -66,7 +66,7 @@ $string['contribution'] = 'Contribution';
$string['compositedeleteconfirm'] = 'Are you sure you want to delete this?';
$string['compositesaved'] = 'Saved successfully';
$string['compositedeleted'] = 'Deleted successfully';
$string['backtoresume'] = 'Back to My Résumé';
$string['backtoresume'] = 'Back to My Resumé';
$string['personalgoal'] = 'Personal Goals';
$string['academicgoal'] = 'Academic Goals';
$string['careergoal'] = 'Career Goals';
......@@ -74,8 +74,8 @@ $string['personalskill'] = 'Personal Skills';
$string['academicskill'] = 'Academic Skills';
$string['workskill'] = 'Work Skills';
$string['goalandskillsaved'] = 'Saved successfully';
$string['resume'] = 'Résumé';
$string['resume'] = 'Resumé';
$string['confirmeditprofile'] = 'If you continue to edit your profile now, you will lose any unsaved information in this area';
$string['profilegotoresume'] = 'Edit My Résumé';
$string['profilegotoresume'] = 'Edit My Resumé';
$string['current'] = 'Current';
?>
......@@ -133,7 +133,7 @@ class ArtefactTypeCoverletter extends ArtefactTypeResume {
}
public function render_full($options) {
return array('html' => $this->title);
return array('html' => $this->description);
}
}
......@@ -362,6 +362,10 @@ abstract class ArtefactTypeResumeComposite extends ArtefactTypeResume {
);
}
public static function get_order_field() {
return 'startdate';
}
/**
* This function should return a snippet of javascript
* to be plugged into a table renderer instantiation
......@@ -505,6 +509,12 @@ abstract class ArtefactTypeResumeComposite extends ArtefactTypeResume {
{$type}list.type = '{$type}';
{$type}list.statevars.push('type');
" .
(( array_key_exists('viewid', $options))
? "{$type}list.view = " . $options['viewid'] . ";
{$type}list.statevars.push('view');"
: ""
) . "
{$type}list.updateOnLoad();
");
return $content;
......@@ -738,6 +748,10 @@ class ArtefactTypeCertification extends ArtefactTypeResumeComposite {
return "r.description";
}
public static function get_order_field() {
return 'date';
}
public static function get_addform_elements() {
return array(
'date' => array(
......@@ -795,6 +809,10 @@ class ArtefactTypeBook extends ArtefactTypeResumeComposite {
return "r.description";
}
public static function get_order_field() {
return 'date';
}
public static function get_addform_elements() {
return array(
'date' => array(
......
<h3>{str tag='book' section='artefact.resume'}
{contextualhelp plugintype='artefact' pluginname='resume' section='addbook'}</h3>
{if $controls}
{contextualhelp plugintype='artefact' pluginname='resume' section='addbook'}
{/if}
</h3>
<table id="booklist" class="tablerenderer hidden resumefour">
<thead>
<tr>
......
<h3>{str tag='certification' section='artefact.resume'}
{contextualhelp plugintype='artefact' pluginname='resume' section='addcertification'}</h3>
{if $controls}
{contextualhelp plugintype='artefact' pluginname='resume' section='addcertification'}
{/if}
</h3>
<table id="certificationlist" class="tablerenderer hidden resumefour">
<thead>
<tr>
......
<h3>{str tag='educationhistory' section='artefact.resume'}
{contextualhelp plugintype='artefact' pluginname='resume' section='addeducationhistory'}</h3>
{if $controls}
{contextualhelp plugintype='artefact' pluginname='resume' section='addeducationhistory'}
{/if}
</h3>
<table id="educationhistorylist" class="tablerenderer hidden resumefive">
<thead>
<tr>
......
<h3>{str tag='employmenthistory' section='artefact.resume'}
{contextualhelp plugintype='artefact' pluginname='resume' section='addemploymenthistory'}</h3>
{if $controls}
{contextualhelp plugintype='artefact' pluginname='resume' section='addemploymenthistory'}
{/if}
</h3>
<table id="employmenthistorylist" class="tablerenderer hidden resumefive">
<thead>
<tr>
......
<h3>{str tag='membership' section='artefact.resume'}
{contextualhelp plugintype='artefact' pluginname='resume' section='addmembership'}</h3>
{if $controls}
{contextualhelp plugintype='artefact' pluginname='resume' section='addmembership'}
{/if}
</h3>
<table id="membershiplist" class="tablerenderer hidden resumefive">
<thead>
<tr>
......
......@@ -838,7 +838,7 @@ function auth_get_login_form() {
*/
function get_login_form_js($form) {
$form = str_replace('/', '\/', str_replace("'", "\'", (str_replace(array("\n", "\t"), '', $form))));
$strcookiesnotenabled = get_string('cookiesnotenabled');
$strcookiesnotenabled = json_encode(get_string('cookiesnotenabled'));
$cookiename = get_config('cookieprefix') . 'ctest';
return <<<EOF
<script type="text/javascript">
......@@ -849,7 +849,7 @@ if (document.cookie) {
document.cookie = '$cookiename=1;expires=1/1/1990 00:00:00';
}
else {
replaceChildNodes(loginbox, P(null, '$strcookiesnotenabled'));
replaceChildNodes(loginbox, P(null, $strcookiesnotenabled));
}
</script>
EOF;
......
......@@ -71,7 +71,7 @@ switch ($type) {
}
$count = count_records_sql('
SELECT COUNT(id)
SELECT COUNT(DISTINCT id)
FROM ' . $prefix . 'view v
LEFT OUTER JOIN ' . $prefix . 'view_access_community a ON a.view=v.id
' . $where,
......@@ -79,7 +79,7 @@ switch ($type) {
);
$data = get_records_sql_array('
SELECT v.*, u.username, u.firstname, u.lastname, u.preferredname, u.id AS usr
SELECT DISTINCT v.*, u.username, u.firstname, u.lastname, u.preferredname, u.id AS usr
FROM ' . $prefix . 'view v
LEFT OUTER JOIN ' . $prefix . 'view_access_community a ON a.view=v.id
INNER JOIN ' . $prefix.'usr u ON v.owner = u.id ' . $where,
......
......@@ -180,6 +180,7 @@ $string['csvfiledescription'] = 'The file containing users to add';
$string['uploadcsverrorinvalidfieldname'] = 'The field name "%s" is invalid';
$string['uploadcsverrorrequiredfieldnotspecified'] = 'A required field "%s" has not been specified in the format line';
$string['uploadcsverrornorecords'] = 'The file appears to contain no records (although the header is fine)';
$string['uploadcsverrorunspecifiedproblem'] = 'The records in your CSV file could not be inserted for some reason. If your file is in the correct format then this is a bug and you should <a href="https://eduforge.org/tracker/?func=add&group_id=176&atid=739">create a bug report</a>, attaching the CSV file (remember to blank out passwords!) and, if possible, the error log file';
$string['uploadcsverrorinvalidemail'] = 'Error on line %s of your file: The e-mail address for this user is not in correct form';
$string['uploadcsverrorincorrectnumberoffields'] = 'Error on line %s of your file: This line does not have the correct number of fields';
$string['uploadcsverrorinvalidpassword'] = 'Error on line %s of your file: The password for this user is not in correct form';
......
......@@ -959,7 +959,7 @@
<SENTENCE TEXT="(name) VALUES ('academic')" />
<SENTENCE TEXT="(name) VALUES ('professionaldevelopment')" />
<SENTENCE TEXT="(name) VALUES ('personaldevelopment')" />
</SENTANCES>
</SENTENCES>
</STATEMENT>
</STATEMENTS>
</XMLDB>
......@@ -296,6 +296,11 @@ function xmldb_core_upgrade($oldversion=0) {
// everything up to here we pre mysql support.
if ($oldversion < 2007062000) {
execute_sql("INSERT INTO {$prefix}config (field, value) VALUES ('lang', (SELECT value FROM {$prefix}config WHERE field = 'language'))");
delete_records('config', 'field', 'language');
}
return $status;
}
......
......@@ -477,8 +477,6 @@ class MaharaException extends Exception {
$outputtitle = $this->get_string('title');
$outputmessage = $this->render_exception();
$message = strip_tags($outputmessage);
$message = htmlspecialchars_decode($message);
if (function_exists('smarty') && !$this instanceof ConfigSanityException) {
$smarty = smarty();
......@@ -487,6 +485,8 @@ class MaharaException extends Exception {
$smarty->display('error.tpl');
}
else {
$outputtitle = hsc($outputtitle);
$outputmessage = nl2br(hsc($outputmessage));
echo <<<EOF
<html>
<head>
......@@ -524,9 +524,6 @@ class MaharaException extends Exception {
</head>
<body>
EOF;
if (function_exists('insert_messages')) {
echo insert_messages();
}
echo <<<EOF
<h1>$outputtitle</h1>
<div id="message">$outputmessage</div>
......@@ -588,14 +585,14 @@ class UserException extends MaharaException implements MaharaThrowable {
protected $log = false;
public function render_exception() {
return $this->get_string('message') . '<br><br>' . $this->getMessage();
return $this->get_string('message') . "\n\n" . $this->getMessage();
}
public function strings() {
return array_merge(parent::strings(),
array('message' => 'Something in the way you\'re interacting with '
. $this->get_sitename()
.' is causing an error.<br>Details if any, follow:'));
. " is causing an error.\nDetails if any, follow:"));
}
}
......@@ -628,7 +625,10 @@ class SQLException extends SystemException {
*/
class ParameterException extends UserException {
public function strings() {
return array_merge(parent::strings(), array('message' => 'A required parameter was missing'));
return array_merge(parent::strings(), array(
'title' => 'Mahara: Invalid Parameter',
'message' => 'A required parameter is missing or malformed')
);
}
}
......
......@@ -77,6 +77,7 @@ function pieform_element_tags_get_value(Pieform $form, $element) {
}
$value = preg_split("/\s*,\s*/", trim($global[$name]));
$value = array_unique(array_filter($value, create_function('$v', 'return !empty($v);')));
return $value;
}
......
......@@ -180,59 +180,63 @@ class File_CSV
$in_quote = false;
$quote = $conf['quote'];
$f = $conf['fields'];
while (($ch = fgetc($fp)) !== false) {
$prev = $c;
$c = $ch;
// Common case
if ($c != $quote && $c != $conf['sep'] && $c != "\n") {
$buff .= $c;
continue;
}
if ($c == $quote && $quote &&
($prev == $conf['sep'] || $prev == "\n" || $prev === null))
{
$in_quote = true;
} elseif ($in_quote) {
// When ends quote
if ($c == $conf['sep'] && $prev == $conf['quote']) {
$in_quote = false;
} elseif ($c == "\n") {
$sub = ($prev == "\r") ? 2 : 1;
if ((strlen($buff) >= $sub) &&
($buff{strlen($buff) - $sub} == $quote))
{
while (($line = fgets($fp)) !== false) {
$line = preg_replace("/\r$/", "\n", $line);
$length = strlen($line);
for ($j = 0; $j < strlen($line); $j++) {
$prev = $c;
$c = substr($line, $j , 1);
// Common case
if ($c != $quote && $c != $conf['sep'] && $c != "\n") {
$buff .= $c;
continue;
}
if ($c == $quote && $quote &&
($prev == $conf['sep'] || $prev == "\n" || $prev === null))
{
$in_quote = true;
} elseif ($in_quote) {
// When ends quote
if ($c == $conf['sep'] && $prev == $conf['quote']) {
$in_quote = false;
} elseif ($c == "\n") {
$sub = ($prev == "\r") ? 2 : 1;
if ((strlen($buff) >= $sub) &&
($buff{strlen($buff) - $sub} == $quote))
{
$in_quote = false;
}
}
}
}
if (!$in_quote && ($c == $conf['sep'] || $c == "\n")) {
// More fields than expected
if (($c == $conf['sep']) && ((count($ret) + 1) == $f)) {