diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..6ae6fbf --- /dev/null +++ b/.htaccess @@ -0,0 +1,3 @@ + +deny from all + diff --git a/author/contact.php b/author/contact.php new file mode 100644 index 0000000..020969e --- /dev/null +++ b/author/contact.php @@ -0,0 +1,125 @@ +' . oc_('Fields not correctly filled out') . ''; + } + if (!isset($_POST['name']) || !preg_match("/\p{L}/u", $_POST['name']) || preg_match("/[\r\n]/", $_POST['name'])) { + $err .= '
  • ' . sprintf(oc_('%s field empty or invalid'), oc_('Name')) . '
  • '; + } + if (!isset($_POST['liame']) || !validEmail(($_POST['liame'] = trim($_POST['liame']))) || preg_match("/[\r\n]/", $_POST['liame'])) { + $err .= '
  • ' . sprintf(oc_('%s field empty or invalid'), oc_('Email')) . '
  • '; + } + if (($OC_configAR['OC_privacy_display'] > 0) && (!isset($_POST['consent']) || ($_POST['consent'] != '1'))) { + $err .= '
  • ' . sprintf(oc_('%s field is required'), oc_('Consent')) . '
  • '; + } + if (!isset($_POST['subject']) || !preg_match("/\p{L}/u", $_POST['subject']) || preg_match("/[\r\n]/", $_POST['subject'])) { + $err .= '
  • ' . sprintf(oc_('%s field empty or invalid'), oc_('Subject')) . '
  • '; + } + if (!isset($_POST['message']) || !preg_match("/\p{L}/u", $_POST['message'])) { + $err .= '
  • ' . sprintf(oc_('%s field empty or invalid'), oc_('Message')) . '
  • '; + } else { + $message = $_POST['message']; + } + + if (oc_hookSet('author-contact-validate')) { + foreach ($GLOBALS['OC_hooksAR']['author-contact-validate'] as $hook) { + require_once $hook; + } + } + + if (empty($err)) { + // add who it's from to body of message in case of an issue with reply headers + $message .= "\n\nFrom: " . $_POST['name'] . ' <' . $_POST['liame'] . ">\n"; + + // setup Reply-To + if (empty($hdr)) { + $hdr = 'From: "' . preg_replace('/"/', '', $_POST['name']) . '" <' . $GLOBALS['OC_configAR']['OC_pcemail'] . '>' . "\r\n" . // pcemail used to avoid email validation issues + 'Reply-To: ' . $_POST['liame'] . "\r\n"; + } else { + if (preg_match("/^(.*Reply-To:\s?)\S+(.*)$/s", $hdr, $matches)) { + $hdr = $matches[1] . $_POST['liame'] . $matches[2]; + } elseif (preg_match("/[\r\n]$/s", $hdr)) { + $hdr .= 'Reply-To: ' . $_POST['liame'] . "\r\n"; + } else { + $hdr .= "\r\n" . 'Reply-To: ' . $_POST['liame'] . "\r\n"; + } + } + if (! oc_mail($OC_configAR['OC_pcemail'], $_POST['subject'], $message, $hdr)) { + err(oc_('An error occurred sending out the email.')); + } else { + print '
    ' . oc_('Your message has been sent.') . '
    '; + printFooter(); + exit; + } + } +} + +print ' + +
    + + + +'; + +if (!empty($err)) { + print ' + +'; + +if ($OC_configAR['OC_privacy_display'] > 0) { + print ''; +} + +print ' + + +'; + +if (oc_hookSet('author-contact-fields')) { + foreach ($GLOBALS['OC_hooksAR']['author-contact-fields'] as $hook) { + require_once $hook; + } +} + +print ' + +
     ' . oc_('Please correct the following:') . '
      ' . $err . '

    '; +} + +print ' +
     

    +
    +

    +'; + +printFooter(); + +?> diff --git a/author/edit.php b/author/edit.php new file mode 100644 index 0000000..b2928f0 --- /dev/null +++ b/author/edit.php @@ -0,0 +1,407 @@ +' . oc_('Submission edits are no longer available.') . '

    '; + } else { + warn(oc_('Submission edits are no longer available.')); + exit; + } + } else { + // set token + $token = oc_idGen(); + $pr = ocsql_query("UPDATE `" . OCC_TABLE_PAPER . "` SET `edittoken`='" . safeSQLstr($token) . "', `edittime`='" . safeSQLstr(time()) . "' WHERE `paperid`=" . (int) $_POST['pid'] . " LIMIT 1") or err(oc_('Unable to edit submission') . ' (token)'); + } + } + + if ($showPaper) { + $pid = $_POST['pid']; + require_once 'view.inc'; + printFooter(); + exit; + } + + } + } elseif ($_POST['ocaction'] != 'Submit Changes') { + warn(oc_('Invalid request')); + exit; + } + + if ($chair) { // display back links + print '

    View This Submission | View All Submissions

    '; + } elseif ($_POST['ocaction'] == 'Submit Changes') { // check token + $pq = "SELECT `edittoken`, `edittime` FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`='" . safeSQLstr($_POST['pid']) . "'"; + $pr = ocsql_query($pq) or err(oc_('Unable to retrieve submission') . ' (tokeninfo)'); + if (ocsql_num_rows($pr) != 1) { err(oc_('Submission ID or password entered is incorrect')); } + $pl = ocsql_fetch_assoc($pr); + if (!isset($_POST['edittoken']) + || ($_POST['edittoken'] != $pl['edittoken']) + || ((time() - $pl['edittime']) > (60 * 60 * $editTimeout)) + ) { + warn(sprintf(oc_('There is a %1$d hour timeout for editing the submission. Please edit submission once again'), $editTimeout, $_SERVER['PHP_SELF'])); + exit; + } + } + + // Set number of author fields to display if Submit Changes, else populate $_POST with database fields + if (isset($_POST['authornum']) && ctype_digit($_POST['authornum'])) { + $oc_authorNum = $_POST['authornum']; + } else { + // get sub + $anr = ocsql_query("SELECT * FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`=" . (int) $_POST['pid']) or err("Unable to retrieve submission information"); + if (ocsql_num_rows($anr) != 1) { + err(oc_('Submission ID or password entered is incorrect')); + } + $_POST = array_merge((array)$_POST, ocsql_fetch_assoc($anr)); + + // get authors + $authorCount = 0; + $anr = ocsql_query("SELECT * FROM `" . OCC_TABLE_AUTHOR . "` WHERE `paperid`=" . (int) $_POST['pid'] . " ORDER BY `position`") or err(oc_('Unable to retrieve author(s) information')); + while ($anl = ocsql_fetch_assoc($anr)) { + foreach ($anl as $anli => $anlv) { + if (($anli == 'paperid') || ($anli == 'position')) { continue; } + $_POST[$anli . $anl['position']] = $anlv; + } + $authorCount = $anl['position']; // track highest position + } + + // get topics + $anr = ocsql_query("SELECT `topicid` FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `paperid`=" . (int) $_POST['pid']) or err(oc_('Unable to retrieve topic(s) information')); + $_POST['topics'] = array(); + while ($anl = ocsql_fetch_assoc($anr)) { + $_POST['topics'][] = $anl['topicid']; + } + + // set author num to either use min display or actual author count, whichever is greater + $oc_authorNum = (($authorCount > $OC_configAR['OC_authorsMinDisplay']) ? $authorCount : $OC_configAR['OC_authorsMinDisplay']); + + // set token + if (! $chair) { + $_POST['edittoken'] = $token; + } + } + + if (oc_hookSet('author-edit-preprocess')) { + foreach ($GLOBALS['OC_hooksAR']['author-edit-preprocess'] as $hook) { + require_once $hook; + } + } + + require_once OCC_FORM_INC_FILE; + require_once OCC_SUBMISSION_INC_FILE; + + // Set non-editable fields to disabled if submissions closed (and it's not Chair) + if (! $chair && ! $OC_statusAR['OC_submissions_open']) { + foreach ($OC_submissionFieldAR as $fid => $far) { + if (isset($far['closeedit']) && ! $far['closeedit']) { + $OC_submissionFieldAR[$fid]['enabled'] = false; + } + } + } + + // remove consent field if already given + if (isset($OC_submissionFieldAR['consent'])) { + $cr = ocsql_query("SELECT `consent` FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`='" . safeSQLstr($_POST['pid']) . "'") or err('Unable to query consent status'); + $cl = ocsql_fetch_assoc($cr); + if (!empty($cl['consent'])) { + unset($OC_submissionFieldAR['consent']); + foreach ($OC_submissionFieldSetAR as $fsid => $fsar) { // remove from fieldset + if (in_array('consent', $fsar['fields'])) { + $OC_submissionFieldSetAR[$fsid]['fields'] = array_diff($OC_submissionFieldSetAR[$fsid]['fields'], array('consent')); + continue; // field should only be in one fieldset + } + } + } + } + + // Update topic field? + if ( isset($OC_submissionFieldAR['topics']['type']) && ($OC_submissionFieldAR['topics']['type'] == 'radio') && isset($_POST['topics']) && is_array($_POST['topics']) && isset($_POST['topics'][0]) ) { + $_POST['topics'] = $_POST['topics'][0]; // change from array to single value + } + + // Update password fieldset + $OC_submissionFieldSetAR['fs_passwords']['fieldset'] = oc_('Change Password'); + $OC_submissionFieldSetAR['fs_passwords']['note'] = oc_('Leave these fields blank if you do not want to change the password'); + $OC_submissionFieldAR['password1']['name'] = oc_('New Password'); + + // Check whether we're submitting changes + if ($_POST['ocaction'] == "Submit Changes") { + if ($chair && !validToken('chair')) { + warn(oc_('Invalid submission')); + } + + $err = ''; + $errInc = ''; + $qfields = array(); // fields to insert into submission table + $afields = array(); // fields to insert into authors table + $tfields = array(); // fields to insert into topics table + $fileUploaded = false; + + require_once 'submission-validate.inc'; + + // process if no errors + if (!empty($err)) { + print '

    ' . oc_('Please check the following:') . '




    '; + } else { + $q = "UPDATE `" . OCC_TABLE_PAPER . "` SET `lastupdate`='" . safeSQLstr(date("Y-m-d")) . "', `edittoken`=NULL, `edittime`=NULL"; + foreach ($qfields as $qid => $qval) { + $q .= ", `" . $qid . "`=" . $qval; + } + $q .= " WHERE `paperid`=" . (int) $_POST['pid']; + $r = ocsql_query($q) or err(oc_('Unable to update submission')); + + $q = "DELETE FROM `" . OCC_TABLE_AUTHOR . "` WHERE `paperid`=" . (int) $_POST['pid']; + $r = ocsql_query($q) or err(oc_('Unable to update authors or topics (2)')); + foreach ($afields as $qid => $qar) { + $q = "INSERT INTO `" . OCC_TABLE_AUTHOR . "` SET `paperid`=" . (int) $_POST['pid'] . ", `position`=" . (int) $qid; + foreach ($qar as $qqid => $qqval) { + $q .= ", `" . $qqid . "`=" . $qqval; + } + $r = ocsql_query($q) or err(oc_('Unable to add one or more authors or topics.')); + } + + if (!empty($tfields)) { + $q = "DELETE FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `paperid`='" . safeSQLstr($_POST['pid']) . "'"; + $r = ocsql_query($q) or err(oc_('Unable to update topics')); + $q = "INSERT INTO `" . OCC_TABLE_PAPERTOPIC . "` (`paperid`,`topicid`) VALUES"; + foreach ($tfields as $t) { + $q .= " (" . safeSQLstr($_POST['pid']) . ",$t),"; + } + $r = ocsql_query(rtrim($q, ',')) or err(oc_('Unable to add topics')); + } + + // Get and update notification template + // ocIgnore included so poEdit picks up (DB) template translation + //T: [:sid:] is the numeric submission ID + $ocIgnoreSubject = oc_('Submission Update ID [:sid:]'); + $ocIgnoreBody = '[:fields:]'; // don't bother with translation + $fields = oc_genFieldMessage($OC_submissionFieldSetAR, $OC_submissionFieldAR, $_POST); + list($mailsubject, $mailbody) = oc_getTemplate('author-edit'); + $templateExtraAR = array( + 'sid' => $_POST['pid'], + 'fields' => (oc_('Submission ID') . ': ' . $_POST['pid'] . "\n\n" . $fields) + ); + $mailsubject = oc_replaceVariables($mailsubject, $templateExtraAR); + $mailbody = oc_replaceVariables($mailbody, $templateExtraAR); + + // Set up confirmation + $confirmmsg = '

    ' . safeHTMLstr(oc_('The submission has been updated. Below is the information submitted.')) . '

    ' . safeHTMLstr($fields) . '
    '; + if (! $chair) { + $confirmmsg .= '

    ' . sprintf(oc_('A copy has also been emailed to the contact author. If you notice any problems or do not receive the email within 24 hours, please contact the Chair.'), urlencode($OC_configAR['OC_pcemail']), urlencode($_POST['pid'])) . '

    '; + } + + if (oc_hookSet('author-edit-save')) { + foreach ($GLOBALS['OC_hooksAR']['author-edit-save'] as $hook) { + require_once $hook; + } + } + + //confirm it + print $confirmmsg; + if (! $chair) { + if (($OC_configAR['OC_emailAuthorRecipients'] == 1) && !empty($allemails)) { + $mailto = $allemails; + } else { + $mailto = $contactemail; + } + sendEmail($mailto, $mailsubject, $mailbody, $OC_configAR['OC_notifyAuthorEdit']); + } + + printFooter(); + + // log + oc_logit('submission', 'Submission ID ' . $_POST['pid'] . ' edited' . ($chair ? ' by Chair' : '') . '. Title: ' . $_POST['title']); + + exit; + } // else no $err + } // if Submit Changes + + + // Display form + print ' +
    + + + +'; + + if ($chair) { + print ' + + +'; + } else { + print ' + +'; + } + + oc_displayFieldSet($OC_submissionFieldSetAR, $OC_submissionFieldAR, $_POST); + + if (oc_hookSet('author-edit-fields')) { + foreach ($GLOBALS['OC_hooksAR']['author-edit-fields'] as $hook) { + require_once $hook; + } + } + + if (! $chair) { + print ' +
    +
    +

    ' . oc_('Emails will be sent to:') . '

    +

    +
    +
    +'; + } + + print '

    '; + + if (! $chair) { + print ' +        +' . oc_('Cancel Changes') . ' +'; + } + + print '

    + +
    +'; + + printFooter(); + + exit; + +} // if Submission + +// display login form by default +print ' +
    + + + + +
    : ( ' . oc_('forgot ID?') . ' )
    : ( ' . oc_('forgot password?') . ' )
    +

    +
    +' . +( + $showPaper ? + '' + : + '

    ' . sprintf(oc_('There is a %d hour limit to complete updates'), $editTimeout) . '

    ' +) . ' + +'; + +if (oc_hookSet('author-edit-bottom')) { + foreach ($GLOBALS['OC_hooksAR']['author-edit-bottom'] as $hook) { + require_once $hook; + } +} + +printFooter(); + +exit; + +?> diff --git a/author/email_papers.php b/author/email_papers.php new file mode 100644 index 0000000..d70bf82 --- /dev/null +++ b/author/email_papers.php @@ -0,0 +1,67 @@ +' . oc_('Email address entered is invalid') . '

    '; + printFooter(); + exit; + } + $q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_AUTHOR . "`.`email`='" . safeSQLstr(oc_strtolower($_POST['email'])) . "' AND `" . OCC_TABLE_AUTHOR . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_AUTHOR . "`.`position`=`" . OCC_TABLE_PAPER . "`.`contactid` ORDER BY `" . OCC_TABLE_PAPER . "`.`paperid`"; + $r = ocsql_query($q) or err(oc_('Error checking for submissions')); + if (($rnum=ocsql_num_rows($r)) == 0) { + print '

    ' . sprintf(oc_("We did not find any submissions where the contact author's email is %s"), safeHTMLstr($_POST['email'])) . '.

    '; + printFooter(); + exit; + } + else { + $msg = "\n" . sprintf(oc_('Per your request, here is a list of submissions made to the %s OpenConf system with you listed as the contact:'), $OC_configAR['OC_confName']) . "\n"; + + while ($e = ocsql_fetch_array($r)) { + $msg .= ' +ID: ' . $e['paperid'] . ' +Title: ' . $e['title'] . ' + '; + } + sendEmail($_POST['email'], oc_('List of submissions made'), $msg, $OC_configAR['OC_notifyAuthorEmailPapers']); + print oc_('We have emailed the list of submissions for which you are the contact author.'); + printFooter(); + exit; + } +} +else { + print '

    ' . oc_('Please enter your email address below and click on Email Submissions. We will then email you a list of submissions for which you are the contact author.') . "

    \n"; +} + +print ' +
    + + + + +
    ' . oc_('Email') . ':

    +
    +'; + +if (oc_hookSet('author-email_papers-bottom')) { + foreach ($GLOBALS['OC_hooksAR']['author-email_papers-bottom'] as $hook) { + require_once $hook; + } +} + +printFooter(); + +?> diff --git a/author/index.html b/author/index.html new file mode 100644 index 0000000..e69de29 diff --git a/author/index.php b/author/index.php new file mode 100644 index 0000000..e69de29 diff --git a/author/paper.php b/author/paper.php new file mode 100644 index 0000000..de5f4a7 --- /dev/null +++ b/author/paper.php @@ -0,0 +1,93 @@ + + + +'; + +if (oc_hookSet('author-viewfile-formtop')) { + foreach ($GLOBALS['OC_hooksAR']['author-viewfile-formtop'] as $hook) { + require_once $hook; + } +} + +print ' + + +
    ( ' . oc_('forgot ID?') . ' )
    ( ' . oc_('forgot password?') . ' )
    +

    + +'; + +if (oc_hookSet('author-paper-bottom')) { + foreach ($GLOBALS['OC_hooksAR']['author-paper-bottom'] as $hook) { + require_once $hook; + } +} + +printFooter(); + +?> diff --git a/author/reset.php b/author/reset.php new file mode 100644 index 0000000..f00fde8 --- /dev/null +++ b/author/reset.php @@ -0,0 +1,64 @@ +' . oc_('Email address entered is invalid') . '

    '; + printFooter(); + exit; + } + $q = "SELECT `" . OCC_TABLE_AUTHOR . "`.`email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_PAPER . "`.`paperid`='" . safeSQLstr($_POST['pid']) . "' AND `" . OCC_TABLE_AUTHOR . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_AUTHOR . "`.`position`=`" . OCC_TABLE_PAPER . "`.`contactid` AND `" . OCC_TABLE_AUTHOR . "`.`email`='" . safeSQLstr(oc_strtolower($_POST['email'])) . "'"; + $r = ocsql_query($q) or err(oc_('Error checking submission ID')); + if (ocsql_num_rows($r) != 1) { + print '

    ' . oc_("Submission ID or contact author's email invalid.") . ' ' . sprintf(oc_('Please contact the Chair.'), $OC_configAR['OC_pcemail'], 'Unable to Reset Password') . '

    '; + printFooter(); + exit; + } + else { + $newpwd = oc_password_generate(); + $q2 = "UPDATE `" . OCC_TABLE_PAPER . "` SET `password`='" . safeSQLstr(oc_password_hash($newpwd)) . "' WHERE `paperid`='" . safeSQLstr($_POST['pid']) . "'"; + $r2 = ocsql_query($q2) or err(oc_('Unable to update password')); + $msg = "\n" . sprintf(oc_('Per your request, we have issued you a new password for accessing the %s OpenConf system. The new password is:'), $OC_configAR['OC_confName']) . "\n " . $newpwd . "\n\n" . oc_('You may change this password by signing in to the OpenConf system and editing your submission.'); + sendEmail($_POST['email'], oc_('Author Password Reset'), $msg, $OC_configAR['OC_notifyAuthorReset']); + print oc_('We have emailed you a new password.'); + printFooter(); + exit; + } +} +else { + print '

    ' . oc_('Please enter your submission id and the contact author\'s email below') . "

    \n"; +} + +print ' +
    + + + + + +
    ' . oc_('Submission ID') . ':
    ' . oc_('Email') . ':

    +'; + +if (oc_hookSet('author-reset-bottom')) { + foreach ($GLOBALS['OC_hooksAR']['author-reset-bottom'] as $hook) { + require_once $hook; + } +} + + +printFooter(); + +?> diff --git a/author/status.php b/author/status.php new file mode 100644 index 0000000..f2e756d --- /dev/null +++ b/author/status.php @@ -0,0 +1,140 @@ +' . oc_('Submission ID') . ': ' . safeHTMLstr($_POST['pid']) . '

    +

    ' . +//T: Submission Title +oc_('Title') . ': ' . safeHTMLstr($l['title']) . '

    +

    ' . +//T: Submission Status +oc_('Status') . ': ' . (empty($l['accepted']) ? oc_('Pending') : safeHTMLstr(oc_($l['accepted']))) . '

    +'; + + if (oc_hookSet('author-status')) { + foreach ($GLOBALS['OC_hooksAR']['author-status'] as $v) { + require_once $v; + } + } + + // display review comments to author + if ($OC_configAR['OC_authorSeePendingSubReviews'] || !empty($l['accepted'])) { + $q2 = "SELECT * FROM `" . OCC_TABLE_PAPERREVIEWER . "` WHERE `paperid`='" . safeSQLstr($_POST['pid']) . "' ORDER BY `reviewerid`"; + $r2 = ocsql_query($q2) or err('Unable to retrieve review data'); + if (ocsql_num_rows($r2) > 0) { + // Fields to display + $displayFieldAR = array(); + foreach ($OC_reviewQuestionsAR as $fid => $far) { + if (isset($far['showauthor']) && $far['showauthor']) { + $displayFieldAR[] = $fid; + } + } + if (count($displayFieldAR) > 0) { + $rcount = 1; + while ($l2 = ocsql_fetch_assoc($r2)) { + $reviewInfo = ''; + foreach ($displayFieldAR as $fid) { + if (!empty($l2[$fid])) { + $reviewInfo .= '

    ' . safeHTMLstr(oc_($OC_reviewQuestionsAR[$fid]['short'])) . ': ' . nl2br(safeHTMLstr(oc_getFieldValue($OC_reviewQuestionsAR, $l2, $fid))) . "

    \n"; + } + } + if (!empty($reviewInfo)) { + print '

    ' . safeHTMLstr(sprintf(oc_('Reviewer %s'), $rcount++)) . ':

    ' . $reviewInfo . '
    '; + } + } + } + } + } + printFooter(); + } else { + warn(oc_('Submission ID or password entered is incorrect'), $hdr, $hdrfn); + } + } else { + warn(oc_('Submission ID or password entered is incorrect'), $hdr, $hdrfn); + } +} +else { // not a submission -- display sub id/password form + // set author token + $_SESSION['atoken'] = oc_idGen(); + session_write_close(); + + printHeader($hdr, $hdrfn); + + print ' + + + + + + +
    : ( ' . oc_('forgot ID?') . ' )
    : ( ' . oc_('forgot password?') . ' )
    +

    +
    + +'; + printFooter(); + + if (oc_hookSet('author-status-bottom')) { + foreach ($GLOBALS['OC_hooksAR']['author-status-bottom'] as $hook) { + require_once $hook; + } + } + +} + +exit; + +?> \ No newline at end of file diff --git a/author/submission-validate.inc b/author/submission-validate.inc new file mode 100644 index 0000000..b19cc4f --- /dev/null +++ b/author/submission-validate.inc @@ -0,0 +1,152 @@ + $fs) { + if ($fsid != 'fs_authors') { // non-author field + foreach ($fs['fields'] as $fid) { + if (!preg_match("/^(?:file|password\d)$/", $fid)) { // skip validation of special fields + oc_validateField($fid, $GLOBALS['OC_submissionFieldAR'], $qfields, $err); + } + } + } else { // author field + for ($a=1; $a<=$OC_configAR['OC_authorsMax']; $a++) { + if (!isset($_POST['name_last' . $a]) || empty($_POST['name_last' . $a])) { + if ($firstBlankAuthor == 0) { + $firstBlankAuthor = $a; + } + if ((isset($_POST['name_first' . $a]) && !empty($_POST['name_first' . $a])) + || (isset($_POST['organization' . $a]) && !empty($_POST['organization' . $a])) + || (isset($_POST['email' . $a]) && !empty($_POST['email' . $a])) + ) { + $err .= '
  • ' . sprintf(oc_('Author %d missing last name'), $a) . '
  • '; + } + } else { + $afields[$a] = array('name_last' => "'" . safeSQLstr(varValue('name_last' . $a, $_POST)) . "'"); + foreach ($fs['fields'] as $fid) { + if ($fid == 'name_last') { continue; } + // override required field attribute? + $requiredOverride = false; + if ($OC_configAR['OC_authorsRequiredData'] > 0) { + if (($OC_configAR['OC_authorsRequiredData'] == 1) && ($a != 1)) { // first author + $requiredOverride = true; + } elseif (($OC_configAR['OC_authorsRequiredData'] == 2) && ($a != $_POST['contactid'])) { // contact author + $requiredOverride = true; + } + } + // validate + oc_validateField($fid, $GLOBALS['OC_submissionFieldAR'], $afields[$a], $err, $a, $requiredOverride); + } + $lastAuthor = $a; + if (isset($_POST['email'.$a]) && !empty($_POST['email'.$a])) { + $allemails .= $_POST['email'.$a] . ','; + } + } + } + } +} +$allemails = rtrim($allemails, ','); + +// Additional author checks +if ($lastAuthor == 0) { // no author info + $err .= '
  • ' . oc_('Authors information missing.') . '
  • '; +} elseif (($firstBlankAuthor > 0) && ($firstBlankAuthor < $lastAuthor)) { // blank author - can't skip otherwise ordering will be messed up + $err .= '
  • ' . oc_('One or more author\'s data skipped. Please enter authors sequentially.') . '
  • '; +} elseif (!preg_match("/^\d+$/", $_POST['contactid']) || ($_POST['contactid'] < 1) || ($_POST['contactid'] > $OC_configAR['OC_authorsMax'])) { // Check that we have a valid contact author & email + $err .= '
  • ' . oc_('Contact author invalid') . '
  • '; +} else { + $contactemail = $_POST['email' . $_POST['contactid']]; + if (!validEmail($contactemail)) { + $err .= '
  • ' . oc_('Contact author email does not seem valid') . '
  • '; + } +} + +// Update topics +if (isset($qfields['topics'])) { + if ($qfields['topics'] != 'NULL') { + if (!preg_match("/^'[\d\,]*'$/", $qfields['topics'])) { + $err .= '
  • ' . sprintf(oc_('%s field does not appear to be valid'), oc_('Topic')) . '
  • '; // should only trigger if validateField above fails + } else { + $tfields = explode(',', trim($qfields['topics'], "'")); + } + } + unset($qfields['topics']); +} + +// Check file +if (isset($OC_submissionFieldAR['file'])) { + if ( isset($_FILES['file']['error']) // good upload + && ($_FILES['file']['error'] == UPLOAD_ERR_OK) // no error + && is_uploaded_file($_FILES['file']['tmp_name']) // legitimate upload + && ($_FILES['file']['size'] > 0) // file not empty + && (empty($OC_configAR['OC_fileLimit']) || ($_FILES['file']['size'] <= ($OC_configAR['OC_fileLimit'] * 1024 * 1024))) // file size <= limit + ) { // file uploaded ok + if ( ! isset($_POST['format']) || ! in_array($_POST['format'], $extAR) ) { // invalid format + $err .= '
  • ' . oc_('File format invalid') . '
  • '; + } else { // upload good + $fileUploaded = true; + $errInc .= '
  • ' . oc_('Also, re-select the file') . '
  • '; // let user know file must be re-selected if there was another error + if (oc_hookSet('author-file-validate')) { + foreach ($GLOBALS['OC_hooksAR']['author-file-validate'] as $hook) { + require_once $hook; + } + } + } + } elseif ( isset($_FILES['file']['error']) ) { // notify of error + switch($_FILES['file']['error']) { + case UPLOAD_ERR_INI_SIZE: + case UPLOAD_ERR_FORM_SIZE: + $err .= '
  • ' . oc_('File size too large') . '
  • '; + break; + case UPLOAD_ERR_NO_FILE: + if (isset($OC_submissionFieldAR['file']['required']) && $OC_submissionFieldAR['file']['required']) { // file required? if not, no error + $err .= '
  • ' . oc_('File missing') . '
  • '; + } + break; + default: + $err .= '
  • ' . oc_('File did not upload properly') . '
  • '; + break; + } + } +} + +// Check password if either field is not empty or it's an original submission +if ( (isset($_POST['password1']) && !empty($_POST['password1'])) + || (isset($_POST['password2']) && !empty($_POST['password2'])) + || ( ! isset($_POST['pid']) ) +) { + if (!isset($_POST['password1']) || !isset($_POST['password2']) || empty($_POST['password1'])) { + $err .= '
  • ' . oc_('Password must be entered twice') . '
  • '; + } elseif ($_POST['password1'] != $_POST['password2']) { + $err .= '
  • ' . oc_('Passwords entered do not match') . '
  • '; + } else { + $qfields['password'] = "'" . oc_password_hash($_POST['password1']) . "'"; + } +} + +// Add datetime to consent and strip tags +if (isset($qfields['consent']) && preg_match("/^\'.*\'$/", $qfields['consent'])) { + $qfields['consent'] = rtrim(strip_tags($qfields['consent']), "'") . safeSQLstr(" (" . gmdate('Y-m-d H:i:s') . " UTC)") . "'"; +} + +if (oc_hookSet('author-submission-validate')) { + foreach ($GLOBALS['OC_hooksAR']['author-submission-validate'] as $hook) { + require_once $hook; + } +} diff --git a/author/submission.inc b/author/submission.inc new file mode 100644 index 0000000..135d769 --- /dev/null +++ b/author/submission.inc @@ -0,0 +1,632 @@ + 0)) + ) { + $OC_submissionFieldAR['consent'] = array( + 'name' => oc_('Consent'), + 'short' => oc_('Consent'), + 'note' => '', + 'type' => 'checkbox', + 'reviewer' => false, + 'advocate' => false, + 'usekey' => false, + 'required' => true, + 'delimiter' => '', + 'values' => array(oc_('I consent to the collection and use of my personal information, including receiving emails, consistent with the Privacy Policy linked above.') . ' ' . oc_('I have also obtained the consent of all other individuals whose information I provide.')) + ); + + $OC_submissionFieldSetAR['fs_consent'] = array( + 'fieldset' => oc_('Consent'), + 'note' => '', + 'fields' => array('consent') + ); + } + + // General Info + $OC_submissionFieldAR['title'] = array( + 'name' => oc_('Submission Title'), + 'short' => oc_('Title'), + 'note' => '', + 'type' => 'text', + 'reviewer' => true, + 'advocate' => true, + 'width' => 80, + 'required' => true // always required + ); + + $OC_submissionFieldAR['type'] = array( + 'name' => oc_('Submission Type'), + 'short' => oc_('Submission Type'), + 'note' => '', + 'type' => 'radio', + 'reviewer' => true, + 'advocate' => true, + 'closeedit' => false, + 'usekey' => false, + 'required' => true, + 'display' => 'sameline', + 'valuetype' => 'custom', + 'values' => array() + ); + if (isset($OC_configAR['OC_subtypes']) && !empty($OC_configAR['OC_subtypes'])) { + $OC_submissionFieldAR['type']['values'] = explode(',', $OC_configAR['OC_subtypes']); + } + + $OC_submissionFieldAR['student'] = array( + 'name' => oc_('Student'), + 'short' => oc_('Student'), + 'note' => '', + 'type' => 'radio', + 'reviewer' => true, + 'advocate' => true, + 'closeedit' => false, + 'usekey' => true, + 'required' => true, + 'delimiter' => '   ', + 'values' => array('T' => oc_('Yes'), 'F' => oc_('No')) + ); + + $OC_submissionFieldSetAR['fs_general'] = array( + 'fieldset' => oc_('General Information'), + 'note' => '', + 'fields' => array('title', 'type', 'student') + ); + + // Authors + $OC_submissionFieldAR['orcid'] = array( + 'name' => oc_('ORCID'), + 'short' => oc_('ORCID'), + 'note' => '', + 'type' => 'text', + 'width' => 30, + 'maxchars' => 30, + 'required' => false + ); + + $OC_submissionFieldAR['honorific'] = array( + 'name' => oc_('Honorific'), + 'short' => oc_('Honorific'), + 'note' => '', + 'type' => 'text', + 'reviewer' => true, + 'advocate' => true, + 'required' => false + ); + + $OC_submissionFieldAR['name_first'] = array( + 'name' => oc_('First/Given Name'), + 'short' => oc_('First Name'), + 'note' => '', + 'type' => 'text', + 'maxchars' => 60, + 'reviewer' => true, + 'advocate' => true, + 'required' => false + ); + + $OC_submissionFieldAR['name_last'] = array( + 'name' => oc_('Last/Family Name'), + 'short' => oc_('Last Name'), + 'note' => '', + 'type' => 'text', + 'maxchars' => 40, + 'reviewer' => true, + 'advocate' => true, + 'required' => true // always required + ); + + $OC_submissionFieldAR['suffix'] = array( + 'name' => oc_('Suffix'), + 'short' => oc_('Suffix'), + 'note' => '', + 'type' => 'text', + 'maxchars' => 60, + 'reviewer' => true, + 'advocate' => true, + 'required' => false + ); + + $OC_submissionFieldAR['position_title'] = array( + 'name' => oc_('Position/Title'), + 'short' => oc_('Position'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['organization'] = array( + 'name' => oc_('Organization'), + 'short' => oc_('Organization'), + 'note' => '', + 'type' => 'text', + 'maxchars' => 150, // limitation as a result of utf8mb4 keys + 'reviewer' => true, + 'advocate' => true, + 'required' => false + ); + + $OC_submissionFieldAR['department'] = array( + 'name' => oc_('Department/Division'), + 'short' => oc_('Department/Division'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['address'] = array( + 'name' => oc_('Address'), + 'short' => oc_('Address'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['address2'] = array( + 'name' => oc_('Address 2'), + 'short' => oc_('Address 2'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['city'] = array( + 'name' => oc_('City'), + 'short' => oc_('City'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['spc'] = array( + 'name' => oc_('State/Province'), + 'short' => oc_('State/Province'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['postcode'] = array( + 'name' => oc_('Postcode/Zip'), + 'short' => oc_('Postcode/Zip'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['country'] = array( + 'name' => oc_('Country'), + 'short' => oc_('Country'), + 'note' => '', + 'type' => 'dropdown', + 'blank' => true, + 'required' => false, + 'usekey' => true, + 'reviewer' => true, + 'advocate' => true, + 'valuetype' => 'country' + ); + + $OC_submissionFieldAR['email'] = array( + 'name' => oc_('Email'), + 'short' => oc_('Email'), + 'note' => '', + 'type' => 'email', + 'required' => false // required for contact author automatically + + ); + + $OC_submissionFieldAR['phone'] = array( + 'name' => oc_('Telephone'), + 'short' => oc_('Telephone'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['url'] = array( + 'name' => oc_('Web Site'), + 'short' => oc_('Web Site'), + 'note' => '', + 'type' => 'text', + 'required' => false, + 'placeholder' => 'https://' + ); + + $OC_submissionFieldAR['facebook'] = array( + 'name' => oc_('Facebook Page'), + 'short' => oc_('Facebook'), + 'note' => '', + 'type' => 'text', + 'required' => false, + 'placeholder' => 'https://' + ); + + $OC_submissionFieldAR['twitter'] = array( + 'name' => oc_('Twitter Page'), + 'short' => oc_('Twitter'), + 'note' => '', + 'type' => 'text', + 'required' => false, + 'placeholder' => 'https://' + ); + + $OC_submissionFieldAR['linkedin'] = array( + 'name' => oc_('LinkedIn Page'), + 'short' => oc_('LinkedIn'), + 'note' => '', + 'type' => 'text', + 'required' => false, + 'placeholder' => 'https://' + ); + + $OC_submissionFieldAR['photo'] = array( + 'name' => oc_('Photo Link'), + 'short' => oc_('Photo'), + 'note' => '', + 'type' => 'text', + 'required' => false, + 'placeholder' => 'https://' + ); + + $OC_submissionFieldAR['presenter'] = array( + 'name' => oc_('Presenter'), + 'short' => oc_('Presenter'), + 'note' => '', + 'type' => 'radio', + 'usekey' => true, + 'required' => false, + 'display' => 'sameline', + 'values' => array('T' => oc_('Yes'), 'F' => oc_('No')) + ); + + $OC_submissionFieldAR['biography'] = array( + 'name' => oc_('Biography'), + 'short' => oc_('Biography'), + 'note' => '', + 'type' => 'textarea', + 'required' => false + ); + + $OC_submissionFieldAR['role'] = array( + 'name' => oc_('Contributor Role'), + 'short' => oc_('Contributor Role'), + 'note' => '', + 'type' => 'picklist', + 'usekey' => true, + 'required' => false, + 'values' => array( + 1 => oc_('Conceptualization'), + 2 => oc_('Data curation'), + 3 => oc_('Formal Analysis'), + 4 => oc_('Funding acquisition'), + 5 => oc_('Investigation'), + 6 => oc_('Methodology'), + 7 => oc_('Project administration'), + 8 => oc_('Resources'), + 9 => oc_('Software'), + 10 => oc_('Supervision'), + 11 => oc_('Validation'), + 12 => oc_('Visualization'), + 13 => oc_('Writing - original draft'), + 14 => oc_('Writing - review & editing') + ) + ); + + $OC_submissionFieldSetAR['fs_authors'] = array( + 'fieldset' => oc_('Author(s)'), + 'note' => '', + 'fields' => array('orcid', 'honorific', 'name_first', 'name_last', 'suffix', 'position_title', 'organization', 'department', 'address', 'address2', 'city', 'spc', 'postcode', 'country', 'email', 'phone', 'url', 'facebook', 'twitter', 'linkedin', 'photo', 'presenter', 'biography', 'role') + ); + + // Contact Author + $OC_submissionFieldAR['contactid'] = array( + 'name' => oc_('Contact Author'), + 'short' => oc_('Contact Author'), + 'note' => oc_('Author who will serve as the point of contact for correspondence about the submission.'), + 'type' => 'dropdown', + 'required' => true, // always required + 'usekey' => true, + 'valuetype' => 'author' + ); + + $OC_submissionFieldAR['altcontact'] = array( + 'name' => oc_('Alternate Contact'), + 'short' => oc_('Alternate Contact'), + 'note' => oc_('Alternate contact information, such as personal email address or telephone number; used only if unable to contact using above email address.'), + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldSetAR['fs_contactauthor'] = array( + 'fieldset' => oc_('Contact Author'), + 'note' => '', + 'fields' => array('contactid', 'altcontact') + ); + + // Topics + $OC_submissionFieldAR['topics'] = array( + 'name' => oc_('Topic Areas'), + 'short' => oc_('Topic(s)'), + 'note' => '', + 'type' => 'checkbox', + 'usekey' => true, + 'display' => 'newline', + 'required' => true, // always required + 'valuetype' => 'topic' + ); + if ($OC_configAR['OC_multipleSubmissionTopics'] != 1) { // (!1 = limited to 1) + $OC_submissionFieldAR['topics']['maxselections'] = 1; + } + + $OC_submissionFieldSetAR['fs_topics'] = array( + 'fieldset' => oc_('Topic Areas'), + 'note' => oc_('To help match submissions to reviewers and sessions, please select the area(s) most applicable to your submission'), + 'fields' => array('topics') + ); + + // Content + $OC_submissionFieldAR['keywords'] = array( + 'name' => oc_('Keywords'), + 'short' => oc_('Keywords'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_submissionFieldAR['abstract'] = array( + 'name' => oc_('Abstract'), + 'short' => oc_('Abstract'), + 'note' => '', + 'reviewer' => true, + 'advocate' => true, + 'type' => 'textarea', + 'height' => 10, + 'required' => false + ); + + $OC_submissionFieldSetAR['fs_content'] = array( + 'fieldset' => oc_('Content'), + 'note' => '', + 'fields' => array('keywords', 'abstract') + ); + + if ( preg_match("/submit/", $_SERVER['PHP_SELF']) || (isset($mod_oc_customforms_edit) && $mod_oc_customforms_edit) || (isset($mod_oc_formfields_edit) && $mod_oc_formfields_edit) ) { // only display file field if submission (or forms editing via module) + $OC_submissionFieldAR['file'] = array( + 'name' => oc_('File'), + 'short' => oc_('File'), + 'note' => (empty($GLOBALS['fileNotice']) ? '' : $GLOBALS['fileNotice'] . '
    ') . (empty($OC_configAR['OC_fileLimit']) ? sprintf(oc_('File size limit is %s.'), $GLOBALS['OC_maxFileSize']) : ''), + 'type' => 'file', + 'closeedit' => false, + 'required' => true + ); + $OC_submissionFieldSetAR['fs_content']['fields'][] = 'file'; + } + + // Password + $OC_submissionFieldAR['password1'] = array( + 'name' => oc_('Password'), + 'short' => oc_('Password'), + 'note' => '', + 'type' => 'password', + 'required' => true // always required + ); + + $OC_submissionFieldAR['password2'] = array( + 'name' => oc_('Re-enter Password'), + 'short' => oc_('Confirm'), + 'note' => '', + 'type' => 'password', + 'required' => true // always required + ); + + $OC_submissionFieldSetAR['fs_passwords'] = array( + 'fieldset' => oc_('Password'), + 'note' => oc_('Please enter a password you will remember. The submission ID, which you will receive via email upon submission of this form, along with this password will allow you to make future changes to this submission.'), + 'fields' => array('password1', 'password2') + ); + + // Comments + $OC_submissionFieldAR['comments'] = array( + 'name' => oc_('Optional Comments'), + 'short' => oc_('Comments'), + 'note' => '', + 'type' => 'textarea', + 'required' => false + ); + + $OC_submissionFieldSetAR['fs_comments'] = array( + 'fieldset' => oc_('Comments'), + 'note' => '', + 'fields' => array('comments') + ); + + // Unset fields that should not be displayed on form + if (!empty($GLOBALS['OC_configAR']['OC_hideSubFields'])) { + $hSF = explode(',', $GLOBALS['OC_configAR']['OC_hideSubFields']); + foreach ($hSF as $hs_f) { + list($a_fs, $a_f) = explode(':', $hs_f); + unset($OC_submissionFieldAR[$a_f]); + if (in_array($a_f, $OC_submissionFieldSetAR[$a_fs]['fields'])) { + $OC_submissionFieldSetAR[$a_fs]['fields'] = array_values(array_diff($OC_submissionFieldSetAR[$a_fs]['fields'], array($a_f))); + } + } + } + +} // if ! custom form + +// Hooks +if (oc_hookSet('author-submission-inc')) { + foreach ($GLOBALS['OC_hooksAR']['author-submission-inc'] as $v) { + require_once $v; + } +} + +// Make updates if form not being edited by module +if ( + (! isset($mod_oc_customforms_edit) || ! $mod_oc_customforms_edit) + && + (! isset($mod_oc_formfields_edit) || ! $mod_oc_formfields_edit) +){ + $GLOBALS['updateAuthorFieldsAR'] = array(); + foreach ($OC_submissionFieldAR as $sfk => $sf) { + // remove field if either: + // - designated for new submissions only if sub being edited, + // - designated for Chair only and author viewing/editing + if ( + (isset($sf['newsubonly']) && $sf['newsubonly'] && isset($GLOBALS['OC_subEdit']) && $GLOBALS['OC_subEdit']) + || + ( + (isset($sf['chair']) && $sf['chair']) + && + ( + (isset($OC_subNew) && $OC_subNew) + || + (isset($OC_subEdit) && $OC_subEdit && (!isset($chair) || !$chair)) + || + (isset($OC_subShow) && $OC_subShow) + ) + ) + ) { + unset($OC_submissionFieldAR[$sfk]); + foreach ($OC_submissionFieldSetAR as $fsid => $fsar) { + if (in_array($sfk, $fsar['fields'])) { + $OC_submissionFieldSetAR[$fsid]['fields'] = array_diff($OC_submissionFieldSetAR[$fsid]['fields'], array($sfk)); + continue; // field should only be in one fieldset + } + } + } else { // update values & valuetypes + if (isset($sf['valuetype']) && !empty($sf['valuetype']) && ($sf['valuetype'] != 'custom')) { + switch($sf['valuetype']) { + case 'author': + $OC_submissionFieldAR[$sfk]['values'] = $sfAuthorAR; + $GLOBALS['updateAuthorFieldsAR'][] = $sfk; + break; + + case 'country': + require_once OCC_COUNTRY_FILE; + $OC_submissionFieldAR[$sfk]['values'] = $GLOBALS['OC_countryAR']; + break; + + case 'topic': + $OC_submissionFieldAR[$sfk]['values'] = $topicAR; + break; + + default: // lib file + require_once OCC_LIB_DIR . $sf['valuetype'] . '.inc'; + $OC_submissionFieldAR[$sfk]['values'] = $GLOBALS['OC_' . $sf['valuetype'] . 'AR']; + break; + } + } elseif ( + isset($sf['values']) + && is_array($sf['values']) + && ( !isset($mod_oc_customforms_customSubForm) || ! $mod_oc_customforms_customSubForm ) + ) { + // Translate values + if (!isset($sf['usekey']) || $sf['usekey']) { + foreach ($sf['values'] as $vk => $vv) { + $OC_submissionFieldAR[$sfk]['values'][$vk] = oc_($vv); + } + } else { // change to usekey in support of field values translation (e.g., consent, sub type) + $OC_submissionFieldAR[$sfk]['usekey'] = true; + $valuesAR = array(); + foreach ($sf['values'] as $vv) { + $valuesAR[$vv] = oc_($vv); + } + $OC_submissionFieldAR[$sfk]['values'] = $valuesAR; + } + } + } + } + + // Update Topics to radio if required and max selections = 1 + if (isset($OC_submissionFieldAR['topics']['required']) && $OC_submissionFieldAR['topics']['required'] && isset($OC_submissionFieldAR['topics']['maxselections']) && ($OC_submissionFieldAR['topics']['maxselections'] == 1) && ($OC_submissionFieldAR['topics']['type'] == 'checkbox')){ + $OC_submissionFieldAR['topics']['type'] = 'radio'; + } + + // Remove file field if present and not making new submission + if (isset($OC_submissionFieldAR['file']) && !preg_match("/submit/", $_SERVER['PHP_SELF']) && !preg_match("/preview/", $_SERVER['QUERY_STRING'])) { + unset($OC_submissionFieldAR['file']); + foreach ($OC_submissionFieldSetAR as $fsid => $fsar) { + if (in_array('file', $fsar['fields'])) { + if (count($fsar['fields']) == 1) { + unset($OC_submissionFieldSetAR[$fsid]); + } else { + $OC_submissionFieldSetAR[$fsid]['fields'] = array_diff($OC_submissionFieldSetAR[$fsid]['fields'], array('file')); + } + break; + } + } + } + + // Set contact author field to 1 and hide it if (minDisplayAuthors=1 && maxAuthors=1) || (OC_authorOneContact=1) + if ( isset($OC_submissionFieldAR['contactid']) && $author1contact ) { + $OC_submissionFieldAR['contactid']['type'] = 'hidden'; + $_POST['contactid'] = 1; + $GLOBALS['updateAuthorFieldsAR'] = array_diff($GLOBALS['updateAuthorFieldsAR'], array('contactid')); // remove contactid field from list of fields to be updated via Add Author + } + +} + diff --git a/author/submit.php b/author/submit.php new file mode 100644 index 0000000..39f78b8 --- /dev/null +++ b/author/submit.php @@ -0,0 +1,244 @@ +' . oc_('Submissions are closed.') . '

    '; + printFooter(); + exit; +} + +// File upload settings +$uploadDir = $OC_configAR['OC_paperDir']; +$extAR = $OC_configAR['OC_extar']; +$fileNotice = ( isset($OC_configAR['OC_paperFldNote']) ? oc_($OC_configAR['OC_paperFldNote']) : '' ); +$formatDBFldName = 'format'; +$fileFldName = 'File'; + +if (oc_hookSet('author-submit-preprocess')) { + foreach ($GLOBALS['OC_hooksAR']['author-submit-preprocess'] as $hook) { + require_once $hook; + } +} + +require_once OCC_FORM_INC_FILE; +require_once OCC_SUBMISSION_INC_FILE; + +// Check whether this is a submission +if (isset($_POST['submit'])) { + $err = ''; + $errInc = ''; + $qfields = array(); // fields to insert into submission table + $afields = array(); // fields to insert into authors table + $tfields = array(); // fields to insert into topics table + $fileUploaded = false; + + require_once 'submission-validate.inc'; + + // errors? + if (!empty($err)) { + print '

    ' . oc_('Please check the following:') . '




    '; + // remove uploaded file? + if (isset($_FILES['file']['tmp_name']) && is_file($_FILES['file']['tmp_name'])) { + unlink($_FILES['file']['tmp_name']); + } + } else { + // Check that paper hasn't been submitted yet; if it has notify author and bail + $q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_PAPER . "`.`title`='" . safeSQLstr($_POST['title']) . "' AND `" . OCC_TABLE_AUTHOR . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_AUTHOR . "`.`position`=`" . OCC_TABLE_PAPER . "`.`contactid` AND `" . OCC_TABLE_AUTHOR . "`.`name_last`='" . safeSQLstr($_POST['name_last'.$_POST['contactid']]) . "'"; + $r = ocsql_query($q) or err(oc_('Unable to verify whether submission has already been made')); + if (ocsql_num_rows($r) > 0) { + print '

    ' . oc_('This submission appears to already have been made; please check your email for a confirmation. '); + if ($OC_statusAR['OC_edit_open']) { + print sprintf(oc_('You may review or edit the submission here.'), 'edit.php') . ' '; + } + print oc_('Please contact the Chair with any questions.') . '

    '; + printFooter(); + exit; + } + + $backupMsg = ''; + + // add paper + $q = "INSERT INTO `" . OCC_TABLE_PAPER . "` SET `submissiondate`='" . safeSQLstr(date("Y-m-d")) . "', `lastupdate`='" . safeSQLstr(date("Y-m-d")) . "'"; + foreach ($qfields as $qid => $qval) { + $q .= ", `" . $qid . "`=" . $qval; + } + $r = ocsql_query($q) or err(oc_('unable to process submission')); + + $backupMsg .= "$q\n\n"; + + // get paper ID + $pid = ocsql_insert_id() or err(oc_('unable to get submission ID')); + + // add authors + foreach ($afields as $qid => $qar) { + $q = "INSERT INTO `" . OCC_TABLE_AUTHOR . "` SET `paperid`=" . (int) $pid . ", `position`=" . (int) $qid; + foreach ($qar as $qqid => $qqval) { + $q .= ", `" . $qqid . "`=" . $qqval; + } + $r = ocsql_query($q) or err(oc_('unable to add one or more authors, but submission added. Please edit submission.')); + $backupMsg .= "$q\n\n"; + } + + // add topic(s) + if (!empty($tfields)) { + $q = "INSERT INTO `" . OCC_TABLE_PAPERTOPIC . "` (`paperid`,`topicid`) VALUES"; + foreach ($tfields as $t) { + $q .= " ($pid,$t),"; + } + $r = ocsql_query(rtrim($q, ',')) or err(oc_('unable to add submission topic, but submission and authors added')); + $backupMsg .= "$q\n\n"; + } + + if (!empty($OC_configAR['OC_subBackupEmail'])) { + sendEmail($OC_configAR['OC_subBackupEmail'], "Submission ID $pid SQL", $backupMsg); + } + + $formFields = oc_('Submission ID') . ": " . $pid . "\n\n" . oc_genFieldMessage($OC_submissionFieldSetAR, $OC_submissionFieldAR, $_POST); + + // confirm it + $confirmmsg = ''; + + // File Uploaded? + if ($fileUploaded) { + $fileName = $uploadDir . $pid . '.' . $_POST['format']; + if (oc_saveFile($_FILES['file']['tmp_name'], $fileName, $_POST['format'])) { + $formFields .= "\n\n" . oc_('File') . ': ' . oc_('uploaded') . "\n"; // confirm to user + // update format + $fq = "UPDATE `" . OCC_TABLE_PAPER . "` SET `" . $formatDBFldName . "`='" . safeSQLstr($_POST['format']) . "' WHERE `paperid`='" . $pid . "' LIMIT 1"; + ocsql_query($fq); // note no error check + } else { + $formFields .= "\n\n" . oc_('File') . ':' . oc_('NOT uploaded') . "\n"; // confirm to user + $confirmmsg .= '

    ' . sprintf(oc_('Your file failed to load properly. Please try uploading just the file or contact the Chair.'), 'upload.php') . '

    '; + } + } + + if (isset($OC_configAR['OC_subConfirmNotice'])) { + if (preg_match("/\<(?:p|br) ?\/?\>/", $OC_configAR['OC_subConfirmNotice'])) { // HTML? + $confirmmsg .= oc_($OC_configAR['OC_subConfirmNotice']); + } else { + $confirmmsg .= nl2br(oc_($OC_configAR['OC_subConfirmNotice'])); + } + } else { + //T: [:code:] should be left untranslated + $confirmmsg .= oc_('

    Thank you for your submission. Your submission ID number is [:sid:]. Please write this number down and include it in any communications with us.

    + +

    Below is the information submitted. We have also emailed a copy to the submission contact. If you notice any problems or do not receive the email within 24 hours, please contact us.

    + +

    [:formfields:]

    '); + } + + // Get and update notification template + // ocIgnore included so poEdit picks up (DB) template translation + //T: [:sid:] is the numeric submission ID + $ocIgnoreSubject = oc_('Submission ID [:sid:]'); + //T: [:OC_confName:] is the event name + $ocIgnoreBody = oc_('Thank you for your submission to [:OC_confName:]. Below is a copy of the information submitted for your records. + +[:fields:]'); + list($mailsubject, $mailbody) = oc_getTemplate('author-submit'); + $templateExtraAR = array( + 'sid' => $pid, + 'fields' => $formFields + ); + $mailsubject = oc_replaceVariables($mailsubject, $templateExtraAR); + $mailbody = oc_replaceVariables($mailbody, $templateExtraAR); + + if (oc_hookSet('author-submit-save')) { + foreach ($GLOBALS['OC_hooksAR']['author-submit-save'] as $hook) { + require_once $hook; + } + } + + // Set up confirmation + $confirmmsg = preg_replace("/\[:sid:\]/", $pid, $confirmmsg); + $confirmmsg = preg_replace("/\[:formfields:\]/", '
    ' . nl2br(safeHTMLstr($formFields)), $confirmmsg); + + print $confirmmsg; + + if (($OC_configAR['OC_emailAuthorRecipients'] == 1) && !empty($allemails)) { + $mailto = $allemails; + } else { + $mailto = $contactemail; + } + + sendEmail($mailto, $mailsubject, $mailbody, $OC_configAR['OC_notifyAuthorSubmit']); + + printFooter(); + + // log + oc_logit('submission', 'Submission ID ' . $pid . ' made. Title: ' . $_POST['title']); + + if (oc_hookSet('author-submit-postsave')) { + foreach ($GLOBALS['OC_hooksAR']['author-submit-postsave'] as $hook) { + require_once $hook; + } + } + + exit; + } // else no errors +} + +if (isset($OC_configAR['OC_paperSubNote']) && !empty($OC_configAR['OC_paperSubNote'])) { + print '
    ' . (preg_match("/\<(?:p|br) ?\/?\>/", oc_($OC_configAR['OC_paperSubNote'])) ? oc_($OC_configAR['OC_paperSubNote']) : nl2br(oc_($OC_configAR['OC_paperSubNote']))) . '


    '; +} + +print ' +
    + +'; + +oc_displayFieldSet($OC_submissionFieldSetAR, $OC_submissionFieldAR, $_POST); + +if (oc_hookSet('author-submit-fields')) { + foreach ($GLOBALS['OC_hooksAR']['author-submit-fields'] as $hook) { + require_once $hook; + } +} + +print ' +

    ' . oc_('Please check over your entries, making sure everything is filled out. When ready, click on the Make Submission button below once.') . '

    +
    +
    +

    ' . oc_('The confirmation email will be sent to:') . '

    +

    +
    +
    +

    + + +
    + +'; + + +printFooter(); + +?> diff --git a/author/upload.php b/author/upload.php new file mode 100644 index 0000000..379b2b3 --- /dev/null +++ b/author/upload.php @@ -0,0 +1,260 @@ +View This Submission | View All Submissions


    '; +} elseif (! $uploadOpen) { // Check that we're still open + warn(oc_('File upload is not available')); +} + +// Check whether this is a submission +if (isset($_POST['ocaction']) && ($_POST['ocaction'] == "Upload File")) { + if ($chair && !validToken('chair')) { + warn(oc_('Invalid submission')); + } + + // Check inputs + if (! isset($_POST['pid']) || ! preg_match("/^\d+$/", $_POST['pid'])) { + warn(oc_('Submission ID is invalid') . '. ' . oc_('Try again') . ''); + } elseif ( + (! $chair && (!isset($_POST['pwd']) || empty($_POST['pwd']))) + || (!isset($_FILES['file']['name']) || empty($_FILES['file']['name'])) + || (!isset($_POST['format']) || !in_array($_POST['format'], $extAR)) + ) { + warn('
    ' . oc_('Please fill in all fields.') . '
    '); + } + + // Set PID to intval in case of leading 0's + $usepid = intval($_POST['pid']); + + // Retrieve pwd, format, & contact author email + $pq = "SELECT `" . OCC_TABLE_PAPER . "`.`" . $formatDBFldName . "`, `" . OCC_TABLE_PAPER . "`.`accepted`, `" . OCC_TABLE_PAPER . "`.`password`, `" . OCC_TABLE_AUTHOR . "`.`email` FROM `" . OCC_TABLE_PAPER . "` LEFT JOIN `" . OCC_TABLE_AUTHOR . "` ON (`" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` AND `" . OCC_TABLE_PAPER . "`.`contactid`=`" . OCC_TABLE_AUTHOR . "`.`position`) WHERE `" . OCC_TABLE_PAPER . "`.`paperid`='" . $usepid . "'"; + $pr = ocsql_query($pq) or err("Unable to upload file"); + if (ocsql_num_rows($pr) != 1) { + warn(oc_('Submission ID or password entered is incorrect')); + } + $pl = ocsql_fetch_array($pr); + + // Valid pid/pwd?; check for chair pwd first to save db call + if (! $chair + && !oc_password_verify($_POST['pwd'], $pl['password']) + ) { + warn(oc_('Submission ID or password entered is incorrect')); + } + + // Was a file successfully loaded + if (!isset($_FILES['file']['error']) // bad upload + || $_FILES['file']['error'] // error + || ! is_uploaded_file($_FILES['file']['tmp_name']) // fake upload + || ($_FILES['file']['size'] <= 0) // empty file + || (!empty($OC_configAR['OC_fileLimit']) && ($_FILES['file']['size'] > ($OC_configAR['OC_fileLimit'] * 1024 * 1024))) // file size > limit + ) { + warn(sprintf(oc_('The file failed to load. Please try again. If the problem persists, contact the Chair'), $_SERVER['PHP_SELF'], $OC_configAR['OC_pcemail'])); + } + + if (oc_hookSet('author-upload-validate')) { + foreach ($GLOBALS['OC_hooksAR']['author-upload-validate'] as $hook) { + require_once $hook; + } + } + + // Delete old file? + $oldFileName = $uploadDir . $usepid . '.' . $pl[$formatDBFldName]; + oc_deleteFile($oldFileName); + + // Move new file + $err = 0; + $newFileName = $uploadDir . $usepid . '.' . $_POST['format']; + + // Check whether file uploaded + if (is_uploaded_file($_FILES['file']['tmp_name']) + && oc_saveFile($_FILES['file']['tmp_name'], $newFileName, $_POST['format']) + ) { + //T: %s = submission ID (number) + $confirmmsg = sprintf(oc_('Submission ID %s has been uploaded.'), $usepid); + + // Get and update notification template + // ocIgnore included so poEdit picks up (DB) template translation + //T: [:sid:] is the numeric submission ID + $ocIgnoreSubject = oc_('Submission ID [:sid:] file uploaded'); + //T: [:sid:] is the numeric submission ID + $ocIgnoreBody = oc_('Submission ID [:sid:] has been uploaded. + +[:error:]'); + list($mailsubject, $mailbody) = oc_getTemplate('author-upload'); + $templateExtraAR = array( + 'sid' => $usepid, + 'error' => '' + ); + + // Set lastupdate date, and format if needed + $eq = "UPDATE `" . OCC_TABLE_PAPER . "` SET `lastupdate`='" . safeSQLstr(date("Y-m-d")) . "'"; + // also update format if changed + if ($_POST['format'] != $pl[$formatDBFldName]) { + $eq .= ", `" . $formatDBFldName . "`='" . safeSQLstr($_POST['format']) . "'"; + } + $eq .= " WHERE `paperid`='" . $usepid . "'"; + if ( ! ocsql_query($eq)) { + $templateExtraAR['error'] = oc_('However, we were unable to update the format.'); + $confirmmsg .= "\n\n" . oc_('However, we were unable to update the format.'); + $err = 1; + } + + $mailsubject = oc_replaceVariables($mailsubject, $templateExtraAR); + $mailbody = oc_replaceVariables($mailbody, $templateExtraAR); + + if (oc_hookSet('author-upload-preconfirm')) { + foreach ($GLOBALS['OC_hooksAR']['author-upload-preconfirm'] as $hook) { + require_once $hook; + } + } + + // Send email confirmation + $mailto = ''; + if ( $OC_configAR['OC_emailAuthorOnUpload'] && ! $chair) { + if ($OC_configAR['OC_emailAuthorRecipients'] == 1) { + $ar = ocsql_query("SELECT `email` FROM `" . OCC_TABLE_AUTHOR . "` WHERE `paperid`='" . safeSQLstr($_POST['pid']) . "'") or err('Unable to retrieve author email addresses'); + while ($al = ocsql_fetch_assoc($ar)) { + $mailto .= $al['email'] . ','; + } + $mailto = rtrim($mailto, ','); + } + if (empty($mailto)) { + $mailto = $pl['email']; + } + } + + sendEmail($mailto, $mailsubject, $mailbody, $OC_configAR['OC_notifyAuthorUpload']); + + if (!$err) { + print $confirmmsg; + } else { + err($confirmmsg); + } + + // log + oc_logit('submission', 'Submission ID ' . $usepid . ' file upload' . (isset($_POST['oc_multifile_type']) ? (' (MultiFile Type: ' . $_POST['oc_multifile_type'] . ')') : '')); + + } else { // file failed to upload or move properly + print '' . sprintf(oc_('The file failed to load properly. Please email it directly to the Chair'), $OC_configAR['OC_pcemail'], $OC_configAR['OC_confName'], $usepid) . ''; + } + + printFooter(); + exit; +} + +print ' +
    + +'; + +if ($chair) { + print ' + + + +'; +} + +print ''; + +if (oc_hookSet('author-upload-formtop')) { + foreach ($GLOBALS['OC_hooksAR']['author-upload-formtop'] as $hook) { + require_once $hook; + } +} + +if (! $chair) { + print ' + + +'; +} else { + print ' +
    +'; +} + +print ' + +'; + +if (oc_hookSet('author-upload-formbottom')) { + foreach ($GLOBALS['OC_hooksAR']['author-upload-formbottom'] as $hook) { + require_once $hook; + } +} + +print ' +
    ( ' . oc_('forgot ID?') . ' )
    ( ' . oc_('forgot password?') . ' )
        +'; + +print '

    \n"; + +print ' +
    ' . nl2br($fileNotice) . '
    +'; + +if (empty($OC_configAR['OC_fileLimit'])) { + print '

    ' . sprintf(oc_('File size limit is %s.'), $OC_maxFileSize) . '

    '; +} + +print ' +
    +

    +

    +
    +

    +'; + +if (oc_hookSet('author-upload-bottom')) { + foreach ($GLOBALS['OC_hooksAR']['author-upload-bottom'] as $hook) { + require_once $hook; + } +} + +printFooter(); + +?> diff --git a/author/view.inc b/author/view.inc new file mode 100644 index 0000000..090f01a --- /dev/null +++ b/author/view.inc @@ -0,0 +1,63 @@ + $aval) { + if (preg_match("/^(?:paperid|position)$/", $akey)) { continue; } + $spl[$akey . $apos] = $aval; + } +} +$oc_authorNum = $apos; + +// Get topics +$qt = "SELECT `topicid` FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `paperid`='" . safeSQLstr($pid) . "'"; +$rt = ocsql_query($qt) or err(oc_('Unable to retrieve topic(s) information')); +$spl['topics'] = array(); +while ($t = ocsql_fetch_array($rt)) { + $spl['topics'][] = $t['topicid']; +} + +require_once OCC_FORM_INC_FILE; +require_once OCC_SUBMISSION_INC_FILE; + +print ' + + +'; + +oc_showFieldSet($OC_submissionFieldSetAR, $OC_submissionFieldAR, $spl); + +if (oc_hookSet('author-show_paper')) { + foreach ($GLOBALS['OC_hooksAR']['author-show_paper'] as $hook) { + require_once $hook; + } +} + +print '
    ' . safeHTMLstr(oc_('Submission ID')) . ':' . safeHTMLstr($pid) . '
    '; + +?> diff --git a/author/withdraw.php b/author/withdraw.php new file mode 100644 index 0000000..b56ff1b --- /dev/null +++ b/author/withdraw.php @@ -0,0 +1,119 @@ +' . oc_('Submission withdraw is not available.') . '

    '; + printFooter(); + exit; +} + +// Is this a post? +if (isset($_POST['ocaction']) && ($_POST['ocaction'] == 'Withdraw Submission')) { + // Check for paper ID & password + if (! isset($_POST['pid']) || + ! preg_match("/^\d+$/", $_POST['pid']) || + ! isset($_POST['pwd']) || + empty($_POST['pwd']) + ) { + warn(oc_('Submission ID or password entered is incorrect')); + printFooter(); + exit; + } + + $pq = "SELECT `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_PAPER . "`.`password`, `" . OCC_TABLE_AUTHOR . "`.`email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_PAPER . "`.`paperid`='" . safeSQLstr($_POST['pid']) . "' AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` AND `" . OCC_TABLE_PAPER . "`.`contactid`=`" . OCC_TABLE_AUTHOR . "`.`position`"; + $pr = ocsql_query($pq) or err("Unable to retrieve submission"); + if (ocsql_num_rows($pr) != 1) { + warn(oc_('Submission ID or password entered is incorrect')); + printFooter(); + exit; + } + $pl = ocsql_fetch_array($pr); + if (!oc_password_verify($_POST['pwd'], $pl['password'])) { + warn(oc_('Submission ID or password entered is incorrect')); + printFooter(); + exit; + } + + // Withdraw submission + if (withdrawPaper($_POST['pid'], OCC_WORD_AUTHOR)) { + $mailto = ''; + if ($OC_configAR['OC_emailAuthorRecipients'] == 1) { + $ar = ocsql_query("SELECT `email` FROM `" . OCC_TABLE_AUTHOR . "` WHERE `paperid`='" . safeSQLstr($_POST['pid']) . "'") or err('Unable to retrieve author email addresses'); + while ($al = ocsql_fetch_assoc($ar)) { + $mailto .= $al['email'] . ','; + } + $mailto = rtrim($mailto, ','); + } + + deletePaper($_POST['pid'], false); + print '

    ' . oc_('Your submission has been withdrawn. If this is not what you intended to do, please contact the Chair.') . '

    '; + // Notify via email + // ocIgnore included so poEdit picks up (DB) template translation + //T: [:sid:] is the numeric submission ID + $ocIgnoreSubject = oc_('Submission Withdraw - ID [:sid:]'); + $ocIgnoreBody = oc_('The submission below has been withdrawn at the author\'s request. If you did not intend to withdraw the submission, please reply back. + +[:submission:]'); + list($mailsubject, $mailbody) = oc_getTemplate('author-withdraw'); + $templateExtraAR = array( + 'sid' => $_POST['pid'], + 'submission' => oc_('Submission ID') . ': ' . $_POST['pid'] . "\n" . oc_('Title') . ': ' . $pl['title'] + ); + $mailsubject = oc_replaceVariables($mailsubject, $templateExtraAR); + $mailbody = oc_replaceVariables($mailbody, $templateExtraAR); + + if (empty($mailto)) { + $mailto = $pl['email']; + } + sendEmail($mailto, $mailsubject, $mailbody, $OC_configAR['OC_notifyAuthorWithdraw']); + } else { + print '

    ' . oc_('We encountered a problem withdrawing your submission. Please contact the Chair.') . '

    '; + } + + printFooter(); + exit; +} // if submit + +// display sub id/password form +print ' +
    + + + + +
    : ( ' . oc_('forgot ID?') . ' )
    : ( ' . oc_('forgot password?') . ' )
    +

    ' . oc_('Clicking the button below will result in your submission being withdrawn.') . '

    +

    +
    + +'; + +if (oc_hookSet('author-withdraw-bottom')) { + foreach ($GLOBALS['OC_hooksAR']['author-withdraw-bottom'] as $hook) { + require_once $hook; + } +} + +printFooter(); + +exit; + +?> diff --git a/chair/assign_advocates.php b/chair/assign_advocates.php new file mode 100644 index 0000000..cddec0d --- /dev/null +++ b/chair/assign_advocates.php @@ -0,0 +1,318 @@ +Please go back and select at least one submission and one advocate

    '; + } else { + // Get conflicts? + if ($OC_configAR['OC_allowConflictOverride'] && isset($_POST['conflict_override']) && ($_POST['conflict_override'] == 1)) { + $conflictAR = array(); + } else { + $conflictAR = getConflicts(); + } + // Assign advocates (and reviewers?) + // NOTE: Although a foreach is used below for future expansion, there should only be 1 advocate + $advocateAssignmentAR = array(); // keep track of advocates w/successful assignments + $submissionAssignmentAR = array(); // keep track of submissions assigned + foreach ($_POST['advocates'] as $i) { + if (!is_numeric($i)) { err('Invalid advocate ID: ' . safeHTMLstr($i)); } + foreach ($_POST['papers'] as $j) { + if (!is_numeric($j)) { err('Invalid submission ID: ' . safeHTMLstr($j)); } + // Check for conflict + if (in_array("$j-$i",$conflictAR)) { + print "

    ! Submission $j is in conflict with advocate $i.

    \n"; + continue; + } + // Delete current assignment? + if (isset($_POST['assignment_override']) && ($_POST['assignment_override'] == 1)) { + oc_deleteAssignments($j, null, 'advocate'); + } + // Make assignment + $q = "INSERT INTO `" . OCC_TABLE_PAPERADVOCATE . "` (`paperid`,`advocateid`) VALUES ('" . safeSQLstr($j) . "','" . safeSQLstr($i) . "')"; + ocsql_query($q); + if (($merr = ocsql_errno()) != 0) { + if ($merr == 1062) { // Duplicate entry + print "

    ! Submission $j already has an advocate assigned. Please delete the existing advocate first before assigning a new one, or select Override Current Assingment.

    \n"; + } else { + print "

    !! Error assigning submission $j to advocate $i

    \n"; + } + } else { + print "

    Submission $j assigned to advocate $i.\n"; + if (!isset($advocateAssignmentAR[$i])) { + $advocateAssignmentAR[$i] = array(); + } + $advocateAssignmentAR[$i][] = $j; + if (!in_array($j, $submissionAssignmentAR)) { + $submissionAssignmentAR[] = $j; + } + // Also assign a reviewer? + if (isset($_POST['asrev']) && ($_POST['asrev'] == "yes")) { + $q = "INSERT INTO `" . OCC_TABLE_PAPERREVIEWER . "` (`paperid`,`reviewerid`,`assigned`) VALUES ('" . safeSQLstr($j) . "','" . safeSQLstr($i) . "','" . safeSQLstr(date('Y-m-d')) . "')"; + ocsql_query($q); + if (($merr = ocsql_errno()) != 0) { + if ($merr == 1062) { // Duplicate entry + print "

    ! Submission $j has already been assigned reviewer $i.

    \n"; + } else { + print "

    !! Error assigning submission $j to reviewer $i

    \n"; + } + } + } + } + } + } + + print '


    '; + + // Notify? + if ( isset($_POST['notify']) && ($_POST['notify'] == 1) && (count($advocateAssignmentAR) > 0) ) { + // Get list of sub titles + $r = ocsql_query("SELECT `paperid`, `title` FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid` IN (" . implode(',',$submissionAssignmentAR) . ")") or err('Unable to retrieve submission titles for notification'); + $submissionTitleAR = array(); + while ($l = ocsql_fetch_assoc($r)) { + $submissionTitleAR[$l['paperid']] = $l['paperid'] . '. ' . $l['title']; + } + + // Get advocates to notify + $q = "SELECT `reviewerid`, `name_first`, `name_last`, CONCAT_WS(' ', `name_first`, `name_last`) AS `name`, `email`, `username` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `reviewerid` IN (" . implode(',', array_keys($advocateAssignmentAR)) . ")"; + $r = ocsql_query($q) or err('Unable not get advocate email address(es) for notification'); + + // Get notification template + // ocIgnore included so poEdit picks up (DB) template translation + $ocIgnoreSubject = oc_('New Advocate Assignment(s)'); + //T: [:OC_confName:] is the event name + $ocIgnoreBody = oc_('New assignments have been made for you to advocate in the [:OC_confName:] OpenConf system: + + +[:assignments:] + +Thank you.'); + list($subject, $message) = oc_getTemplate('chair-assign_advocates'); + + // Hook + if (oc_hookSet('chair-assign-advocate-notify')) { + foreach ($OC_hooksAR['chair-assign-advocate-notify'] as $f) { + require_once $f; + } + } + + // Iterate through advocates + while ($l = ocsql_fetch_assoc($r)) { + $templateExtraAR = $l; + $templateExtraAR['assignments'] = ''; + $templateExtraAR['advocateid'] = $l['reviewerid']; + foreach ($advocateAssignmentAR[$l['reviewerid']] as $sid) { + $templateExtraAR['assignments'] .= $submissionTitleAR[$sid] . "\n\n"; + } + $tmpsubject = oc_replaceVariables($subject, $templateExtraAR); + $tmpmessage = oc_replaceVariables($message, $templateExtraAR); + if (sendEmail($l['email'], $tmpsubject, $tmpmessage)) { + print '

    Notification sent to ' . safeHTMLstr($l['name']) . ' (' . safeHTMLstr($l['reviewerid']) . ')

    '; + } else { + print '

    !! Unable to email notification to ' . safeHTMLstr($l['name']) . ' (' . safeHTMLstr($l['reviewerid']) . ')

    '; + } + } + print '


    '; + } + } + + print ' +

    » Make additional assignments

    +

    » View/Edit assignments

    +

    » Manage conflicts

    +'; + +} else { + $pq = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid` FROM `" . OCC_TABLE_PAPER . "` LEFT JOIN `" . OCC_TABLE_PAPERADVOCATE . "` ON `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERADVOCATE . "`.`paperid` ORDER BY `" . OCC_TABLE_PAPER . "`.`paperid`"; + $pr = ocsql_query($pq) or err("Unable to get submissions"); + // Get pad size for paper id's - yes, we really need the max id, but this should do:) + $psize = oc_strlen((string) ocsql_num_rows($pr)); + if (ocsql_num_rows($pr) == 0) { + print 'No submissions have been made yet

    '; + } else { + if (!isset($_GET['s']) || ($_GET['s'] == "id")) { + $idsortstr = 'ID'; + $nsortstr = 'Name'; + $rsortstr = 'No. Submission'; + $legend = "[ Advocate ID - $nsortstr ($rsortstr) ]"; + $sortby = "`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + } elseif ($_GET['s'] == "reviews") { + $rsortstr = 'No. Reviews'; + $idsortstr = 'ID'; + $nsortstr = 'Name'; + $legend = "[ No. Submissions - Advocate $nsortstr - $idsortstr ]"; + $sortby = "`acount`, `" . OCC_TABLE_REVIEWER . "`.`name_last`, `" . OCC_TABLE_REVIEWER . "`.`name_first`"; + } else { + $idsortstr = 'ID'; + $nsortstr = 'Name'; + $rsortstr = 'No. Submissions'; + $legend = "[ Advocate Name - $idsortstr ($rsortstr) ]"; + $sortby = "`" . OCC_TABLE_REVIEWER . "`.`name_last`, `" . OCC_TABLE_REVIEWER . "`.`name_first`"; + } + $rq = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, count(`" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`) AS `acount` FROM `" . OCC_TABLE_REVIEWER . "` LEFT JOIN `" . OCC_TABLE_PAPERADVOCATE . "` ON `" . OCC_TABLE_REVIEWER . "`.`reviewerid`=`" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid` WHERE `" . OCC_TABLE_REVIEWER . "`.`onprogramcommittee`='T' GROUP BY `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `name` ORDER BY $sortby"; + $rr = ocsql_query($rq) or err("Unable to get program committee members"); + // Get pad size for advocate id's - yes, we really need the max id, but this should do:) + $rsize = oc_strlen((string) ocsql_num_rows($rr)); + if (ocsql_num_rows($rr) == 0) { + print 'No program committee members have signed up yet

    '; + } else { + // display filter? + $subSort = false; + $revSort = false; + $subFilterAR = array(); + $revFilterAR = array(); + if (count($topicsAR) > 1) { + print ' +

    +
    +     +
    +
    +'; + if (!empty($topicfilter)) { + if ($srfilter != 'Advocates') { + $subSort = true; + $r = ocsql_query("SELECT `paperid` FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `topicid`='" . safeSQLstr($topicfilter) . "'") or err('Unable to filter submissions by topic'); + while ($l = ocsql_fetch_assoc($r)) { + $subFilterAR[] = $l['paperid']; + } + } + if ($srfilter != 'Submissions') { + $revSort = true; + $r = ocsql_query("SELECT `reviewerid` FROM `" . OCC_TABLE_REVIEWERTOPIC . "` WHERE `topicid`='" . safeSQLstr($topicfilter) . "'") or err('Unable to filter reviewers by topic'); + while ($l = ocsql_fetch_assoc($r)) { + $revFilterAR[] = $l['reviewerid']; + } + } + } + } + + // display assignment form + print ' +
    + +
    +

    Select Submission(s):

    +

    [ Submission ID - Title (Advocate ID or ***) ]

    + +
    +
    +

    Select Advocate:   (one per submission)
    +

    ' . $legend . '

    + +
    +Tip: Click the ID, Name, or Submission links
    above to re-sort this list (page will reload)
    +
    +
    + +

    Options:

    +

    – check box to also assign advocate as reviewer of submission

    +

    – check box to change advocate if one already assigned

    +'; + if ($OC_configAR['OC_allowConflictOverride']) { + print '

    – check box to make assignments even if there is a conflict

    '; + } + print ' +

    – check box to notify advocate(s) that new assignments have been made

    +
    +

    +
    +'; + } + } +} + +printFooter(); + +?> diff --git a/chair/assign_auto_advocates.php b/chair/assign_auto_advocates.php new file mode 100644 index 0000000..9db9fcf --- /dev/null +++ b/chair/assign_auto_advocates.php @@ -0,0 +1,359 @@ + 'Weighted Topic Match', + 'description' => 'Assigns based on number of topic matches (high to low) between submissions and reviewers, giving assignment precedence to submissions with the least number of overall matching reviewer/topic pairings', + 'include' => 'assign_auto_advocates_weighted_topic_match.inc' + ), + array( + 'algorithm' => 'Topic Match', + 'description' => 'Assigns based on number of topic matches (high to low) between submissions and reviewers', + 'include' => 'assign_auto_advocates_topic_match.inc' + ), +); + +function oc_skipSubAssignment($sid) { + $skip = false; + + // skip if accepted + if (isset($_POST['skipaccepted']) && ($_POST['skipaccepted'] == 'Yes') && isset($GLOBALS['pInfoAR'][$sid]['accepted']) && !empty($GLOBALS['pInfoAR'][$sid]['accepted'])) { + $skip = true; + } + //skip if not of the selected type + if (isset($_POST['limittype']) && !empty($_POST['limittype']) && isset($GLOBALS['pInfoAR'][$sid]['type']) && ($_POST['limittype'] != $GLOBALS['pInfoAR'][$sid]['type'])) { + $skip = true; + } + + return($skip); +} + +// Check for addt'l (hook) algorithms +if (oc_hookSet('assign_auto_advocates-algorithm')) { + foreach ($OC_hooksAR['assign_auto_advocates-algorithm'] as $k => $v) { + $OC_algorithmAR[] = $v; + } +} + +// Submit - Commit assignments to database? +if (isset($_POST['submit']) && ($_POST['submit'] == "Make Assignments")) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + if (!isset($_SESSION['OPENCONFCHAIRVARS']['aAssignments'])) { + err("No advocates set"); + } + + // Keep or delete current assignments + $currAR = array(); + if ($_POST['keep'] == 'Yes') { + $aq = "SELECT `paperid`, `advocateid` FROM `" . OCC_TABLE_PAPERADVOCATE . "`"; + $ar = ocsql_query($aq) or err("Unable to access database"); + while ($al = ocsql_fetch_array($ar)) { + $currAR[] = $al['paperid'] . '-' . $al['advocateid']; + } + } else { + oc_deleteAssignments(null, null, 'advocate'); + } + + // Add advocates + foreach ($_SESSION['OPENCONFCHAIRVARS']['aAssignments'] as $pid => $aid) { + if (!$aid || in_array($pid . '-' . $aid, $currAR)) { continue; } + $q = "INSERT INTO `" . OCC_TABLE_PAPERADVOCATE . "` (`paperid`,`advocateid`) VALUES ('" . safeSQLstr($pid) . "','" . safeSQLstr($aid) . "')"; + issueSQL($q); + } + + // Okey Dokey + print '

    Assignments have been made

    +

    List Advocates

    + '; + unset($_SESSION['OPENCONFCHAIRVARS']['aAssignments']); + + printFooter(); + exit; +} + +// Check whether any reviewers or advocates assigned yet +$aq = "SELECT `paperid`, `advocateid` FROM `" . OCC_TABLE_PAPERADVOCATE . "`"; +$ar = ocsql_query($aq) or err("Unable to access database"); +$patot = ocsql_num_rows($ar); +$q = "SELECT count(*) as `rtot` FROM `" . OCC_TABLE_PAPERREVIEWER . "`"; +$r = ocsql_query($q) or err("Unable to access database"); +$rl = ocsql_fetch_array($r); +if (($patot > 0) || ($rl['rtot'] > 0)) { + print '

    Advocates or Reviewers appear to have already been assigned. Existing advocate assignments will be deleted unless you choose Yes to Keep Existing Assignments below.

    '; + $confirmOverride = true; +} else { + $confirmOverride = false; +} + +// Get number of papers and initialize paper count array +$pAR = array(); // paper advocate array +$pInfoAR = array(); // paper info array +$q = "SELECT `paperid`, `title`, `accepted`, `type` FROM `" . OCC_TABLE_PAPER . "` ORDER BY `paperid`"; +$r = ocsql_query($q) or err("Unable to get papers"); +if (($ptot = ocsql_num_rows($r)) == 0) { + warn('No submissions have been made yet.'); +} +while ($l=ocsql_fetch_array($r)) { + $pAR[$l['paperid']] = ""; + $pInfoAR[$l['paperid']] = array( + 'title' => $l['title'], + 'accepted' => $l['accepted'], + 'type' => $l['type'] + ); +} + +// Get number of advocates and initialize advocate count array +$aNameAR = array(); // advocate name array +$aAR = array(); // advocate papers array +$q = "SELECT `reviewerid`, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `onprogramcommittee`='T' ORDER BY `reviewerid`"; +$r = ocsql_query($q) or err("Unable to get advocates"); +if (($atot = ocsql_num_rows($r)) == 0) { + warn('No program committee members have signed up yet.'); +} +while ($l=ocsql_fetch_array($r)) { + $aAR[$l['reviewerid']] = array(); + $aNameAR[$l['reviewerid']] = $l['name']; +} + +// Get conflicts +$nAR = getConflicts(); + +// Calculate max # of papers each advocate should advocate (pronunciation test) +if (isset($_POST['ppa']) && preg_match("/^\d+$/",$_POST['ppa'])) { + $papersPerAdvocate = $_POST['ppa']; +} else { + $papersPerAdvocate = ceil($ptot/$atot); # +count($nAR) to $ptot ? +} + +// Set min # of papers each advocate should be assigned +if (isset($_POST['ppat']) && preg_match("/^\d+$/",$_POST['ppat'])) { + $ppaThreshold = $_POST['ppat']; +} else { + $ppaThreshold = floor($papersPerAdvocate/2); +} + +// Keep assignments already made? +if (!isset($_POST['keep']) || ($_POST['keep'] == 'Yes')) { + $confirmOverride = false; + if ($patot > 0) { + while ($al = ocsql_fetch_array($ar)) { + $pAR[$al['paperid']] = $al['advocateid']; + array_push($aAR[$al['advocateid']],$al['paperid']); + } + } +} + +// Get list of sub. types +$OC_activeSubTypeAR = array(); +$typer = ocsql_query("SELECT DISTINCT `type` FROM `" . OCC_TABLE_PAPER . "` WHERE `type` IS NOT NULL AND `type`!='' ORDER BY `type`") or err('Unable to retrieve submission types'); +while ($typel = ocsql_fetch_assoc($typer)) { + $OC_activeSubTypeAR[$typel['type']] = substr($typel['type'], 0, 50); +} + +// Algorithm to use +if (isset($_POST['algo']) && ctype_digit($_POST['algo'])) { + $algo = $_POST['algo']; +} else { + $algo = 0; // default to first defined algorithm above +} +// Run algo +if (isset($OC_algorithmAR[$algo]['include']) && is_file($OC_algorithmAR[$algo]['include'])) { + require_once $OC_algorithmAR[$algo]['include']; +} else { + err("Algorithm choice unknown"); + exit; +} + +// Remedy missing advocates by assigning advocates w/lowest #s (if set) +if (isset($_POST['remedy']) && in_array("random",$_POST['remedy'])) { + foreach (array_keys($pAR) as $k) { + if (oc_skipSubAssignment($k)) { + continue; + } + if (empty($pAR[$k])) { + // Create an ordered array of advocates w/least # of reviews + $acountAR = array(); + foreach (array_keys($aAR) as $k2) { + $acountAR[$k2] = count($aAR[$k2]); + } + asort($acountAR); + reset($acountAR); + // Assign advocate + while (key($acountAR) && empty($pAR[$k])) { + // check for no conflict + if (!in_array($k.'-'.key($acountAR),$nAR)) { + $pAR[$k] = key($acountAR); + array_push($aAR[key($acountAR)],$k); + } + next($acountAR); + } + } + } +} + + + +// Remember assignments +$_SESSION['OPENCONFCHAIRVARS']['aAssignments'] = $pAR; + +// Display form +print ' +

    Below you will find OpenConf\'s suggested advocate assignments. You may fine tune these automated assignments by changing the following options and clicking Re-Evaluate Assignments. Once you are satisfied, click the Make Assignments button to commit them to the database. You may manually add/delete advocates afterwards through the Assign Advocates Manually and List/Unassign Advocates menus.'; + +if (oc_moduleValid('oc_auto_assign')) { + print ' If instead of using this feature you would like assignments to be made automatically when a new submission is made, use the Auto Assign module.'; +} + +print '

    + +
    + + + + + + + + + + + +'; + +if (count($OC_activeSubTypeAR) > 1) { + print ' + +'; +} + +$algoOptions = ''; +foreach ($OC_algorithmAR as $k => $v) { + $algoOptions .= '
    '; +} +$algoOptions = preg_replace("/(value=\"" . $algo . "\")/","$1 checked", $algoOptions); + +print ''; + +$remStr = ''; +if (isset($_POST['remedy'])) { + foreach ($_POST['remedy'] as $rs) { + if (preg_match("/^\w+$/", $rs)) { + $remStr = preg_replace("/(value=\"" . preg_quote($rs, '/') . "\")/", "$1 checked", $remStr); + } + } +} + +print $remStr . ' + +
    Total Submissions:' . $ptot . '
    Total Advocates:' . $atot . '
    Advocate/Submission Pairings in Conflict:' . count($nAR) . '  (manage)
    Maximum Submissions per Advocate:
    Highlight if Submissions per Advocate < =
    Keep Existing Assignments?' . generateRadioOptions('keep', $yesNoAR, varValue('keep', $_POST, 'Yes'), 0) . '
    Skip Accepted/Rejected Submissions?' . generateRadioOptions('skipaccepted', $yesNoAR, varValue('skipaccepted', $_POST, 'Yes'), 0) . '
    Assign submissions of type:
    Algorithm:' . $algoOptions . '
    Remedy Missing Assignments by:

    (commits assingments to database)

    +
    +


    + +'; + +function fmtNumSpacing ($n,$dir="l") { + $sp = ""; + if ($n < 10) { $sp = " "; } + elseif ($n < 100) { $sp = " "; } + if ($dir=="l") { return($sp.$n); } + else { return($n.$sp); } +} + +function fmtStrSpacing ($str,$len) { + $a = substr($str,0,$len); + for ($i=oc_strlen($a); $i<$len; $i++) { + $a .= " "; + } + return $a; +} + +print ' + + + +
    Suggested Assignments' . ((!isset($_POST['keep']) || ($_POST['keep'] == 'Yes')) ? '

    including already assigned

    ' : '') . '
    + *  Unable to assign advocate
    +
    +Click title for submission info (new window)
    +
    +
    +Submission ID (Title) (Advocate)
    +';
    +foreach ($pAR as $k => $v) {
    +	$tmpStr = fmtNumSpacing($k).' (' . safeHTMLstr(fmtStrSpacing($pInfoAR[$k]['title'], 20)) . ") (";
    +	if (!empty($v)) { 
    +		$tmpStr .= safeHTMLstr(fmtStrSpacing($pAR[$k] . "-" . $aNameAR[$pAR[$k]],15)); 
    +		print $tmpStr.")\n";
    +	}
    +	else { 
    +		$tmpStr .= fmtStrSpacing("",15); 
    +		print '' . $tmpStr . ") *\n";
    +	}
    +}
    +
    +
    +print '
    +
           
    + *  below threshold
    +
    +Click name for reviewer info (new window)
    +Place cursor on No. Submissions for assignments
    +
    +No. Submissions per Advocate ID (Name)
    +';
    +
    +foreach ($aAR as $k => $v) {
    +	$titleStr = "Submissions for Advocate $k - " . $aNameAR[$k] . ":\n\n";
    +	foreach ($v as $vv) { $titleStr .= "$vv - ". safeHTMLstr(substr($pInfoAR[$vv]['title'],0,40))."\n"; }
    +	$tmpStr = '' . fmtNumSpacing(count($v)) . " - " . fmtNumSpacing($k) . '' . safeHTMLstr($titleStr) . ' (' . safeHTMLstr(fmtStrSpacing($aNameAR[$k],25)).")";
    +	if (count($v) <= $ppaThreshold) { print ''.$tmpStr." *\n"; }
    +	else { print $tmpStr . "\n"; }
    +}
    +
    +print '
    +
    + + +'; + +printFooter(); + +?> diff --git a/chair/assign_auto_advocates_topic_match.inc b/chair/assign_auto_advocates_topic_match.inc new file mode 100644 index 0000000..3486fb9 --- /dev/null +++ b/chair/assign_auto_advocates_topic_match.inc @@ -0,0 +1,33 @@ + 0) && isset($topicReviewerAR[$t]) && (count($topicReviewerAR[$t] > 0))) { + $topicScoreAR[$t] = count($topicReviewerAR[$t]) / $topPAR[$t]; + } + else $topicScoreAR[$t] = 0; + } + + // Calculate paper scores + foreach ($paperTopicAR as $paperid => $topiclist) { + $score = 0; + foreach ($topiclist as $topicid) { + $score += $topicScoreAR[$topicid]; + } + $paperScoreAR[$paperid] = $score; + } + asort($paperScoreAR); + + // Calculate advocate scores + foreach ($reviewerTopicAR as $reviewerid => $topiclist) { + $score = 0; + foreach ($topiclist as $topicid) { + $score += $topicScoreAR[$topicid]; + } + $reviewerScoreAR[$reviewerid] = $score; + } + asort($reviewerScoreAR); + + // Iterate through papers (score low to high) assigning + // advocates in order of their score + + foreach (array_keys($paperScoreAR) as $paperid) { + // Skip if paper already has advocate + if (!empty($pAR[$paperid])) { continue; } + // Skip submission (e.g., accepted subs) + if (oc_skipSubAssignment($paperid)) { + continue; + } + // Create a list of advocates for paper incl. scores + $Rs = array(); + if (isset($paperTopicAR[$paperid])) { + foreach($paperTopicAR[$paperid] as $topicid) { + if (isset($topicReviewerAR[$topicid])) { // may not have a reviewer for every topic + foreach ($topicReviewerAR[$topicid] as $reviewerid) { + if (!in_array($paperid."-".$reviewerid,$nAR) // advocate not in conflict + && (count($aAR[$reviewerid]) < $ppa) ) // not enough papers yet + { + $Rs[$reviewerid] = $reviewerScoreAR[$reviewerid]; + } + } + } + } + } + // Assign advocate based on reviewer score high->low + if (count($Rs) > 0) { + if ($sortorder=="1") { arsort($Rs); } + else { asort($Rs); } + reset($Rs); + $pAR[$paperid] = key($Rs); + array_push($aAR[key($Rs)],$paperid); + } + } +} + +oc_algoAdvocateWeightedTopicMatch($papersPerAdvocate,1); diff --git a/chair/assign_auto_reviewers.php b/chair/assign_auto_reviewers.php new file mode 100644 index 0000000..bc24f9b --- /dev/null +++ b/chair/assign_auto_reviewers.php @@ -0,0 +1,521 @@ + $GLOBALS['pAR'], + 'nAR' => $GLOBALS['nAR'], + 'rAR' => $GLOBALS['rAR'], + 'pInfoAR' => $GLOBALS['pInfoAR'], + 'ptot' => $GLOBALS['ptot'], + 'rNameAR' => $GLOBALS['rNameAR'], + 'pcAR' => $GLOBALS['pcAR'], + 'rtot' => $GLOBALS['rtot'], + 'reviewersPerPaper' => $GLOBALS['reviewersPerPaper'], + 'papersPerReviewer' => $GLOBALS['papersPerReviewer'], + 'pprThreshold' => $GLOBALS['pprThreshold'], + 'algo' => $GLOBALS['algo'], + 'continueFrom' => (isset($GLOBALS['continueVal']) ? $GLOBALS['continueVal'] : 0), + 'POST' => array( + 'remedy' => (isset($_POST['remedy']) ? $_POST['remedy'] : array()), + 'keep' => (isset($_POST['keep']) ? $_POST['keep'] : ''), + 'skipaccepted' => (isset($_POST['skipaccepted']) ? $_POST['skipaccepted'] : ''), + 'limittype' => (isset($_POST['limittype']) ? $_POST['limittype'] : ''), + 'pcrev' => (isset($_POST['pcrev']) ? $_POST['pcrev'] : ''), + 'advrev' => (isset($_POST['advrev']) ? $_POST['advrev'] : ''), + 'rpp' => (isset($_POST['rpp']) ? $_POST['rpp'] : ''), + 'ppr' => (isset($_POST['ppr']) ? $_POST['ppr'] : ''), + 'pprt' => (isset($_POST['pprt']) ? $_POST['pprt'] : ''), + 'ppa' => (isset($_POST['ppa']) ? $_POST['ppa'] : ''), + 'algo' => (isset($_POST['algo']) ? $_POST['algo'] : '') + ) + ); + if (isset($GLOBALS['continueAR'])) { + foreach ($GLOBALS['continueAR'] as $k) { + $_SESSION['OPENCONFCHAIRVARS']['timeoutAR'][$k] = $GLOBALS[$k]; + } + } + session_write_close(); + header("Location: " . $_SERVER['PHP_SELF'] . "?timeout=1"); + ob_clean(); + exit; +} + +ob_start(); + +printHeader("Auto Assign Reviewers", 1); + +// Init algorithm array +$OC_algorithmAR = array( + array( + 'algorithm' => 'Weighted Topic Match', + 'description' => 'Assigns based on number of topic matches (high to low) between submissions and reviewers, giving assignment precedence to submissions with the least number of overall matching reviewer/topic pairings', + 'include' => 'assign_auto_reviewers_weighted_topic_match.inc' + ), + array( + 'algorithm' => 'Topic Match', + 'description' => 'Assigns based on number of topic matches (high to low) between submissions and reviewers', + 'include' => 'assign_auto_reviewers_topic_match.inc' + ), +); + +// Check for addt'l (hook) algorithms +if (oc_hookSet('assign_auto_reviewers-algorithm')) { + foreach ($OC_hooksAR['assign_auto_reviewers-algorithm'] as $k => $v) { + $OC_algorithmAR[] = $v; + } +} + +// Submit - Commit assignments to database? +if (isset($_POST['submit']) && ($_POST['submit'] == "Make Assignments")) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + if (!isset($_SESSION['OPENCONFCHAIRVARS']['pAssignments'])) { + err("No reviewers set"); + } + + // Keep or delete current assignments? + $currAR = array(); + if ($_POST['keep'] == 'Yes') { + $prq = "SELECT `paperid`, `reviewerid` FROM `" . OCC_TABLE_PAPERREVIEWER . "`"; + $prr = ocsql_query($prq) or err("Unable to access database"); + while ($prl = ocsql_fetch_array($prr)) { + $currAR[] = $prl['paperid'] . '-' . $prl['reviewerid']; + } + } else { + oc_deleteAssignments(null, null); + } + + // Add reviewers + foreach ($_SESSION['OPENCONFCHAIRVARS']['pAssignments'] as $pid => $rids) { + foreach ($rids as $rid) { + if (!$rid || in_array($pid . '-' . $rid, $currAR)) { continue; } + $q = "INSERT INTO `" . OCC_TABLE_PAPERREVIEWER . "` (`paperid`,`reviewerid`,`assigned`) VALUES ('" . safeSQLstr($pid) . "','" . safeSQLstr($rid) . "','" . safeSQLstr(date('Y-m-d')) . "')"; + issueSQL($q); + } + } + + // Okey Dokey + print '

    Assignments have been made

    +

    List Reviews

    + '; + unset($_SESSION['OPENCONFCHAIRVARS']['pAssignments']); + + printFooter(); + exit; +} + +// Check whether any reviews assigned yet +$prq = "SELECT `paperid`, `reviewerid` FROM `" . OCC_TABLE_PAPERREVIEWER . "`"; +$prr = ocsql_query($prq) or err("Unable to access database"); +$prtot = ocsql_num_rows($prr); +if ($prtot > 0) { + print '

    Reviews appear to have already been assigned. Existing reviews will be deleted unless you choose Yes to Keep Existing Assignments below.

    '; + $confirmOverride = true; +} else { + $confirmOverride = false; +} + + +if (isset($_GET['timeout']) && ($_GET['timeout'] == 1) && isset($_SESSION['OPENCONFCHAIRVARS']['timeoutAR']) && is_array($_SESSION['OPENCONFCHAIRVARS']['timeoutAR'])) { + foreach($_SESSION['OPENCONFCHAIRVARS']['timeoutAR'] as $k => $v) { + if ($k == 'POST') { + foreach ($v as $pk => $pv) { + $_POST[$pk] = $pv; + } + } else { + $$k = $v; + } + } + unset($_SESSION['OPENCONFCHAIRVARS']['timeoutAR']); +} else { + // Assign PC members as reviewers? + $ppa = ''; + if (isset($_POST['pcrev']) && ($_POST['pcrev'] == 'Yes')) { + $onpc = ""; + // Set a diff max # of subs per advocate reviewer + if (isset($_POST['ppa']) && preg_match("/^\d+$/", $_POST['ppa'])) { + $ppa = $_POST['ppa']; + } + } else { + $onpc = " AND `" . OCC_TABLE_REVIEWER . "`.`onprogramcommittee`='F'"; + } + + // Get number of papers and initialize paper count array + $pAR = array(); // paper reviewers array + $pInfoAR = array(); // paper info array + $q = "SELECT `paperid`, `title`, `accepted`, `type` FROM `" . OCC_TABLE_PAPER . "` ORDER BY `paperid`"; + $r = ocsql_query($q) or err("Unable to get submissions"); + if (($ptot = ocsql_num_rows($r)) == 0) { + warn('No submissions have been made yet.'); + } + while ($l=ocsql_fetch_array($r)) { + $pAR[$l['paperid']] = array(); + $pInfoAR[$l['paperid']] = array( + 'title' => $l['title'], + 'accepted' => $l['accepted'], + 'type' => $l['type'] + ); + } + + // Get number of reviewers and initialize reviewer count arrays + $rAR = array(); // reviewer papers array + $rNameAR = array(); // reviewer name array + $pcAR = array(); // program committee array + $q = "SELECT `reviewerid`, CONCAT_WS(' ', `name_first`, `name_last`) AS `name`, `onprogramcommittee` FROM `" . OCC_TABLE_REVIEWER . "` ORDER BY `reviewerid`"; + $r = ocsql_query($q) or err("Unable to get reviewers"); + if (($rtot = ocsql_num_rows($r)) == 0) { + warn('No reviewers have signed up yet.'); + } + while ($l=ocsql_fetch_array($r)) { + $rAR[$l['reviewerid']] = array(); + $rNameAR[$l['reviewerid']] = $l['name']; + if ($l['onprogramcommittee'] == 'T') { $pcAR[] = $l['reviewerid']; } + } + + // Revise rtot based on whether pc members assigned as reviewers + if (!isset($_POST['pcrev']) || ($_POST['pcrev'] == 'No')) { + $rtot -= count($pcAR); + } + + // Get conflicts + $nAR = getConflicts(); + + // Calculate # of reviewers per paper + if (isset($_POST['rpp']) && preg_match("/^\d+$/",$_POST['rpp'])) { + $reviewersPerPaper = $_POST['rpp']; + } else { + if (($rppavg=round($rtot/$ptot)) > $OC_configAR['OC_minReviewersPerPaper']) { + $reviewersPerPaper = $rppavg; + } else { + $reviewersPerPaper = $OC_configAR['OC_minReviewersPerPaper']; + } + } + + // Calculate max # of papers each reviewer should get assigned + if (isset($_POST['ppr']) && preg_match("/^\d+$/",$_POST['ppr'])) { + $papersPerReviewer = $_POST['ppr']; + #set below: $pprThreshold = $_POST['pprt']; + } else { + $totrevs = $rtot; + $papersPerReviewer = ceil((($ptot*$reviewersPerPaper)+count($nAR))/$totrevs); # possibly remove +count($nAR) + } + + // Set min # of paper each reviewer should be assigned + if (isset($_POST['pprt']) && preg_match("/^\d+$/",$_POST['pprt'])) { + $pprThreshold = $_POST['pprt']; + } else { + $pprThreshold = floor($papersPerReviewer/2); + } + + // Keep assignments already made? + if (!isset($_POST['keep']) || ($_POST['keep'] == 'Yes')) { + $confirmOverride = false; + if ($prtot > 0) { + while ($prl = ocsql_fetch_array($prr)) { + array_push($pAR[$prl['paperid']], $prl['reviewerid']); + array_push($rAR[$prl['reviewerid']], $prl['paperid']); + } + } + } + + // Add advocates as reviewers? + if ($OC_configAR['OC_paperAdvocates'] + && (!isset($_POST['advrev']) || empty($_POST['advrev']) || ($_POST['advrev'] == "Yes")) + ) { + $q = "SELECT `paperid`, `advocateid` FROM `" . OCC_TABLE_PAPERADVOCATE . "`"; + $r = ocsql_query($q) or err("Unable to get submissions' advocate"); + while ($l=ocsql_fetch_array($r)) { + if (oc_skipSubAssignment($l['paperid'])) { + continue; + } + if (!in_array($l['advocateid'], $pAR[$l['paperid']])) { + array_push($pAR[$l['paperid']], $l['advocateid']); + array_push($rAR[$l['advocateid']], $l['paperid']); + } + } + } + + // Set max # of papers for advocate reviewers + if (empty($ppa)) { + $papersPerAdvocate = $papersPerReviewer; + } else { + $papersPerAdvocate = $ppa; + } + + // Algorithm to use + if (isset($_POST['algo']) && ctype_digit($_POST['algo'])) { + $algo = $_POST['algo']; + } else { + $algo = 0; // default to first defined algorithm above + } +} + +// Get list of sub. types +$OC_activeSubTypeAR = array(); +$typer = ocsql_query("SELECT DISTINCT `type` FROM `" . OCC_TABLE_PAPER . "` WHERE `type` IS NOT NULL AND `type`!='' ORDER BY `type`") or err('Unable to retrieve submission types'); +while ($typel = ocsql_fetch_assoc($typer)) { + $OC_activeSubTypeAR[$typel['type']] = substr($typel['type'], 0, 50); +} + +// Run algo +if (isset($OC_algorithmAR[$algo]['include']) && is_file($OC_algorithmAR[$algo]['include'])) { + require_once $OC_algorithmAR[$algo]['include']; +} else { + err("Algorithm choice unknown"); + exit; +} + +// Remedy missing reviews by assigning reviewers w/lowest #s (if set) +if (isset($_POST['remedy']) && in_array("random", $_POST['remedy'])) { + foreach (array_keys($pAR) as $k) { + if (oc_skipSubAssignment($k)) { + continue; + } + if (count($pAR[$k]) < $reviewersPerPaper) { + // Create an ordered array of reviewers w/least # of reviews + $rcountAR = array(); + foreach (array_keys($rAR) as $k2) { + if ((!isset($_POST['pcrev']) || ($_POST['pcrev'] == 'No')) && in_array($k2, $pcAR)) { // skip PC members? + continue; + } + $rcountAR[$k2] = count($rAR[$k2]); + } + asort($rcountAR); + reset($rcountAR); + // Assign reviewers + if (!in_array(key($rcountAR),$pAR[$k]) && !in_array($k.'-'.key($rcountAR),$nAR)) { + array_push($pAR[$k], key($rcountAR)); + array_push($rAR[key($rcountAR)], $k); + } + while ( (count($pAR[$k]) < $reviewersPerPaper) && (next($rcountAR) !== false) ) { + if (!in_array(key($rcountAR),$pAR[$k]) && !in_array($k.'-'.key($rcountAR),$nAR)) { + array_push($pAR[$k], key($rcountAR)); + array_push($rAR[key($rcountAR)], $k); + } + } + } + } +} + +// Remember assignments +$_SESSION['OPENCONFCHAIRVARS']['pAssignments'] = $pAR; + +// Display form +print ' + + +

    Below you will find OpenConf\'s suggested review assignments. You may fine tune these automated assignments by changing the following options and clicking Re-Evaluate Assignments. Once you are satisfied, click the Make Assignments button to commit them to the database. You may manually add/delete reviews afterwards through the Assign Reviews Manually and List/Unassign Reviews menus.'; + +if (oc_moduleValid('oc_auto_assign')) { + print ' If instead of using this feature you would like assignments to be made automatically when a new submission is made, use the Auto Assign module.'; +} + +print '

    + +
    + + + + + + + + + + + + +'; + +if (count($OC_activeSubTypeAR) > 1) { + print ' + +'; +} + +$algoOptions = ''; +foreach ($OC_algorithmAR as $k => $v) { + $algoOptions .= '
    '; +} +$algoOptions = preg_replace("/(value=\"" . $algo . "\")/","$1 checked", $algoOptions); + +print ''; + +$remStr = ''; +if (isset($_POST['remedy']) && !empty($_POST['remedy'])) { + foreach ($_POST['remedy'] as $rs) { + if (preg_match("/^\w+$/", $rs)) { + $remStr = preg_replace("/(value=\"" . preg_quote($rs, '/') . "\")/", "$1 checked", $remStr); + } + } +} + +print $remStr; + +if ($OC_configAR['OC_paperAdvocates']) { + print ' + + + +'; +} else { + print ' + + + +'; +} + +print ' + + +
    Total Submissions:' . $ptot . '
    Total Reviewers:' . $rtot . '
    Reviewer/Submission Pairings in Conflict:' . count($nAR) . '  (manage)
    Desired Reviewers per Submission:
    Maximum Submissions per Reviewer: + +
    Highlight if Submissions per Reviewer < =
    Keep Existing Assignments?' . generateRadioOptions('keep', $yesNoAR, varValue('keep', $_POST, 'Yes'), 0) . '
    Skip Accepted/Rejected Submissions?' . generateRadioOptions('skipaccepted', $yesNoAR, varValue('skipaccepted', $_POST, 'Yes'), 0) . '
    Assign submissions of type:
    Algorithm:' . $algoOptions . '
    Remedy Missing Assignments by:
    Assign PC members as reviewers?' . generateRadioOptions('pcrev', $yesNoAR, varValue('pcrev', $_POST, 'No'), 0, 'onclick="updatePPA(this.value);"') . '
    Maximum Submissions per Advocate: leave blank to use reviewer value above
    Assign submission\'s advocate as reviewer?' . generateRadioOptions('advrev', $yesNoAR, varValue('advrev', $_POST, 'Yes'), 0) . '
     

    (commits assignments to database)

    +
    +


    + +'; + +function fmtNumSpacing ($n, $dir="l") { + $sp = ""; + if ($n < 10) { $sp = " "; } + elseif ($n < 100) { $sp = " "; } + if ($dir=="l") { return($sp.$n); } + else { return($n.$sp); } +} + +function fmtStrSpacing ($str, $len) { + $a = substr($str,0,$len); + for ($i=oc_strlen($a); $i<$len; $i++) { + $a .= " "; + } + return $a; +} + +print ' + + + +
    Suggested Assignments' . ((!isset($_POST['keep']) || ($_POST['keep'] == 'Yes')) ? '

    including already assigned

    ' : '') . '
    + *  below threshold
    +
    +Place cursor on No. Reviewers for assignments
    +Click title for submission info (new window)
    +
    +No. Reviewers per Submission ID (Title)
    +';
    +foreach ($pAR as $k => $v) {
    +	$titleStr = "Reviewers for Submission $k:\n\n";
    +	foreach ($v as $vv) { $titleStr .= "$vv - " . $rNameAR[$vv] . "\n"; }
    +	$tmpStr = '' . fmtNumSpacing(count($v)) . " - " . fmtNumSpacing($k) . '' . safeHTMLstr($titleStr) . ' (' . safeHTMLstr(fmtStrSpacing($pInfoAR[$k]['title'], 28)) . ")";
    +	if (count($v) < $reviewersPerPaper) { print '' . $tmpStr . " *\n"; }
    +	else { print $tmpStr."\n"; }
    +}
    +
    +
    +print '
    +
           
    + *  below threshold
    +
    +Place cursor on No. Submissions for reviewers
    +Click name for reviewer info (new window)
    +
    +No. Submissions per Reviewer ID (Name)
    +';
    +
    +foreach ($rAR as $k => $v) {
    +	$titleStr = "Submissions for Reviewer $k:\n\n";
    +	foreach ($v as $vv) { $titleStr .= "$vv - " . substr($pInfoAR[$vv]['title'],0,40) . "\n"; }
    +	$tmpStr = '' . fmtNumSpacing(count($v)) . " - " . fmtNumSpacing($k) . '' . safeHTMLstr($titleStr) . ' (';
    +	if (in_array($k, $pcAR)) {
    +		$tmpStr .= 'PC-';
    +		$len = 21;
    +	} else {
    +		$len = 24;
    +	}
    +	$tmpStr .= '' . safeHTMLstr(fmtStrSpacing($rNameAR[$k],$len)).")";
    +	if (count($v) <= $pprThreshold) { print '' . $tmpStr . " *\n"; }
    +	else { print $tmpStr . "\n"; }
    +}
    +
    +print '
    + + +'; + +printFooter(); + +ob_end_flush(); + +?> diff --git a/chair/assign_auto_reviewers_topic_match.inc b/chair/assign_auto_reviewers_topic_match.inc new file mode 100644 index 0000000..78a4746 --- /dev/null +++ b/chair/assign_auto_reviewers_topic_match.inc @@ -0,0 +1,52 @@ + 0) && isset($topicReviewerAR[$t]) && (count($topicReviewerAR[$t] > 0))) { + $topicScoreAR[$t] = count($topicReviewerAR[$t]) / $topPAR[$t]; + } + else $topicScoreAR[$t] = 0; + } + + // Calculate paper scores + foreach ($paperTopicAR as $paperid => $topiclist) { + $score = 0; + foreach ($topiclist as $topicid) { + $score += $topicScoreAR[$topicid]; + } + $paperScoreAR[$paperid] = $score; + } + asort($paperScoreAR); + + // Calculate reviewer scores + foreach ($reviewerTopicAR as $reviewerid => $topiclist) { + $score = 0; + foreach ($topiclist as $topicid) { + $score += $topicScoreAR[$topicid]; + } + $reviewerScoreAR[$reviewerid] = $score; + } + asort($reviewerScoreAR); + } + + // Iterate through papers (score low to high) assigning + // REVIEWERS in order of their score + foreach (array_keys($paperScoreAR) as $paperid) { + if ($continueFrom && ($paperid != $continueFrom)) { // skip to where processing stopped + continue; + } + else { // reset continueFrom - excessive, need to clean up + $continueFrom = 0; + $continueVal = $paperid; + } + + if (oc_checkTimeout()) { // shutdown if close to timeout + oc_assignTimeoutShutdown(); + } + + // Skip submission (e.g., accepted subs) + if (oc_skipSubAssignment($paperid)) { + continue; + } + + // Create a list of reviewers for paper incl. scores + $Rs = array(); + if (isset($paperTopicAR[$paperid])) { + foreach($paperTopicAR[$paperid] as $topicid) { + if (isset($topicReviewerAR[$topicid])) { // may not have a reviewer for every topic + foreach ($topicReviewerAR[$topicid] as $reviewerid) { + if (!in_array($reviewerid,$pAR[$paperid]) // reviewer not yet assigned to paper + && !in_array($paperid."-".$reviewerid,$nAR) // reviewer not in conflict + && (count($rAR[$reviewerid]) < (in_array($reviewerid, $pcAR) ? $ppa : $ppr)) ) // not enough papers yet + { + $Rs[$reviewerid] = $reviewerScoreAR[$reviewerid]; + } + } + } + } + } + // Assign reviewers based on reviewer scores (sortorder: 1=highest first; 2=lowest first) + if (count($Rs) > 0) { + if ($sortorder=="1") { arsort($Rs); } + else { asort($Rs); } + reset($Rs); + // assign reviewers while available & not enough + while ((count($Rs)>0) && (count($pAR[$paperid]) < $rpp)) { + $rid = key($Rs); + array_push($pAR[$paperid],$rid); + array_push($rAR[$rid],$paperid); + unset($Rs[$rid]); + #next($Rs); + } + } + } +} + +oc_algoWeightedTopicMatch($reviewersPerPaper, $papersPerReviewer, $papersPerAdvocate, 1); \ No newline at end of file diff --git a/chair/assign_reviews.php b/chair/assign_reviews.php new file mode 100644 index 0000000..437d957 --- /dev/null +++ b/chair/assign_reviews.php @@ -0,0 +1,333 @@ +Please go back and select at least one submission and one reviewer

    '; + } else { + // Get conflicts? + if ($OC_configAR['OC_allowConflictOverride'] && isset($_POST['conflict_override']) && ($_POST['conflict_override'] == 1)) { + $conflictAR = array(); + } else { + $conflictAR = getConflicts(); + } + // Assign reviews + $reviewerAssignmentAR = array(); // keep track of reviewers w/successful assignments + $submissionAssignmentAR = array(); // keep track of submissions assigned + foreach ($_POST['reviewers'] as $i) { + // valid rev id? + if (!preg_match("/^\d+$/", $i)) { + err('Invalid reviewer selected'); + } + // iterate through submissions for reviewers + foreach ($_POST['papers'] as $j) { + // valid sub id? + if (!preg_match("/^\d+$/", $j)) { + err('Invalid submission selected'); + } + // Check for conflict + if (in_array("$j-$i", $conflictAR)) { + print "

    ! Submission $j is in conflict with reviewer $i.

    \n"; + continue; + } + // Make assignment + $q = "INSERT INTO `" . OCC_TABLE_PAPERREVIEWER . "` (`paperid`,`reviewerid`,`assigned`) VALUES ('" . safeSQLstr($j) . "','" . safeSQLstr($i) . "','" . safeSQLstr(date('Y-m-d')) . "')"; + ocsql_query($q); + if (($merr = ocsql_errno()) != 0) { + if ($merr == 1062) { // Duplicate entry + print "

    ! Submission $j was already assigned reviewer $i.

    \n"; + } else { + print "

    !! Error assigning submission $j to reviewer $i

    \n"; + } + } else { + print "

    Submission $j assigned to reviewer $i.

    \n"; + if (!isset($reviewerAssignmentAR[$i])) { + $reviewerAssignmentsAR[$i] = array(); + } + $reviewerAssignmentAR[$i][] = $j; + if (!in_array($j, $submissionAssignmentAR)) { + $submissionAssignmentAR[] = $j; + } + + // Hook + if (oc_hookSet('chair-assign-review')) { + foreach ($OC_hooksAR['chair-assign-review'] as $f) { + require_once $f; + } + } + + } + } + } + + print '


    '; + + // Notify? + if ( isset($_POST['notify']) && ($_POST['notify'] == 1) && (count($reviewerAssignmentAR) > 0) ) { + // Get list of sub titles + $r = ocsql_query("SELECT `paperid`, `title` FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid` IN (" . implode(',',$submissionAssignmentAR) . ")") or err('Unable to retrieve submission titles for notification'); + $submissionTitleAR = array(); + while ($l = ocsql_fetch_assoc($r)) { + $submissionTitleAR[$l['paperid']] = $l['paperid'] . '. ' . $l['title']; + } + + // Get reviewers to notify + $q = "SELECT `reviewerid`, `name_first`, `name_last`, CONCAT_WS(' ', `name_first`, `name_last`) AS `name`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `reviewerid` IN (" . implode(',', array_keys($reviewerAssignmentAR)) . ")"; + $r = ocsql_query($q) or err('Unable not get reviewer email address(es) for notification'); + + // Get notification template + // ocIgnore included so poEdit picks up (DB) template translation + $ocIgnoreSubject = oc_('New Reviewer Assignment(s)'); + //T: [:OC_confName:] is the event name + $ocIgnoreBody = oc_('New assignments have been made for you to review in the [:OC_confName:] OpenConf system: + + +[:assignments:] + +Thank you.'); + list($subject, $message) = oc_getTemplate('chair-assign_reviews'); + + // Hook + if (oc_hookSet('chair-assign-review-notify')) { + foreach ($OC_hooksAR['chair-assign-review-notify'] as $f) { + require_once $f; + } + } + + // Iterate through reviewers + while ($l = ocsql_fetch_assoc($r)) { + $templateExtraAR = $l; + $templateExtraAR['assignments'] = ''; + foreach ($reviewerAssignmentAR[$l['reviewerid']] as $sid) { + $templateExtraAR['assignments'] .= $submissionTitleAR[$sid] . "\n\n"; + } + $tmpsubject = oc_replaceVariables($subject, $templateExtraAR); + $tmpmessage = oc_replaceVariables($message, $templateExtraAR); + if (sendEmail($l['email'], $tmpsubject, $tmpmessage)) { + print '

    Notification sent to ' . safeHTMLstr($l['name']) . ' (' . safeHTMLstr($l['reviewerid']) . ')

    '; + } else { + print '

    !! Unable to email notification to ' . safeHTMLstr($l['name']) . ' (' . safeHTMLstr($l['reviewerid']) . ')

    '; + } + } + print '


    '; + } + } + + print ' +

    » Make additional assignments

    +

    » View/Edit assignments

    +

    » Manage conflicts

    +'; + +} else { + $pq = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title`, count(`" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`) AS `pcount` FROM `" . OCC_TABLE_PAPER . "` LEFT JOIN `" . OCC_TABLE_PAPERREVIEWER . "` ON `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERREVIEWER . "`.`paperid` GROUP BY `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title` ORDER BY `" . OCC_TABLE_PAPER . "`.`paperid`"; + $pr = ocsql_query($pq) or err("Unable to get submissions"); + // Get pad size for paper id's - yes, we really need the max id, but this should do:) + $rows = ocsql_num_rows($pr); + $psize = oc_strlen((string) $rows); + if ($rows == 0) { + print 'No submissions have been made yet

    '; + } + else { + if (!isset($_GET['s']) || empty($_GET['s']) || ($_GET['s'] == "id")) { + $idsortstr = 'ID'; + $nsortstr = 'Name'; + $rsortstr = 'No. Reviews'; + $legend = "[ Reviewer ID - $nsortstr ($rsortstr) ]"; + $sortby = "`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + } elseif ($_GET['s'] == "reviews") { + $rsortstr = 'No. Reviews'; + $idsortstr = 'ID'; + $nsortstr = 'Name'; + $legend = "[ No. Reviews - Reviewer $nsortstr - $idsortstr ]"; + $sortby = "`rcount`, `" . OCC_TABLE_REVIEWER . "`.`name_last`, `" . OCC_TABLE_REVIEWER . "`.`name_first`"; + } else { + $idsortstr = 'ID'; + $nsortstr = 'Name'; + $rsortstr = 'No. Reviews'; + $legend = "[ Reviewer Name - $idsortstr ($rsortstr) ]"; + $sortby = "`" . OCC_TABLE_REVIEWER . "`.`name_last`, `" . OCC_TABLE_REVIEWER . "`.`name_first`"; + } + $rq = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `onprogramcommittee`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, COUNT(`" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`) AS `rcount` FROM `" . OCC_TABLE_REVIEWER . "` LEFT JOIN `" . OCC_TABLE_PAPERREVIEWER . "` ON `" . OCC_TABLE_REVIEWER . "`.`reviewerid`=`" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid` GROUP BY `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `onprogramcommittee`, `name` ORDER BY $sortby"; + $rr = ocsql_query($rq) or err("Unable to get reviewers"); + // Get pad size for reviewer id's - yes, we really need the max id, but this should do:) + $rsize = oc_strlen((string) ocsql_num_rows($rr)); + if (ocsql_num_rows($rr) == 0) { + print 'No reviewers have signed up yet

    '; + } + else { + // display filter? + $subSort = false; + $revSort = false; + $subFilterAR = array(); + $revFilterAR = array(); + if (count($topicsAR) > 1) { + print ' +

    +
    +     +
    +
    +'; + if (!empty($topicfilter)) { + if ($srfilter != 'Reviewers') { + $subSort = true; + $r = ocsql_query("SELECT `paperid` FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `topicid`='" . safeSQLstr($topicfilter) . "'") or err('Unable to filter submissions by topic'); + while ($l = ocsql_fetch_assoc($r)) { + $subFilterAR[] = $l['paperid']; + } + } + if ($srfilter != 'Submissions') { + $revSort = true; + $r = ocsql_query("SELECT `reviewerid` FROM `" . OCC_TABLE_REVIEWERTOPIC . "` WHERE `topicid`='" . safeSQLstr($topicfilter) . "'") or err('Unable to filter reviewers by topic'); + while ($l = ocsql_fetch_assoc($r)) { + $revFilterAR[] = $l['reviewerid']; + } + } + } + } + + // display assignment form + print ' +
    + +
    +

    Select Submission(s):

    +

    [ Submission ID - Title (No. Reviewers) ]

    + +
    +
    +

    Select Reviewer(s):

    +

    ' . $legend . '

    + +

    Tip: Click the ID, Name, or Reviews links above
    to re-sort this list (page will reload)

    + +
    +
    + +Options:
    +'; + if ($OC_configAR['OC_allowConflictOverride']) { + print ' +

    Override Conflicts – check box to force assignments even if there is a conflict

    +'; + } + print ' +

    – check box to notify reviewer(s) that new assignments have been made

    +
    +

    +
    +'; + } + } +} + +printFooter(); + +?> diff --git a/chair/clear_advocate_data.php b/chair/clear_advocate_data.php new file mode 100644 index 0000000..50db4aa --- /dev/null +++ b/chair/clear_advocate_data.php @@ -0,0 +1,84 @@ +'; + if ($count > 0) { + print safeHTMLstr($count) . ' advocate recommendation records have been cleared'; + } else { + print 'No advocate recommendations found to be cleared'; + } + print '

    '; + +} + +print ' +
    + +

    Clicking the button below will clear out advocate recommendation data while maintaining advocate assignments. Only click the button if you intend on having advocates start the recommendation process anew.

    +

    +

    +

    +
    +'; + +printFooter(); + +?> diff --git a/chair/clear_review_data.php b/chair/clear_review_data.php new file mode 100644 index 0000000..03972e1 --- /dev/null +++ b/chair/clear_review_data.php @@ -0,0 +1,103 @@ += 1) { + while ($l = ocsql_fetch_assoc($r)) { + $fields .= ", `" . $l['Field'] . "`=NULL"; + } + } + + // clear out + if ($_POST['type'] == 'All Submissions') { + issueSQL("TRUNCATE `" . OCC_TABLE_PAPERSESSION . "`"); + issueSQL("UPDATE `" . OCC_TABLE_PAPERREVIEWER . "` SET " . $fields); + } else { + if ($_POST['type'] == 'Pending') { + $acceptedValue = ' IS NULL'; + } elseif (in_array($_POST['type'], $accTypesAR)) { + $acceptedValue = "='" . safeSQLstr($_POST['type']) . "'"; + } else { + warn('Invalid acceptance type'); + } + issueSQL("DELETE FROM `" . OCC_TABLE_PAPERSESSION . "` WHERE `" . OCC_TABLE_PAPERSESSION . "`.`paperid` IN (SELECT `" . OCC_TABLE_PAPER . "`.`paperid` FROM `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_PAPER . "`.`accepted`" . $acceptedValue . ")"); + issueSQL("UPDATE `" . OCC_TABLE_PAPERREVIEWER . "` `pr` INNER JOIN `" . OCC_TABLE_PAPER . "` `p` ON `pr`.`paperid`=`p`.`paperid` SET `pr`." . preg_replace("/, `/", ", `pr`.`", $fields) . " WHERE `p`.`accepted`" . $acceptedValue); + } + $count = ocsql_affected_rows(); + + // Hook + if (oc_hookSet('chair-clear-review')) { + foreach ($OC_hooksAR['chair-clear-review'] as $f) { + require_once $f; + } + } + + // confirm + print '

    '; + if ($count > 0) { + print safeHTMLstr($count) . ' review records have been cleared'; + } else { + print 'No reviews found to be cleared'; + } + print '

    '; + +} + +print ' +
    + +

    Clicking the button below will clear out data for all built-in and custom review form fields while maintaining review assignments. Only click the button if you intend on having reviewers start the review process anew. Backing up the database and exporting reviews is recommended prior to clearing review data.

    +

    +

    +

    keep comments to

    +
    +'; + + +printFooter(); + +?> diff --git a/chair/create_sub.php b/chair/create_sub.php new file mode 100644 index 0000000..c23a960 --- /dev/null +++ b/chair/create_sub.php @@ -0,0 +1,100 @@ +Title must be entered'; + } + if (!isset($_POST['name_last']) || !preg_match("/\p{L}/u", $_POST['name_last'])) { + $err .= '
  • Last Name must be entered
  • '; + } + if (!isset($_POST['email']) || !validEmail($_POST['email'])) { + $err .= '
  • Email is not valid
  • '; + } + if (!isset($_POST['password1']) || !isset($_POST['password2']) || empty($_POST['password1'])) { + $err .= '
  • ' . oc_('Password must be entered twice') . '
  • '; + } elseif ($_POST['password1'] != $_POST['password2']) { + $err .= '
  • ' . oc_('Passwords entered do not match') . '
  • '; + } + if (empty($err)) { + $q = "INSERT INTO `" . OCC_TABLE_PAPER . "` SET " . + "`title`='" . safeSQLstr($_POST['title']) . "', " . + "`password`='" . safeSQLstr(oc_password_hash($_POST['password1'])) . "', " . + "`contactid`=1, " . + "`altcontact`=' '," . + "`submissiondate`='" . safeSQLstr(date('Y-m-d')) . "'"; + $r = ocsql_query($q) or err('Unable to create submission record.'); + $pid = ocsql_insert_id() or err('unable to get submission ID'); + + $q = "INSERT INTO `" . OCC_TABLE_AUTHOR . "` SET " . + "`paperid`='" . safeSQLstr($pid) . "', " . + "`position`=1, " . + "`name_first`='" . safeSQLstr(varValue('name_first', $_POST)) . "', " . + "`name_last`='" . safeSQLstr($_POST['name_last']) . "', " . + "`email`='" . safeSQLstr($_POST['email']) . "'"; + if ($r = ocsql_query($q)) { + if (preg_match("/^(.*)\/chair\/create_sub\.php/", $_SERVER['PHP_SELF'], $match)) { + $url = 'http' . ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) ? 's' : '') . '://' . safeHTMLstr($_SERVER['SERVER_NAME']) . (ctype_digit($_SERVER['SERVER_PORT']) && (($_SERVER['SERVER_PORT'] != '80')) ? (':' . $_SERVER['SERVER_PORT']) : '') . $match[1] . '/author/edit.php'; + } elseif (!empty($OC_configAR['OC_confURL'])) { + $url = $OC_configAR['OC_confURL']; + } else { + $url = ''; + } + $subject = urlencode($OC_configAR['OC_confName']) . ' Submission Information'; + $body = 'A submission entry to ' . $OC_configAR['OC_confName'] . ' has been created for you. Please use the following information to edit your submission' . (empty($url) ? '' : (' at ' . $url)) . '. + + Submission ID: ' . $pid . ' + Password: ' . $_POST['password1']; + print '

    Submission ID ' . $pid . ' successfully created.

    Notify ' . safeHTMLstr(oc_strtolower(OCC_WORD_AUTHOR)) . '

    '; + printFooter(); + exit; + } else { + ocsql_query("DELETE FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`=" . (int) $pid . " LIMIT 1"); + err('Unable to add ' . safeHTMLstr(oc_strtolower(OCC_WORD_AUTHOR)) . ' to submission'); + } + } +} + +if (!empty($err)) { + print '

    Please correct the following items. Note that the password fields must be re-entered.


    '; +} + +print ' +

    This form allows you to create a new submission record. It is intended to permit late submissions once New Submissions have been closed. Upon creating the submission record, provide the ' . oc_strtolower(OCC_WORD_AUTHOR) . ' with the submission ID and password, and instruct them to edit the submission. An email link will be provided upon submission of this form for contacting the ' . oc_strtolower(OCC_WORD_AUTHOR) . ' with this information.

    + +
    + +
    +
    +
    +
    +
    +
    +
    +

    +
    +'; + +printFooter(); + +?> diff --git a/chair/db_backup.php b/chair/db_backup.php new file mode 100644 index 0000000..13795b8 --- /dev/null +++ b/chair/db_backup.php @@ -0,0 +1,137 @@ + 0) { + $l = mysqli_fetch_row($r); + $sqldump .= $l[1]; + if (preg_match("/auto_increment/s",$l[1])) { + mysqli_free_result($r); + $q = 'SHOW TABLE STATUS LIKE "' . $table . '"'; + $r = ocsql_query($q) or backuperr("Unable to query auto increment value for $table $q"); + $l = mysqli_fetch_array($r); + $sqldump .= " AUTO_INCREMENT=" . $l['Auto_increment']; + } + $sqldump .= ";\n\n\n"; + } + mysqli_free_result($r); + + $q = 'SELECT * FROM ' . quoteit($table); + if ($table == 'log') { + $q .= " WHERE `type` NOT LIKE '%fail'"; + } + $r = ocsql_query($q) or backuperr("Unable to query table contents for $table"); + $fieldNum = mysqli_num_fields($r); + $recNum = mysqli_num_rows($r); + $sqldump .= ' +# +# Records in table ' . quoteit($table) . ' (' . $recNum . ') +# + +'; + + $fieldAR = array(); + for ($f=0; $f < $fieldNum; $f++) { + $finfo = mysqli_fetch_field_direct($r, $f); + $fieldAR[$f] = quoteit($finfo->name); + if (preg_match("/(?:int|timestamp)$/",$finfo->type)) { + $fieldNumAR[$f] = TRUE; + } else { $fieldNumAR[$f] = FALSE; } + } + + $fldVal = array(); + while ($row = mysqli_fetch_row($r)) { + $sqldump .= 'INSERT INTO ' . quoteit($table) . ' VALUES ('; + for ($f=0; $f < $fieldNum; $f++) { + if (!isset($row[$f])) { + $fldVal[] = 'NULL'; + } elseif (($row[$f] == '0') || ($row[$f] != '')) { + if ($fieldNumAR[$f]) { + $fldVal[] = $row[$f]; + } else { + $fldVal[] = "'" . safeSQLstr($row[$f]) . "'"; + } + } else { + $fldVal[] = "''"; + } + } + $sqldump .= implode(', ', $fldVal) . ");\n"; + unset($fldVal); + } + mysqli_free_result($r); + +} // for tables + +$fileName = 'openconf'; +if (preg_match("/^\w+$/", $OC_configAR['OC_confName'])) { + $fileName .= '-' . $OC_configAR['OC_confName']; +} +$fileName .= '-' . date('YmdHi') . '.sql'; + +oc_sendNoCacheHeaders(); +header('Content-Type: text/plain'); +header('Content-Disposition: attachment; filename="' . $fileName . '"'); + +print $sqldump; + +?> diff --git a/chair/db_reset.php b/chair/db_reset.php new file mode 100644 index 0000000..c8ad215 --- /dev/null +++ b/chair/db_reset.php @@ -0,0 +1,72 @@ +Selected tables have been emptied

    '; + } elseif ($_POST['submit'] == "Empty Tables") { + print '

    Please confirm that you want to empty (truncate) the tables:



    '; + } else { + err("Unknown submit option"); + } +} else { + print '

    NOTE: Once emptied, the data in the tables cannot be recovered. Make a backup, and use caution when deciding which tables to empty.

    Select tables to empty:

    '; + foreach ($tableAR as $table) { + print '
    '; + } + print '

    '; +} + +printFooter(); + +?> diff --git a/chair/download.php b/chair/download.php new file mode 100644 index 0000000..3d84994 --- /dev/null +++ b/chair/download.php @@ -0,0 +1,41 @@ + diff --git a/chair/email-authors.inc b/chair/email-authors.inc new file mode 100644 index 0000000..d4a2f2a --- /dev/null +++ b/chair/email-authors.inc @@ -0,0 +1,99 @@ + $far) { + if (isset($far['showauthor']) && $far['showauthor']) { + $displayFieldAR[] = $fid; + } +} + +// get review fields and reviewer comments +$tempq = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPERREVIEWER . "`.* FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_PAPERREVIEWER . "` WHERE " . (!empty($accSQL) ? ($accSQL . " AND ") : '') . "`" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`"; +$tempr = ocsql_query($tempq) or err("Unable to get " . oc_strtolower(OCC_WORD_AUTHOR) . " comments"); +while ($templ = ocsql_fetch_array($tempr)) { + // init vars for paperid + if (!isset($authorcomments[$templ['paperid']])) { + $authorcomments[$templ['paperid']] = ""; + } + if (!isset($reviewfields[$templ['paperid']])) { + $reviewfields[$templ['paperid']] = ""; + } + // set author comments + if (!empty($templ['authorcomments'])) { + $authorcomments[$templ['paperid']] .= $commentSeparator . "\n" . $templ['authorcomments'] . "\n"; + } + // set review fields + $reviewInfo = ''; + foreach ($displayFieldAR as $fid) { + if (!empty($templ[$fid])) { + $reviewInfo .= oc_strtoupper(oc_($OC_reviewQuestionsAR[$fid]['short'])) . ': ' . oc_getFieldValue($OC_reviewQuestionsAR, $templ, $fid) ."\n\n"; + } + } + if (!empty($reviewInfo)) { + $reviewfields[$templ['paperid']] .= $commentSeparator . "\n" . $reviewInfo . "\n"; + } +} + +// get advocate and comments +$tempq = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`, `" . OCC_TABLE_REVIEWER . "`.`email`, `" . OCC_TABLE_PAPERADVOCATE . "`.`adv_comments` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_PAPERADVOCATE . "`, `" . OCC_TABLE_REVIEWER . "` WHERE " . (!empty($accSQL) ? ($accSQL . " AND ") : '') . "`" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERADVOCATE . "`.`paperid` AND `" . OCC_TABLE_REVIEWER . "`.`reviewerid`=`" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`"; +$tempr = ocsql_query($tempq) or err("Unable to get advocate comments"); +while ($templ = ocsql_fetch_array($tempr)) { + if ($OC_configAR['OC_paperAdvocates'] && !empty($templ['email'])) { + $advocatename[$templ['paperid']] = $templ['name_first'] . ' ' . $templ['name_last']; + $advocateemail[$templ['paperid']] = $templ['email']; + } + if (!empty($templ['adv_comments'])) { + $advocatecomment[$templ['paperid']] = "\n" . $templ['adv_comments'] . "\n"; + } +} + +// get chair comments +$tempq = "SELECT `paperid`, `pcnotes` FROM `" . OCC_TABLE_PAPER . "`" . (!empty($accSQL) ? ( " WHERE " . $accSQL) : ''); +$tempr = ocsql_query($tempq) or err("Unable to get chair comments"); +while ($templ = ocsql_fetch_array($tempr)) { + if (!empty($templ['pcnotes'])) { + $chairnotes[$templ['paperid']] = "\n" . $templ['pcnotes'] . "\n"; + } +} + +$specialIndexAR['authorcomments'] = 'paperid'; +$specialIndexAR['reviewfields'] = 'paperid'; +$specialIndexAR['advocatecomment'] = 'paperid'; +$specialIndexAR['advocatename'] = 'paperid'; +$specialIndexAR['advocateemail'] = 'paperid'; +$specialIndexAR['chairnotes'] = 'paperid'; + +// Check for addt'l (hook) special variables +if (oc_hookSet('chair-email-authors')) { + foreach ($OC_hooksAR['chair-email-authors'] as $f) { + require_once $f; + } +} diff --git a/chair/email-queue-log.php b/chair/email-queue-log.php new file mode 100644 index 0000000..fe577dd --- /dev/null +++ b/chair/email-queue-log.php @@ -0,0 +1,109 @@ +show email log entries

    '; + +if (isset($_GET['qid']) && ctype_digit($_GET['qid'])) { + $q = "SELECT * FROM `" . OCC_TABLE_EMAIL_QUEUE . "` WHERE `id`='" . safeSQLstr($_GET['qid']) . "'"; + $r = ocsql_query($q) or err('Unable to retrieve message'); + if (ocsql_num_rows($r) == 1) { + $l = ocsql_fetch_assoc($r); + print ' + Message ID: ' . safeHTMLstr($l['id']) . '
    +'; + if (!empty($l['reference_id'])) { + print 'Reference ID: ' . safeHTMLstr($l['reference_id']) . '
    '; + } + print ' + Queued: ' . safeHTMLstr($l['queued']) . (!empty($_GET['lid']) ? '   (view messages queued at same time)' : '') . '
    + Sent: '; + if (!empty($l['sent'])) { + print safeHTMLstr($l['sent']); + } else { + print 'Failed to send'; + } + print '   (re-send message)

    +To: ' . safeHTMLstr($l['to']) . '
    +Subject: ' . safeHTMLstr($l['subject']) . '
    +
    ' . safeHTMLstr($l['body']) . '
    +'; + } else { + warn('Unable to find message'); + } +} elseif (isset($_GET['lid']) && ctype_digit($_GET['lid'])) { + $q = "SELECT `" . OCC_TABLE_EMAIL_QUEUE . "`.`id`, `" . OCC_TABLE_EMAIL_QUEUE . "`.`reference_id`, `" . OCC_TABLE_EMAIL_QUEUE . "`.`sent`, `" . OCC_TABLE_EMAIL_QUEUE . "`.`tries`, `" . OCC_TABLE_EMAIL_QUEUE . "`.`to`, `" . OCC_TABLE_EMAIL_QUEUE . "`.`subject` FROM `" . OCC_TABLE_EMAIL_QUEUE . "`, `" . OCC_TABLE_LOG . "` WHERE `" . OCC_TABLE_LOG . "`.`logid`='" . safeSQLstr($_GET['lid']) . "' AND `" . OCC_TABLE_LOG . "`.`datetime`=`" . OCC_TABLE_EMAIL_QUEUE . "`.`queued` ORDER BY `id`"; + $r = ocsql_query($q) or err('Unable to retrieve log entries'); + if (ocsql_num_rows($r) > 0) { + $displayed = true; + print ''; + $row = 1; + $failed = 0; + while ($l = ocsql_fetch_assoc($r)) { + print '\n"; + if ($row == 1) { + $row = 2; + } else { + $row = 1; + } + } + print '
    IDSentRef IDToSubject
    ' . safeHTMLstr($l['id']) . ''; + if (!empty($l['sent'])) { + print safeHTMLstr($l['sent']); + } else { + print 'Failed to send'; + $failed++; + } + print '' . safeHTMLstr($l['reference_id']) . '' . safeHTMLstr($l['to']) . '' . safeHTMLstr($l['subject']) . "

    Log entries are shown in Coordinated Universal Time (UTC)

    '; + if ($failed > 0) { + print ' +
    + + + +
    '; + } + } else { + warn('No messages found'); + } +} else { + warn('Invalid ID'); +} + +printFooter(); + +?> diff --git a/chair/email-resend.php b/chair/email-resend.php new file mode 100644 index 0000000..6938185 --- /dev/null +++ b/chair/email-resend.php @@ -0,0 +1,38 @@ +Message ID ' . safeHTMLstr($_GET['qid']) . ' successfully sent.

    +

    Note: Re-sent messages will not be displayed in the log/queue.

    +'; + } else { + warn('Unable to send message ID ' . safeHTMLstr($_GET['qid'])); + } + } +} else { + warn('Invalid ID'); +} + +printFooter(); + +?> \ No newline at end of file diff --git a/chair/email.inc b/chair/email.inc new file mode 100644 index 0000000..a510366 --- /dev/null +++ b/chair/email.inc @@ -0,0 +1,200 @@ + OCC_WORD_CHAIR . ' Email Address', + 'OC_confirmmail' => 'Notification Email Address', + 'OC_confName' => 'Event/Journal Short Name', + 'OC_confNameFull' => 'Event/Journal Full Name', + 'OC_confURL' => 'Event/Journal Web Address', + 'OC_openconfURL' => 'OpenConf Web Address', +); + +$OC_emailVarAR['author'] = array( + 'paperid' => 'Submission ID', + 'title' => 'Submission Title', + 'name_last' => 'Recipient Last Name', + 'name_first' => 'Recipient First Name', + 'email' => 'Recipient Email' +); + +$OC_emailVarAR['author_acceptance'] = array( + 'author-comments' => 'Reviewers Comment to Author', + 'advocate-comment' => 'Committee (Adv.) Comment', + 'chair-notes' => OCC_WORD_CHAIR . ' Notes' +); +if ($OC_configAR['OC_paperAdvocates']) { + $OC_emailVarAR['author_acceptance']['advocate-name'] = 'Advocate Name'; + $OC_emailVarAR['author_acceptance']['advocate-email'] = 'Advocate Email'; +} +if (oc_moduleActive('oc_customforms')) { + $OC_emailVarAR['author_acceptance']['review-fields'] = 'Review Fields set to Show Author in Custom Forms module'; +} + +$OC_emailVarAR['committee'] = array( + 'name_last' => 'Reviewer Last Name', + 'name_first' => 'Reviewer First Name', + 'username' => 'Reviewer Username', + 'email' => 'Reviewer Email' +); + +// Check for addt'l (hook) variables +if (oc_hookSet('chair-email-variables')) { + foreach ($OC_hooksAR['chair-email-variables'] as $f) { + require_once $f; + } +} + +// Retrieve templates +$templateAR = array(); +$q = "SELECT `templateid`, `name`, `module` FROM `" . OCC_TABLE_TEMPLATE . "` WHERE `type`='email' ORDER BY `name` ASC"; +$r = ocsql_query($q) or err('Unable to retrieve templates'); +while ($l = ocsql_fetch_assoc($r)) { + // Skip templates for modules not active + if (isset($l['module']) && !empty($l['module']) && ($l['module'] != 'OC') && !in_array($l['module'], $OC_activeModulesAR)) { + continue; + } + // Skip PC templates if advocates not used + if ($OC_configAR['OC_paperAdvocates'] || !preg_match("/^pc_/", $l['templateid'])) { + $templateAR[$l['templateid']] = $l['name']; + } +} + +// Author(s) to include +if ($OC_configAR['OC_emailAuthorRecipients'] == 0) { + $authorIncludeSQL = " AND `" . OCC_TABLE_AUTHOR . "`.`position`=`" . OCC_TABLE_PAPER . "`.`contactid` "; +} else { + $authorIncludeSQL = ''; +} + +// Set up recipients +// - limit keys to [\w-], and text to [\w -] +$recipientAR = array(); +$recipientAR['authors_all']['text'] = OCC_WORD_AUTHOR . 's - All'; +$recipientAR['authors_all']['sql'] = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `name_last`, `name_first`, `title`, `email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` " . $authorIncludeSQL . " ORDER BY `paperid`"; +$recipientAR['authors_all']['vars'] = array_merge($OC_emailVarAR['author'], $OC_emailVarAR['author_acceptance']); +$recipientAR['authors_all']['special'] = 'email-authors.inc'; +$recipientAR['authors_all']['id'] = "`" . OCC_TABLE_PAPER . "`.`paperid`"; + +$sr = ocsql_query("SELECT COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` WHERE `student`='T'") or err('Unable to check student field'); +if (($sl = ocsql_fetch_assoc($sr)) && ($sl['count'] > 0)) { + $recipientAR['authors_students']['text'] = OCC_WORD_AUTHOR . 's - Student submissions'; + $recipientAR['authors_students']['sql'] = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `name_last`, `name_first`, `title`, `email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_PAPER . "`.`student`='T' AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` " . $authorIncludeSQL . " ORDER BY `paperid`"; + $recipientAR['authors_students']['vars'] = array_merge($OC_emailVarAR['author'], $OC_emailVarAR['author_acceptance']); + $recipientAR['authors_students']['special'] = 'email-authors.inc'; + $recipientAR['authors_students']['id'] = "`" . OCC_TABLE_PAPER . "`.`paperid`"; +} + +$recipientAR['authors_nofile']['text'] = OCC_WORD_AUTHOR . 's - Missing file'; +$recipientAR['authors_nofile']['sql'] = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `name_last`, `name_first`, `title`, `email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `format` is NULL AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` " . $authorIncludeSQL . " ORDER BY `paperid`"; +$recipientAR['authors_nofile']['vars'] = array_merge($OC_emailVarAR['author'], $OC_emailVarAR['author_acceptance']); +$recipientAR['authors_nofile']['special'] = 'email-authors.inc'; +$recipientAR['authors_nofile']['id'] = "`" . OCC_TABLE_PAPER . "`.`paperid`"; + +if (count($OC_acceptanceValuesAR) > 1) { + $recipientAR['authors_accepted_all']['text'] = OCC_WORD_AUTHOR . 's - All accepted'; + $recipientAR['authors_accepted_all']['sql'] = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_AUTHOR . "`.`name_last`, `" . OCC_TABLE_AUTHOR . "`.`name_first`, `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_AUTHOR . "`.`email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "`, `" . OCC_TABLE_ACCEPTANCE . "` WHERE `" . OCC_TABLE_PAPER . "`.`accepted`=`" . OCC_TABLE_ACCEPTANCE . "`.`value` AND `" . OCC_TABLE_ACCEPTANCE . "`.`accepted`=1 AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` " . $authorIncludeSQL . " ORDER BY `paperid`"; + $recipientAR['authors_accepted_all']['vars'] = array_merge($OC_emailVarAR['author'], $OC_emailVarAR['author_acceptance']); + $recipientAR['authors_accepted_all']['special'] = 'email-authors.inc'; + $recipientAR['authors_accepted_all']['id'] = "`" . OCC_TABLE_PAPER . "`.`paperid`"; +} + +// acceptance break down +foreach ($OC_acceptanceValuesAR as $idx => $acc) { + $recipientAR['authors_' . $idx]['text'] = OCC_WORD_AUTHOR . 's - Decision - ' . $acc['value']; + $recipientAR['authors_' . $idx]['sql'] = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `name_last`, `name_first`, `title`, `email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_PAPER . "`.`accepted`='" . safeSQLstr($acc['value']) . "' AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` " . $authorIncludeSQL . " ORDER BY `paperid`"; + $recipientAR['authors_' . $idx]['vars'] = array_merge($OC_emailVarAR['author'], $OC_emailVarAR['author_acceptance']); + $recipientAR['authors_' . $idx]['special'] = 'email-authors.inc'; + $recipientAR['authors_' . $idx]['id'] = "`" . OCC_TABLE_PAPER . "`.`paperid`"; +} + +// type break down if in use +if (isset($OC_submissionFieldAR['type']['values']) && is_array($OC_submissionFieldAR['type']['values']) && (count($OC_submissionFieldAR['type']['values']) > 0)) { + foreach ($OC_submissionFieldAR['type']['values'] as $typeidx => $typeval) { + $recipientAR['authors_type_' . $typeidx]['text'] = OCC_WORD_AUTHOR . 's - Type - ' . $typeval; + $recipientAR['authors_type_' . $typeidx]['sql'] = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `name_last`, `name_first`, `title`, `email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_PAPER . "`.`type`='" . safeSQLstr($typeval) . "' AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` " . $authorIncludeSQL . " ORDER BY `paperid`"; + $recipientAR['authors_type_' . $typeidx]['vars'] = array_merge($OC_emailVarAR['author'], $OC_emailVarAR['author_acceptance']); + $recipientAR['authors_type_' . $typeidx]['special'] = 'email-authors.inc'; + $recipientAR['authors_type_' . $typeidx]['id'] = "`" . OCC_TABLE_PAPER . "`.`paperid`"; + } +} + +if (isset($OC_submissionFieldAR['presenter']) && in_array('presenter', $OC_submissionFieldSetAR['fs_authors']['fields'])) { + $recipientAR['presenters']['text'] = 'Presenting ' . OCC_WORD_AUTHOR . 's - Accepted'; + $recipientAR['presenters']['sql'] = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_AUTHOR . "`.`name_last`, `" . OCC_TABLE_AUTHOR . "`.`name_first`, `" . OCC_TABLE_AUTHOR . "`.`email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "`, `" . OCC_TABLE_ACCEPTANCE . "` WHERE `" . OCC_TABLE_PAPER . "`.`accepted`=`" . OCC_TABLE_ACCEPTANCE . "`.`value` AND `" . OCC_TABLE_ACCEPTANCE . "`.`accepted`=1 AND `" . OCC_TABLE_AUTHOR . "`.`presenter`='T' AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` ORDER BY `paperid`"; + $recipientAR['presenters']['vars'] = $OC_emailVarAR['author']; + $recipientAR['presenters']['id'] = "`" . OCC_TABLE_PAPER . "`.`paperid`"; +} + +if ($OC_configAR['OC_paperAdvocates']) { + $recipientAR['reviewer_pc_all']['text'] = 'Review and Program Committee Members - All'; + $recipientAR['reviewer_pc_all']['text'] = 'Review and Program Committee Members - All'; + $recipientAR['reviewer_pc_all']['sql'] = "SELECT `reviewerid`, `name_last`, `name_first`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "` WHERE 1=1 ORDER BY `reviewerid`"; + $recipientAR['reviewer_pc_all']['vars'] = $OC_emailVarAR['committee']; + $recipientAR['reviewer_pc_all']['id'] = '`reviewerid`'; + + $recipientAR['reviewers_all']['text'] = 'Reviewers - All (except Program Committee members)'; +} else { + $recipientAR['reviewers_all']['text'] = 'Reviewers - All'; +} +$recipientAR['reviewers_all']['sql'] = "SELECT `reviewerid`, `name_last`, `name_first`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `onprogramcommittee`='F' ORDER BY `reviewerid`"; +$recipientAR['reviewers_all']['vars'] = $OC_emailVarAR['committee']; +$recipientAR['reviewers_all']['id'] = '`reviewerid`'; + +$recipientAR['reviewers_noreview']['text'] = 'Reviewers - Reviews not yet completed or no score'; +$recipientAR['reviewers_noreview']['sql'] = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `name_last`, `name_first`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERREVIEWER . "` WHERE (`" . OCC_TABLE_PAPERREVIEWER . "`.`completed` != 'T' OR `" . OCC_TABLE_PAPERREVIEWER . "`.`score` IS NULL) AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` GROUP BY `reviewerid`, `name_last`, `name_first`, `username`, `email` ORDER BY `reviewerid`"; +$recipientAR['reviewers_noreview']['vars'] = $OC_emailVarAR['committee']; +$recipientAR['reviewers_noreview']['id'] = "`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + +$recipientAR['reviewers_reviewscomplete']['text'] = 'Reviewers - Reviews all completed'; +$recipientAR['reviewers_reviewscomplete']['sql'] = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `name_last`, `name_first`, `username`, `email`, MIN(`completed`) AS `minc` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERREVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` GROUP BY `reviewerid`, `name_last`, `name_first`, `username`, `email` HAVING MIN(`completed`) NOT LIKE 'F' ORDER BY `reviewerid`"; +$recipientAR['reviewers_reviewscomplete']['vars'] = $OC_emailVarAR['committee']; +$recipientAR['reviewers_reviewscomplete']['id'] = "`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + +$recipientAR['reviewers_nocomment']['text'] = 'Reviewers - Missing author comments'; +$recipientAR['reviewers_nocomment']['sql'] = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `name_last`, `name_first`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERREVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`authorcomments` IS NULL AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` GROUP BY `reviewerid`, `name_last`, `name_first`, `username`, `email` ORDER BY `reviewerid`"; +$recipientAR['reviewers_nocomment']['vars'] = $OC_emailVarAR['committee']; +$recipientAR['reviewers_nocomment']['id'] = "`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + +if ($OC_configAR['OC_paperAdvocates']) { + $recipientAR['pc_all']['text'] = 'Program Committee - All'; + $recipientAR['pc_all']['sql'] = "SELECT `reviewerid`, `name_last`, `name_first`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `onprogramcommittee`='T' ORDER BY `reviewerid`"; + $recipientAR['pc_all']['vars'] = $OC_emailVarAR['committee']; + $recipientAR['pc_all']['id'] = '`reviewerid`'; + + $recipientAR['pc_norecommendation']['text'] = 'Program Committee - Missing advocate recommendation'; + $recipientAR['pc_norecommendation']['sql'] = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `name_last`, `name_first`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`adv_recommendation` is NULL and `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` GROUP BY `reviewerid`, `name_last`, `name_first`, `username`, `email` ORDER BY `reviewerid`"; + $recipientAR['pc_norecommendation']['vars'] = $OC_emailVarAR['committee']; + $recipientAR['pc_norecommendation']['id'] = "`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; +} + +// Check for addt'l (hook) recipients +if (oc_hookSet('chair-email-recipient')) { + foreach ($OC_hooksAR['chair-email-recipient'] as $f) { + require_once $f; + } +} + +// Get sorted list of recipients +$recipients = array(); +foreach ($recipientAR as $k => $v) { + $recipients[$k] = $v['text']; +} +natcasesort($recipients); diff --git a/chair/email.php b/chair/email.php new file mode 100644 index 0000000..3ab71f1 --- /dev/null +++ b/chair/email.php @@ -0,0 +1,489 @@ +New Email » '; +} + +printHeader("Email", 1); + +require_once 'email.inc'; + +clearstatcache(); + +$commentSeparator = "\n***************************************************************\n"; // author comments separator + +$specialIndexAR = array(); // tracks which DB col to use for special var handling + +function showAddresses($recipient, $sql) { + $r = ocsql_query($sql) or err("Unable to retrieve emails"); + if (ocsql_num_rows($r) == 0) { + print '

    No email addresses available for ' . safeHTMLstr($recipient) . '

    '; + } else { + print '

    Email addresses for ' . safeHTMLstr($recipient) . ':

    '; + while ($l = ocsql_fetch_array($r)){ + print safeHTMLstr($l['email']) . "
    \n"; + } + } +} + +function specialValue($a1, $a2) { + global $specialIndexAR, $l; + $varName = $a1 . $a2; + if (!empty($varName) && isset($specialIndexAR[$varName]) && isset($l[$specialIndexAR[$varName]]) && isset($GLOBALS[$varName][$l[$specialIndexAR[$varName]]])) { + return($GLOBALS[$varName][$l[$specialIndexAR[$varName]]]); + } else { + return(''); + } +} + +function queueMessage(&$queueAR, $date) { + $q = "INSERT INTO `" . OCC_TABLE_EMAIL_QUEUE . "` (`queued`, `to`, `subject`, `body`, `reference_id`) VALUES " . implode(', ', $queueAR); + if ( ! ocsql_query($q)) { + $err = 'Unable to queue messages (' . ocsql_errno() . '). You may want to try again or have the administrator check the error logs. '; + if (ocsql_query("DELETE FROM `" . OCC_TABLE_EMAIL_QUEUE . "` WHERE `datetime`='" . $date . "'")) { + $err .= 'Messages just queued for delivered have been deleted'; + } else { + $err .= 'We were unable to remove messages queued for delivery; for reference, their time stamp is ' . $date . '.'; + } + err($err); + } +} + +if (isset($_POST['submit'])) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + // Verify recipient + if (!isset($_POST['recipient']) || !isset($recipients[$_POST['recipient']])) { + warn("Recipient(s) must be selected"); + } + + // Verify template + if (!empty($_POST['template']) && !in_array($_POST['template'], array_keys($templateAR))) { + err("Invalid template"); + } + + // Which message should we use? + if (isset($_POST['message'])) { + $subject = stripslashes($_POST['subject']); + $message = stripslashes($_POST['message']); + + // YMMV wrt below + $message = preg_replace("/\r/","",$message); + + // Save template? + if (!empty($_POST['template']) && isset($_POST['save']) && ($_POST['save'] == "yes")) { + saveTemplate($subject, $message, $_POST['template']); + } + } elseif (!empty($_POST['template'])) { + // retrieve template + list($subject, $message) = oc_getTemplate($_POST['template']); + } else { + $message = ''; + $subject = ''; + } + + // Which submit? + // List Email addresses + if ($_POST['submit'] == "List Email Addresses") { + showAddresses($recipientAR[$_POST['recipient']]['text'], $recipientAR[$_POST['recipient']]['sql']); + } + // Send Email + elseif ($_POST['submit'] == "Send Message") { + + $q = $recipientAR[$_POST['recipient']]['sql']; + + // Individual recipients? + $recipientList = array(); + if (isset($_POST['select_recipients']) && ($_POST['select_recipients'] == 1)) { + if (! isset($_POST['selected_recipients']) || empty($_POST['selected_recipients'])) { + print ' +
    + + + + + + + +
    +'; + warn('No recipients selected'); + } + $selectRecipients = true; + $qrecipientsAR = array(); + foreach ($_POST['selected_recipients'] as $recip) { + list($id, $email) = explode('/', $recip); + if (!preg_match("/^\d+$/", $id) || !validEmail($email)) { continue; } + $recipientList[] = $email; + $qrecipientsAR[] = "'" . safeSQLstr($recip) . "'"; + } + $q = preg_replace("/ WHERE /", " WHERE CONCAT_WS('/', " . $recipientAR[$_POST['recipient']]['id'] . ", " . (isset($recipientAR[$_POST['recipient']]['emailcol']) ? $recipientAR[$_POST['recipient']]['emailcol'] : "`email`") . ") IN (" . implode(',', $qrecipientsAR) . ") AND ", $q); + } else { + $selectRecipients = false; + } + $r = ocsql_query($q) or err("Unable to retrieve information to email"); + $recipientTotal = ocsql_num_rows($r); + if ($recipientTotal == 0) { + err("No email addresses found (on send)"); + } elseif ($selectRecipients && ( ! $OC_configAR['OC_emailAuthorRecipients'] ) && ($recipientTotal != count($_POST['selected_recipients']))) { + // This may mean that the recipientAR SELECT statement does not contain a WHERE clause, resulting the preg_replace above failing + warn("Recipient mismatch - contact your OpenConf administrator"); + } + + // Special var handling + if (isset($recipientAR[$_POST['recipient']]['special']) && is_file($recipientAR[$_POST['recipient']]['special'])) { + require_once $recipientAR[$_POST['recipient']]['special']; + } + + // Log it + $date = safeSQLstr(gmdate('Y-m-d H:i:s')); // set fixed time for log & so messages in queue are grouped together + $logq = "INSERT INTO `" . OCC_TABLE_LOG . "` SET `datetime`='" . $date . "', `type`='email', `entry`='Email sent to "; + if ($selectRecipients) { + $logq .= safeSQLstr($extra = implode(", ", $recipientList)); + } else { + $logq .= safeSQLstr($extra = $recipientAR[$_POST['recipient']]['text']); + } + $extra .= "\nSubject: " . $subject . "\n\n" . $message; + $logq .= "', `extra`='To: " . safeSQLstr($extra) . "'"; + ocsql_query($logq); + + // Send out emails + $to = $tmpmessage = $tmpsubject = ''; + $queueAR = array(); + $queue_date = gmdate('Y-m-d H:i:s'); + if ($OC_configAR['OC_queueEmails']) { // queue messages? + $queueMessages = true; + print '

    Messages are being queued for delivery. Once queued, this page will refresh and the message sent out. If the page does not refresh, you must click the link that will appear at the bottom of the page, and is also available on the ' . OCC_WORD_CHAIR . ' home page.

    '; + } else { + $queueMessages = false; + } + ob_end_flush(); + flush(); + ob_start(); + $emailAR = array(); + while ($l = ocsql_fetch_array($r)) { + if ( + empty($l['email']) + || + (isset($_POST['skipsame']) && ($_POST['skipsame'] == 'yes') && in_array($l['email'], $emailAR)) + ) { + continue; + } + + $emailAR[] = $l['email']; + + $tmpsubject = oc_replaceVariables($subject, $l); + $tmpmessage = oc_replaceVariables($message, $l); + + // Replace special vars (\w-\w) + if (isset($recipientAR[$_POST['recipient']]['special'])) { + $tmpmessage = preg_replace_callback( + "/\[:(\w+)-(\w+):\]/", + function ($matches) { + return specialValue($matches[1], $matches[2]); + }, + $tmpmessage + ); + } + + // YMMV wrt below + $tmpmessage = preg_replace("/\r/","",$tmpmessage); + + $to = $l['email']; // req'd for OC_mailCopyLast code block below + print 'emailing ' . safeHTMLstr($l['email'] . ' (' . $l[0] . ') ... '); + ob_flush(); + flush(); + if ($queueMessages) { + // try to get id for log reference + $reference_id = ''; + if (isset($l['paperid']) && preg_match("/^\d+$/", $l['paperid'])) { + $reference_id = $l['paperid']; + } + if (isset($l['reviewerid']) && preg_match("/^\d+$/", $l['reviewerid'])) { + if (!empty($reference_id)) { + $reference_id .= '-'; + } + $reference_id = $l['reviewerid']; + } + // add to queue + $queueAR[] = "('" . $date . "', '" . safeSQLstr($l['email']) . "', '" . safeSQLstr($tmpsubject) . "', '" . safeSQLstr($tmpmessage) . "', '" . safeSQLstr($reference_id) . "')"; + print "queued
    \n"; + if (count($queueAR) >= 10) { // store messages as a group to save on DB calls + queueMessage($queueAR, $date); + $queueAR = array(); // reset queue array + + } + } elseif (oc_mail($l['email'], $tmpsubject, $tmpmessage)) { // deliver instantly + print "sent
    \n"; + } else { + print "FAILED!!!
    \n"; + } + } + ob_end_flush(); + flush(); + + // Any remaining messages for queue storage? + if ($queueMessages && (count($queueAR) > 0)) { + queueMessage($queueAR, $date); + } + + // Email chair a copy of last email sent + if ($OC_configAR['OC_mailCopyLast']) { + $msg = "To: " . $to . "\nSubject: " . $tmpsubject . "\n\n" . $tmpmessage . "\n"; + if (sendEmail($OC_configAR['OC_confirmmail'], 'Copy of last email sent', $msg)) { + print '

    A copy of the last message ' . ($queueMessages ? 'queued' : 'sent') . ' has been forwarded to ' . $OC_configAR['OC_confirmmail'] . '.

    '; + } else { + print '

    The system was unable to forward a copy of the last message ' . ($queueMessages ? 'queued' : 'sent') . ' to ' . $OC_configAR['OC_confirmmail'] . '.

    '; + } + } + + // attempt javascript redirect + if ($queueMessages) { + print ' + +

    Your messages have been queued. If this page does not refresh automatically and your browser does not look like it is doing something, please follow this link to send them out now, or visit the ' . OCC_WORD_CHAIR . ' home page to send them out later.

    +'; + } + } + // Preview Email + elseif ($_POST['submit'] == "Preview Message") { + $q = $recipientAR[$_POST['recipient']]['sql'] . " LIMIT 1"; + if (isset($_POST['selected_recipients']) && !empty($_POST['selected_recipients'])) { + list($selid, $selemail) = preg_split("/\//", $_POST['selected_recipients'][0]); + $q = preg_replace("/ WHERE /", " WHERE " . $recipientAR[$_POST['recipient']]['id'] . "='" . safeSQLstr($selid) . "' AND " . (isset($recipientAR[$_POST['recipient']]['emailcol']) ? $recipientAR[$_POST['recipient']]['emailcol'] : "`email`") . "='" . safeSQLstr($selemail) . "' AND ", $q); + } + $r = ocsql_query($q) or err("Unable to retrieve information to preview"); + if (ocsql_num_rows($r) == 0) { + err("No email addresses found (preview)"); + } + + $l = ocsql_fetch_array($r); + + // Special var handling + if (isset($recipientAR[$_POST['recipient']]['special']) && is_file($recipientAR[$_POST['recipient']]['special'])) { + require_once $recipientAR[$_POST['recipient']]['special']; + } + + print ' +
    + + + + + +'; + if (isset($_POST['select_recipients']) && ($_POST['select_recipients'] == 1)) { + print ''; + if (isset($_POST['selected_recipients'])) { + foreach ($_POST['selected_recipients'] as $selected_recipient) { + print ''; + } + } + } + print ' + +      + +
    +
    +
    +';		
    +
    +		$tmpsubject = oc_replaceVariables($subject, $l);
    +		$tmpmessage = oc_replaceVariables($message, $l);
    +
    +		// Replace special vars (\w-\w)
    +		if (isset($recipientAR[$_POST['recipient']]['special'])) {
    +			$tmpmessage = preg_replace_callback( 
    +				"/\[:(\w+)-(\w+):\]/",
    +				function ($matches) {
    +					return specialValue($matches[1], $matches[2]);
    +				},
    +				$tmpmessage
    +			);
    +		}
    +		
    +		// Show to/subject and message
    +		print 'To: ';
    +		if (isset($_POST['select_recipients']) && ($_POST['select_recipients'] == 1)) {
    +			if (! isset($_POST['selected_recipients']) || empty($_POST['selected_recipients'])) {
    +				warn('No recipients selected');
    +			} elseif (count($_POST['selected_recipients']) == 1) {
    +				list($id, $email) = explode("/", $_POST['selected_recipients'][0]);
    +				print safeHTMLstr($email . ' (ID: ' . $id . ')');
    +			} else {
    +				print "(The following is a list of selected recipients. The preview is shown for only one of them.)";
    +				foreach ($_POST['selected_recipients'] as $recip) {
    +					list($id, $email) = explode("/", $recip);
    +					print "\n  " . safeHTMLstr($email . ' (ID: ' . $id . ')');
    +				}
    +			}
    +		} else {
    +			print safeHTMLstr($l['email']);
    +		}
    +		print "\n\n";
    +		print 'Subject: ' . safeHTMLstr($tmpsubject) . "\n\n";
    +		print safeHTMLstr(wordwrap($tmpmessage, $OC_configAR['OC_emailWrap'])) . "\n
    \n"; + } + // Write Email + elseif (($_POST['submit'] == "Write Email Online") || ($_POST['submit'] == "Edit Message")) { + // Valid recipient? + if (!isset($_POST['recipient']) || !isset($recipients[$_POST['recipient']])) { + err("Unknown recipient group selected"); + } + // Any addresses + $r = ocsql_query($recipientAR[$_POST['recipient']]['sql']) or err("Unable to retrieve email addresses"); + if (ocsql_num_rows($r) == 0) { + print '

    No email addresses available for ' . safeHTMLstr($recipientAR[$_POST['recipient']]['text']) . '

    '; + } else { + + print ' +
    + + + + + + + + + +'; + + // Save template? + if (!empty($_POST['template'])) { + print ''; + } + + print ' + +
    '; + + if (isset($_POST['select_recipients']) && ($_POST['select_recipients'] == 1)) { + print ''; + } else { + print safeHTMLstr($recipientAR[$_POST['recipient']]['text']); + } + + print ' 
     
    [:variables:]

    '; + + foreach ($OC_emailVarAR['general'] as $vkey => $vval) { + print ''; + } + foreach ($recipientAR[$_POST['recipient']]['vars'] as $vkey => $vval) { + print ''; + } + + print '
    [:' . safeHTMLstr($vkey) . ':]' . safeHTMLstr($vval) . '
    [:' . safeHTMLstr($vkey) . ':]' . safeHTMLstr($vval) . '

    +

    + +      + +
    +
    +

    The variables appearing next to the message field may be used in your email by enclosing each instance in [:variable:] . These will be substituted for their value prior to the email being sent. For example, to include the conference (short) name in your message use [:OC_confName:] . Some variables are only available for certain recipient groups. The [:review-fields:] variable, available when emailing author acceptance notices, includes the review form fields designated to "show author" in the Custom Forms module; the default is to only show the reviewer Comments to Author.

    + '; + } // if Any emails + } // end submit write +} // end submit +// Not a submit - select recipient/template +else { + print ' + +
    + +
    +

    +

    +

    +
    +
    For "' . OCC_WORD_AUTHOR . 's -", ' . (($OC_configAR['OC_emailAuthorRecipients'] == 0) ? ('only the contact ' . oc_strtolower(OCC_WORD_AUTHOR)) : ('all ' . oc_strtolower(OCC_WORD_AUTHOR) . 's')) . ' of a submission will be emailed
    + +

    (edit)

    +

    + +
    +
    + +      + +
    +
    +
    +'; + +} // else not a submit + +printFooter(); + +?> diff --git a/chair/email_process_queue.php b/chair/email_process_queue.php new file mode 100644 index 0000000..0dbda2e --- /dev/null +++ b/chair/email_process_queue.php @@ -0,0 +1,87 @@ +New Email » '; + +ob_start(); + +printHeader("Email Queue", 1); + +ob_flush(); +flush(); + +$r = ocsql_query("SELECT * FROM `" . OCC_TABLE_EMAIL_QUEUE . "` WHERE `sent` IS NULL AND `tries`<1") or err('Unable to retrieve queued messages'); +$count = ocsql_num_rows($r); +if (($count == 0) && (!isset($_GET['pass']) || !ctype_digit($_GET['pass']))) { + print '

    The queue is empty. View email log.

    '; +} else { + if (isset($_GET['f']) && ctype_digit($_GET['f'])) { + $failed = $_GET['f']; + } else { + $failed = 0; + } + $date = safeSQLstr(gmdate('Y-m-d H:i:s')); + print '

    ' . ((isset($_GET['pass']) && ($_GET['pass'] == 1)) ? 'Remaining m' : 'M') . 'essages in queue: ' . $count . "

    \n"; + while ($l = ocsql_fetch_assoc($r)) { + if ($l['tries'] >= 1) { continue; } // skip messages that have been tried already + print 'Message ID ' . $l['id'] . ' (' . safeHTMLstr($l['to']) . ') ... '; + ob_flush(); + flush(); + $set = "`tries`=" . ((int) $l['tries'] + 1); + if (oc_mail($l['to'], $l['subject'], $l['body'])) { + print 'sent'; + $set .= ", `sent`='" . $date . "'"; + } else { + print 'FAILED!!!'; + if ($l['tries'] == 2) { // this will have been the third try + print ' Too many tries, will not try again.'; + } + print ''; + $failed++; + } + print "
    \n"; + $q = "UPDATE `" . OCC_TABLE_EMAIL_QUEUE . "` SET " . $set . " WHERE `id`=" . (int) $l['id'] . " LIMIT 1"; + if ( ! ocsql_query($q)) { // throw error so same message doesn't keep being sent + ob_flush_end(); + err('Unable to update status for message ID ' . $l['id'] . '. Troubleshoot before trying again.'); + } + + // reload script if close to timeout + if (oc_checkTimeout()) { + print ' + + +'; + } + } + if ($failed == 0) { + print '

    All messages have been sent.

    '; + } else { + print '

    ' . $failed . ' messages failed to be sent.

    '; + } + print '

    View email log (most recent batch of messages will appear at the top)

    '; +} + +ob_end_flush(); + +printFooter(); + +?> \ No newline at end of file diff --git a/chair/email_templates.php b/chair/email_templates.php new file mode 100644 index 0000000..a9236d8 --- /dev/null +++ b/chair/email_templates.php @@ -0,0 +1,161 @@ +New Email » '; + +printHeader('Email Templates', 1); + +require_once 'email.inc'; + +clearstatcache(); + +function oc_templateForm($tid, $name, $subject, $body) { + print ' +

    all templates

    +
    +
    + + + + + + + + +
    Template
    Name:

    letters, numbers, hyphen, underscore, and space
     
    Subject:
    Message: 
    +
    +

    Variables available for use in a message are based on the recipient group selected when sending
    +the message. View a list of groups and variables.

    +
    +
    +'; + printFooter(); + exit; +} + +$name = ''; // new template name + +if (isset($_GET['ocaction']) && ($_GET['ocaction'] == 'edit') && isset($_GET['tid']) && isset($templateAR[$_GET['tid']])) { + $r = ocsql_query("SELECT `name`, `subject`, `body` FROM `" . OCC_TABLE_TEMPLATE . "` WHERE `type`='email' AND `templateid`='" . safeSQLstr($_GET['tid']) . "'") or err('Unable to retrieve template'); + if (ocsql_num_rows($r) == 1) { + $l = ocsql_fetch_assoc($r); + oc_templateForm($_GET['tid'], $l['name'], $l['subject'], $l['body']); + } else { + print '

    Template not found

    '; + } +} elseif (isset($_POST['ocaction'])) { + switch($_POST['ocaction']) { + case 'Add Template': + $name = (isset($_POST['name']) ? trim($_POST['name']) : ''); + $templateid = 'custom' . time(); + if (!preg_match("/^[\w -]+$/", $name)) { + print '

    Template name must not be blank, and only contain
    letters, numbers, hyphen, underscore, and space

    '; + } elseif ( in_array($name, $templateAR) ) { + print '

    A template with that name already exists

    '; + } elseif ( ! ocsql_query("INSERT INTO `" . OCC_TABLE_TEMPLATE . "` SET `templateid`='" . safeSQLstr($templateid) . "', `type`='email', `module`='OC', `name`='" . safeSQLstr($name) . "', `subject`='', `body`='', `updated`='" . safeSQLstr(date('Y-m-d')) . "'") ) { + print '

    Unable to add template; perhaps you double-clicked? Check below.

    '; + } else { + print '

    Template added

    '; + $templateAR[$templateid] = $name; + asort($templateAR); + $name = ''; + } + break; + + case 'Delete Templates': + if (isset($_POST['templates']) && is_array($_POST['templates'])) { + $count = 0; + foreach ($_POST['templates'] as $tid) { + if (isset($templateAR[$tid])) { + if (ocsql_query("DELETE FROM `" . OCC_TABLE_TEMPLATE . "` WHERE `type`='email' AND `templateid`='" . safeSQLstr($tid) . "' LIMIT 1")) { + unset($templateAR[$tid]); + $count++; + } + } + } + print '

    Deleted ' . $count . ' template' . (($count!=1) ? 's' : '') . '

    '; + } + break; + + case 'Save Template': + $templatename = (isset($_POST['templatename']) ? trim($_POST['templatename']) : ''); + $templateid = (isset($_POST['templateid']) ? trim($_POST['templateid']) : ''); + $subject = (isset($_POST['subject']) ? trim($_POST['subject']) : ''); + $body = (isset($_POST['body']) ? trim($_POST['body']) : ''); + + $err = ''; + if ( ! preg_match("/^[\w-]+$/", $templateid) || ! isset($templateAR[$templateid]) ) { + warn('Template ID invalid'); + } elseif (!preg_match("/^[\w -]+$/", $templatename)) { + $err = 'Template name invalid'; + } elseif (preg_match("/[\r\n]/", $subject)) { + $err = 'Subject invalid'; + } else { + $q = "UPDATE `" . OCC_TABLE_TEMPLATE . "` SET `name`='" . safeSQLstr($templatename) . "', `subject`='" . safeSQLstr($subject) . "', `body`='" . safeSQLstr($body) . "', `updated`='" . safeSQLstr(date("Y-m-d")) . "' WHERE `templateid`='" . safeSQLstr($templateid) . "' LIMIT 1"; + if ( ! ocsql_query($q) ) { + $err = 'Unable to add/update database'; + } + } + + if (empty($err)) { + print '

    Template saved

    '; + } else { + print '

    ' . $err . '

    '; + } + + oc_templateForm($templateid, $templatename, $subject, $body); + + break; + + default: + warn('Request unknown'); + exit; + } +} + +print ' +
    +

    + + + +'; + +$row = 2; +$custom = 0; +foreach ($templateAR as $templateID => $templateName) { + print ''; + $row = $rowAR[$row]; +} + +if ($custom > 0) { + print ''; +} + +print ' +
     Template - click name to edit
    '; + if (preg_match("/^custom/", $templateID)) { + print ''; + $custom++; + } else { + print ' '; + } + print '
    +
    +'; + +printFooter(); + +?> diff --git a/chair/email_username.php b/chair/email_username.php new file mode 100644 index 0000000..78ca391 --- /dev/null +++ b/chair/email_username.php @@ -0,0 +1,41 @@ +Functionality disabled

    '; +} +elseif (isset($_POST['submit']) && ($_POST['submit'] == "Email Username")) { + $msg = ' +The ' . OCC_WORD_CHAIR . ' username for accessing the ' . $OC_configAR['OC_confName'] . ' OpenConf system is: + + ' . $OC_configAR['OC_chair_uname'] . ' +'; + if (sendEmail($OC_configAR['OC_pcemail'], OCC_WORD_CHAIR . " username", $msg)) { + print '

    The ' . OCC_WORD_CHAIR . ' username has been emailed to the ' . OCC_WORD_CHAIR . '\'s address

    Proceed to sign in

    '; + } else { + err('Unable to send email'); + } +} else { + print ' +

    Click the button below to email the username to the ' . OCC_WORD_CHAIR . '\'s address

    +
    +

    +
    +'; +} + +printFooter(); + +?> diff --git a/chair/email_variables.php b/chair/email_variables.php new file mode 100644 index 0000000..4d2a0b5 --- /dev/null +++ b/chair/email_variables.php @@ -0,0 +1,79 @@ + + + + + +Email Variables + + + + +'; + +if (isset($_GET['l']) && ($_GET['l'] == 'all')) { + foreach ($varsAR as $rAR) { + print '

    ' . safeHTMLstr($rAR['text']) . '

    ' . $rAR['table']; + } +} else { + print '

    ' . safeHTMLstr($first['text']) . '

    ' . $first['table'] . '
    '; +} + +print '

    General

    '; + +foreach ($OC_emailVarAR['general'] as $varID => $var) { + print ''; +} + +print ' +
    [:' . safeHTMLstr($varID) . ':]' . safeHTMLstr($var) . '
    + + +'; + +?> \ No newline at end of file diff --git a/chair/export.inc b/chair/export.inc new file mode 100644 index 0000000..93696f6 --- /dev/null +++ b/chair/export.inc @@ -0,0 +1,313 @@ + array('name'=>'CSV', 'mime'=>'text/plain'), + 'xls' => array('name'=>'Microsoft Excel 2000', 'mime'=>'application/vnd.ms-excel'), + 'xlsx' => array('name'=>'Microsoft Excel 2007', 'mime'=>'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'), + 'txt' => array('name'=>'Text (tab-delimited)', 'mime'=>'text/plain'), + 'xml' => array('name'=>'XML', 'mime'=>'application/xml') +); + +function oc_export_headers($filename, $format) { + oc_sendNoCacheHeaders(); + header('Content-Type: ' . $GLOBALS['OC_exportFormatAR'][$format]['mime']); + header('Content-Disposition: attachment; filename="' . $filename . '"'); +} + +function oc_export_err($e) { + if (isset($GLOBALS['hdr'])) { + $hdr = $GLOBALS['hdr']; + } else { + $hdr = 'Export Error'; + } + if (isset($GLOBALS['hdrfn'])) { + $hdrfn = $GLOBALS['hdrfn']; + } else { + $hdrfn = 1; + } + err($e, $hdr, $hdrfn); +} + +function oc_colID($cols) { // converts a column number to its alpha representation (e.g., 0=A, 25=Z, 26=AA) + for ($r=""; $cols>=0; ($cols = intval($cols/26)-1)) { + $r = chr($cols%26 + 0x41) . $r; + } + return $r; +} + +function oc_export(&$scope, &$exportFieldsAR, &$fieldNameAR, &$dbR, &$extraAR=array(), &$fieldAR=array()) { + + if (isset($_POST['format']) && isset($GLOBALS['OC_exportFormatAR'][$_POST['format']])) { + $format = $_POST['format']; + } else { + $format = 'csv'; + } + + // set filename + $fileName = 'openconf'; + if (preg_match("/^\w+$/", $GLOBALS['OC_configAR']['OC_confName'])) { + $fileName .= '-' . $GLOBALS['OC_configAR']['OC_confName']; + } + $fileName .= '-' . oc_strtolower($scope) . '-' . date('YmdHi') . '.' . $format; + + // field limit? + if (isset($_POST['charlimit']) && ($_POST['charlimit'] == 1)) { + $useCharLimit = $GLOBALS['OC_exportCharLimit']; + } else { + $useCharLimit = 0; + } + + // export file + switch ($format) { + + case 'xlsx': // ***************************************************************** + + $rows = ocsql_num_rows($dbR) + 1; // +1 = header + $cols = count($exportFieldsAR); + $celltotal = $rows * $cols; + + if (!class_exists('ZipArchive')) { + oc_export_err('ZipArchive library missing'); + } + + $tempZip = tempnam('/tmp/', 'ocexport') or oc_export_err('could not generate Excel file (1)'); + copy(OCC_LIB_DIR . 'xlsx-template.zip', $tempZip) or oc_export_err('could not generate Excel file (2)'); + $zip = new ZipArchive; + if (($res = $zip->open($tempZip)) && ($res === true)) { + // Create/add sheet1.xml + $sheetFile = tempnam('/tmp/', 'ocexport') or oc_export_err('could not generate Excel file (3)'); + $fp = fopen($sheetFile, 'w') or oc_export_err('could not generate Excel file (4)'); + fputs($fp, ' + '); + $v = 0; + for ($row=1; $row<=$rows; $row++) { + fputs($fp, ''); + for ($col=0; $col<$cols; $col++) { + fputs($fp, '' . $v++ . ''); + } + fputs($fp, ''); + } + fputs($fp, ''); + fclose($fp); + if (($res = $zip->addFile($sheetFile, 'xl/worksheets/sheet1.xml')) && ($res === false)) { + $zip->close(); + unlink($sheetFile); + unlink($tempZip); + oc_export_err('could not generate Excel file (5)'); + } + + // create/add shareStrings.xml + $sharedStringsFile = tempnam('/tmp/', 'ocexport') or oc_export_err('could not generate Excel file (6)'); + $fp = fopen($sharedStringsFile, 'w') or oc_export_err('could not generate Excel file (7)'); + fputs($fp, ' + '); + foreach ($exportFieldsAR as $f) { // header + fputs($fp, '' . htmlspecialchars(isset($fieldNameAR[$f]) ? $fieldNameAR[$f] : ucwords(preg_replace("/_/", " ", trim($f, "_")))) . ''); + } + while ($l = ocsql_fetch_array($dbR)) { // data + foreach ($exportFieldsAR as $f) { + if (preg_match("/^_/", $f)) { + if (isset($extraAR[$l['id']][$f])) { + $val = $extraAR[$l['id']][$f]; + } else { + $val =''; + } + } else { + $val = oc_getFieldValue($fieldAR, $l, $f, '', $useCharLimit, false); + } + fputs($fp, '' . htmlspecialchars($val) . ''); + } + } + fputs($fp, ''); + fclose($fp); + if (($res = $zip->addFile($sharedStringsFile, 'xl/sharedStrings.xml')) && ($res === false)) { + $zip->close(); + unlink($sheetFile); + unlink($sharedStringsFile); + unlink($tempZip); + oc_export_err('could not generate Excel file (8)'); + } + + // create/add core.xml + $coreFile = tempnam('/tmp/', 'ocexport') or die('could not generate Excel file (6)'); + $fp = fopen($coreFile, 'w') or oc_export_err('could not generate Excel file (9)'); + fputs($fp, ' + OpenConf' . date("Y-m-d\TH:i:s.00\Z") . ''); + fclose($fp); + if (($res = $zip->addFile($coreFile, 'docProps/core.xml')) && ($res === false)) { + $zip->close(); + unlink($sheetFile); + unlink($sharedStringsFile); + unlink($coreFile); + unlink($tempZip); + oc_export_err('could not generate Excel file (10)'); + } + + + $zip->close(); + + unlink($sheetFile); + unlink($sharedStringsFile); + unlink($coreFile); + + oc_export_headers($fileName, $format); + readfile($tempZip); + + unlink($tempZip); + + } else { + oc_export_err('could not generate Excel file (0)'); + } + + break; + + case 'xls': // ***************************************************************** + + oc_export_headers($fileName, $format); + + print ' + + + + + + + + + + +
    + + + '; + // Title Row + print ''; + foreach ($exportFieldsAR as $f) { + print ''; + } + print ''; + + // Iterate through records + while ($l = ocsql_fetch_array($dbR)) { + print ''; + foreach ($exportFieldsAR as $f) { + if (preg_match("/^_/", $f)) { + if (isset($extraAR[$l['id']][$f])) { + $val = $extraAR[$l['id']][$f]; + } else { + $val =''; + } + } else { + $val = oc_getFieldValue($fieldAR, $l, $f, '', $useCharLimit, false); + } + print ''; + } + print ''; + } + print ' +
    ' . htmlspecialchars(isset($fieldNameAR[$f]) ? $fieldNameAR[$f] : ucwords(preg_replace("/_/", " ", trim($f, "_")))) . '
    ' . htmlspecialchars($val) . '
    +
    + + + '; + + break; + + case 'xml': // ***************************************************************** + + oc_export_headers($fileName, $format); + + print ' + + + '; + + // Iterate through records + while ($l = ocsql_fetch_array($dbR)) { + print " \n"; + foreach ($exportFieldsAR as $f) { + $tag = (isset($fieldNameAR[$f]) ? $fieldNameAR[$f] : ucwords(preg_replace("/_/", " ", trim($f, "_")))); + $tag = preg_replace("/[^\w]/", "", $tag); + if (preg_match("/^_/", $f)) { + if (isset($extraAR[$l['id']][$f])) { + $val = $extraAR[$l['id']][$f]; + } else { + $val =''; + } + } else { + $val = oc_getFieldValue($fieldAR, $l, $f, '', $useCharLimit, false); + } + if ($val == '') { + print " <$tag />\n"; + } else { + print " <$tag>" . htmlspecialchars($val) . "\n"; + } + } + print " \n"; + } + + print ''; + + break; + + default: // ***************************************************************** + + oc_export_headers($fileName, $format); + + if ($format == 'txt') { + $delim = "\t"; + } else { + $delim = ','; + } + + // Title Row + $titlerow = ''; + foreach ($exportFieldsAR as $f) { + $titlerow .= '"' . str_replace("\"", "\"\"", (isset($fieldNameAR[$f]) ? $fieldNameAR[$f] : preg_replace("/_/", " ", trim($f, "_")))) . '"' . $delim; + } + print oc_strtoupper(rtrim($titlerow, $delim)) . "\r\n"; + + // Iterate through records + while ($l = ocsql_fetch_array($dbR)) { + $row = ''; + // Add non-author/extra fields to row + foreach ($exportFieldsAR as $f) { + if (preg_match("/^_/", $f)) { + $row .= '"' . (isset($extraAR[$l['id']][$f]) ? str_replace("\"", "\"\"", $extraAR[$l['id']][$f]) : '') . '"' . $delim; + } else { + $row .= '"' . str_replace("\"", "\"\"", oc_getFieldValue($fieldAR, $l, $f, '', $useCharLimit, false)) . '"' . $delim; + } + } + + $row = preg_replace("/\015(\012)?/", "\012", $row); + print rtrim($row, $delim) . "\015\012"; + } + + break; + + } + + // exit so not additional code is executed + exit; +} // oc_export f'n diff --git a/chair/export_papers.php b/chair/export_papers.php new file mode 100644 index 0000000..a3d42f5 --- /dev/null +++ b/chair/export_papers.php @@ -0,0 +1,293 @@ + 'Submission ID', + 'submissiondate' => 'Submission Date', + 'lastupdate' => 'Last Updated', + 'accepted' => 'Acceptance', + '_score' => 'Score', +); + +$authorFieldsAR = array(); +foreach ($OC_submissionFieldSetAR as $fsKey => $fsAR) { + if (count($fsAR['fields']) == 0) { continue; } + if ($fsKey == 'fs_authors') { + $fieldAR['skip' . $skip++] = ''; + $fieldAR['name'] = 'Contact ' . OCC_WORD_AUTHOR . ' Full Name'; + $authorFieldsAR['author_name'] = 'All ' . OCC_WORD_AUTHOR . 's Full Name'; + foreach ($fsAR['fields'] AS $fieldID) { + $fieldAR[$fieldID] = 'Contact ' . OCC_WORD_AUTHOR . ' ' . (empty($OC_submissionFieldAR[$fieldID]['short']) ? $OC_submissionFieldAR[$fieldID]['name'] : $OC_submissionFieldAR[$fieldID]['short']); + $authorFieldsAR['author_' . $fieldID] = 'All ' . OCC_WORD_AUTHOR . 's ' . (empty($OC_submissionFieldAR[$fieldID]['short']) ? $OC_submissionFieldAR[$fieldID]['name'] : $OC_submissionFieldAR[$fieldID]['short']); + } + $fieldAR['skip' . $skip++] = ''; + } else { + foreach ($fsAR['fields'] AS $fieldID) { + if (preg_match("/^password/i", $fieldID) || ($fieldID == 'file') || ($fieldID == 'topics') || empty($OC_submissionFieldAR[$fieldID]['name'])) { continue; } + $fieldAR[$fieldID] = (empty($OC_submissionFieldAR[$fieldID]['short']) ? $OC_submissionFieldAR[$fieldID]['name'] : $OC_submissionFieldAR[$fieldID]['short']); + } + } +} + +if (isset($OC_submissionFieldAR['topics']['short'])) { + $fieldAR['_topics'] = $OC_submissionFieldAR['topics']['short']; +} + +$fieldAR['skip' . $skip++] = ''; + +$fieldAR = array_merge($fieldAR, $authorFieldsAR); + +$fieldAR['skip' . $skip++] = ''; + +// Default list of checked fields +$checkedFieldAR = array('paperid','title','name','email'); + +// Advocate/Committee fields +if ($OC_configAR['OC_paperAdvocates']) { + $fieldAR['skip' . $skip++] = ''; + $fieldAR['_advocateid'] = 'Advocate ID'; + $fieldAR['_advocate'] = 'Advocate'; + $fieldAR['_adv_recommendation'] = 'Advocate Recommendation'; + $fieldAR['_adv_comments'] = 'Advocate (Committee) Notes'; + $fieldAR['pcnotes'] = OCC_WORD_CHAIR . ' Notes'; + $fieldAR['skip' . $skip++] = ''; +} else { + $fieldAR['skip' . $skip++] = ''; + $fieldAR['pcnotes'] = OCC_WORD_CHAIR . ' Notes'; + $fieldAR['skip' . $skip++] = ''; +} + +// Include extra fields +if (oc_hookSet('chair-export-fields')) { + foreach ($OC_hooksAR['chair-export-fields'] as $v) { + require_once $v; + } +} + +if (isset($_POST['submit']) && ($_POST['submit'] == "Generate File") && isset($_POST['fields']) && !empty($_POST['fields'])) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + // Verify Fields + $fieldARkeys = array_keys($fieldAR); + foreach ($_POST['fields'] as $f) { + if (!in_array($f,$fieldARkeys)) { + err('Invalid field name selection', $hdr, $hdrfn); + } + } + + // Init extra field AR + $extraAR = array(); + + // List of fields to export + $exportFieldsAR = $_POST['fields']; + + // All author data to display + $incAuthorFieldsAR = array_intersect($_POST['fields'], array_keys($authorFieldsAR)); + if (!empty($incAuthorFieldsAR)) { + $maxPosition = 1; // tracks max number of authors per submission + + // Get all authors info + $q = "SELECT `" . OCC_TABLE_AUTHOR . "`.*, CONCAT_WS(' ', `" . OCC_TABLE_AUTHOR . "`.`name_first`, `" . OCC_TABLE_AUTHOR . "`.`name_last`) AS `name` FROM `" . OCC_TABLE_AUTHOR . "`, `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` " . $accSQL . " ORDER BY `paperid`, `position`"; + $r = ocsql_query($q) or err("Unable to retrieve data for export (1)", $hdr, $hdrfn); + while ($l = ocsql_fetch_assoc($r)) { + foreach ($authorFieldsAR as $afKey => $afVal) { + if (preg_match("/^author_(\w+)$/", $afKey, $matches)) { + if (isset($OC_submissionFieldAR[$matches[1]]['values']) && is_array($OC_submissionFieldAR[$matches[1]]['values']) + && isset($OC_submissionFieldAR[$matches[1]]['usekey']) && $OC_submissionFieldAR[$matches[1]]['usekey'] + && !empty($l[$matches[1]]) + && isset($OC_submissionFieldAR[$matches[1]]['values'][$l[$matches[1]]]) + ) { + $extraAR[$l['paperid']]['_' . $afKey . $l['position']] = $OC_submissionFieldAR[$matches[1]]['values'][$l[$matches[1]]]; + } else { + $extraAR[$l['paperid']]['_' . $afKey . $l['position']] = $l[$matches[1]]; + } + $fieldAR['_' . $afKey . $l['position']] = preg_replace("/All " . OCC_WORD_AUTHOR . "s /", "", (OCC_WORD_AUTHOR . ' ' . $l['position'] . ' ' . $fieldAR[$afKey])); + } + } + if ($l['position'] > $maxPosition) { + $maxPosition = $l['position']; + } + } + + $newAuthorFieldsAR = array(); + for ($i=1; $i<=$maxPosition; $i++) { + foreach($incAuthorFieldsAR as $f) { + $newAuthorFieldsAR[] = '_' . $f . $i; + } + } + reset($incAuthorFieldsAR); + array_splice( + $exportFieldsAR, + array_search(current($incAuthorFieldsAR), $_POST['fields']), + count($incAuthorFieldsAR), + $newAuthorFieldsAR + ); + } + + // Topics + if (in_array('_topics', $exportFieldsAR)) { + $q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_TOPIC . "`, `" . OCC_TABLE_PAPERTOPIC . "` WHERE `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERTOPIC . "`.`paperid` AND `" . OCC_TABLE_PAPERTOPIC . "`.`topicid`=`" . OCC_TABLE_TOPIC . "`.`topicid` " . $accSQL; + $r = ocsql_query($q) or err("Unable to retrieve data for export (t)", $hdr, $hdrfn); + while ($l = ocsql_fetch_assoc($r)) { + if (isset($extraAR[$l['paperid']]['_topics'])) { + $extraAR[$l['paperid']]['_topics'] .= "\n" . useTopic($l['short'], $l['topicname']); + } else { + $extraAR[$l['paperid']]['_topics'] = useTopic($l['short'], $l['topicname']); + } + } + } + + // Score + if (in_array('_score', $exportFieldsAR)) { + $q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, ABS(FORMAT(AVG(`score`),2)) AS `recavg` FROM `" . OCC_TABLE_PAPER . "` LEFT JOIN `" . OCC_TABLE_PAPERREVIEWER . "` ON `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` WHERE 1=1 " . $accSQL . " GROUP BY `paperid`"; + $r = ocsql_query($q) or err("Unable to retrieve data for export (s)", $hdr, $hdrfn); + while ($l = ocsql_fetch_assoc($r)) { + $extraAR[$l['paperid']]['_score'] = $l['recavg']; + } + } + + // Committee Comments + if (preg_match("/\b_adv/", implode(',', $exportFieldsAR))) { + // $accSQL is left out below as OCC_TABLE_PAPER is not included, meaning we use a little more memory + $q = "SELECT `" . OCC_TABLE_PAPERADVOCATE . "`.*, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `advocate` FROM `" . OCC_TABLE_PAPERADVOCATE . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` ORDER BY `paperid`"; + $r = ocsql_query($q) or err("Unable to retrieve data for export (c)", $hdr, $hdrfn); + while ($l = ocsql_fetch_assoc($r)) { + $extraAR[$l['paperid']]['_adv_comments'] = $l['adv_comments']; + $extraAR[$l['paperid']]['_advocateid'] = $l['advocateid']; + $extraAR[$l['paperid']]['_advocate'] = $l['advocate']; + $extraAR[$l['paperid']]['_adv_recommendation'] = $l['adv_recommendation']; + } + } + + // Get extra fields data + if (oc_hookSet('chair-export-data')) { + foreach ($OC_hooksAR['chair-export-data'] as $v) { + require_once $v; + } + } + + // Get sub. data & iterate through each + $q = "SELECT `" . OCC_TABLE_PAPER . "`.*, `" . OCC_TABLE_PAPER . "`.`paperid` AS `id`, `" . OCC_TABLE_AUTHOR . "`.*, CONCAT_WS(' ',`" . OCC_TABLE_AUTHOR . "`.`name_first`,`" . OCC_TABLE_AUTHOR . "`.`name_last`) AS `name` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "` WHERE `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` AND `" . OCC_TABLE_AUTHOR . "`.`position`=`" . OCC_TABLE_PAPER . "`.`contactid` " . $accSQL . " ORDER BY `" . OCC_TABLE_PAPER . "`.`paperid`"; + $r = ocsql_query($q) or err("Unable to retrieve data for export", $hdr, $hdrfn); + if (ocsql_num_rows($r) == 0) { + warn("There are no papers to export", $hdr, $hdrfn); + exit; + } else { // Export file + oc_export($scope, $exportFieldsAR, $fieldAR, $r, $extraAR, $OC_submissionFieldAR); + exit; + } + +} + +// Display form +printHeader($hdr, $hdrfn); + +print ' +
    + +

    Export will generate one row/entry per submission. When selecting All ' . OCC_WORD_AUTHOR . 's, each ' . oc_strtolower(OCC_WORD_AUTHOR) . '\'s data will appear as separate fields.

    + +'; + +foreach ($fieldAR as $fieldID => $fieldName) { + if (preg_match("/^skip\d+$/", $fieldID)) { + print '
    '; + continue; + } + print '
    \n"; +} + +print ' +
    + +    + + +
    + +

    + +
    + +

    Note: When opening up a CSV or Tab-delimited file in a spreadsheet, you may need to specify the character encoding: UTF-8.

    + +'; + +printFooter(); + +?> diff --git a/chair/export_reviewers.php b/chair/export_reviewers.php new file mode 100644 index 0000000..80bcfc3 --- /dev/null +++ b/chair/export_reviewers.php @@ -0,0 +1,171 @@ + 'ID', + 'name' => 'Full Name', +); + +if ($OC_configAR['OC_paperAdvocates']) { + $fieldAR['onprogramcommittee'] = 'OnProgramCommittee'; +} + +foreach ($OC_reviewerFieldSetAR as $fsKey => $fsAR) { + foreach ($fsAR['fields'] AS $fieldID) { + if (preg_match("/^password/i", $fieldID) || ($fieldID == 'topics') || empty($OC_reviewerFieldAR[$fieldID]['short'])) { continue; } + $fieldAR[$fieldID] = $OC_reviewerFieldAR[$fieldID]['short']; + } +} + +if (isset($OC_reviewerFieldAR['topics']['short'])) { + $fieldAR['_topics'] = $OC_reviewerFieldAR['topics']['short']; +} + +$fieldAR['skip' . $skip++] = ''; + +// Default list of checked fields +$checkedFieldAR = array_keys($fieldAR); + +// Include extra fields +if (oc_hookSet('chair-export_reviewers-fields')) { + foreach ($OC_hooksAR['chair-export_reviewers-fields'] as $v) { + require_once $v; + } +} + +if (isset($_GET['template']) && ($_GET['template'] == 1)) { + $template = true; + unset($fieldAR['name']); +} else { + $template = false; +} + +if (isset($_POST['submit']) && ($_POST['submit'] == "Generate File") && isset($_POST['fields']) && !empty($_POST['fields'])) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + // Verify Fields + $fieldARkeys = array_keys($fieldAR); + foreach ($_POST['fields'] as $f) { + if (!in_array($f, $fieldARkeys)) { + err('Invalid field name selection'); + } + } + + // Init extra field AR + $extraAR = array(); + + // List of fields to export + $exportFieldsAR = $_POST['fields']; + + // Topics + if (in_array('_topics', $exportFieldsAR)) { + $q = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_TOPIC . "`, `" . OCC_TABLE_REVIEWERTOPIC . "` WHERE `" . OCC_TABLE_REVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWERTOPIC . "`.`reviewerid` AND `" . OCC_TABLE_REVIEWERTOPIC . "`.`topicid`=`" . OCC_TABLE_TOPIC . "`.`topicid`"; + $r = ocsql_query($q) or err("Unable to retrieve data for export (t)", $hdr, $hdrfn); + while ($l = ocsql_fetch_assoc($r)) { + if (isset($extraAR[$l['reviewerid']]['_topics'])) { + $extraAR[$l['reviewerid']]['_topics'] .= "\n" . useTopic($l['short'], $l['topicname']); + } else { + $extraAR[$l['reviewerid']]['_topics'] = useTopic($l['short'], $l['topicname']); + } + } + } + + // Get extra fields data + if (oc_hookSet('chair-export_reviewers-data')) { + foreach ($OC_hooksAR['chair-export_reviewers-data'] as $v) { + require_once $v; + } + } + + // Get sub. data & iterate through each + $q = "SELECT *,`reviewerid` AS `id`, CONCAT_WS(' ', `name_first`, `name_last`) AS `name` FROM `" . OCC_TABLE_REVIEWER . "` ORDER BY `reviewerid`"; + $r = ocsql_query($q) or err("Unable to retrieve data for export"); + if ((ocsql_num_rows($r) == 0) && !$template) { + warn("There are no committee members to export", 'Export Committee Members', 1); + exit; + } else { // Export file + oc_export($scope, $exportFieldsAR, $fieldAR, $r, $extraAR, $OC_reviewerFieldAR); + exit; + } + +} + +// Display form +printHeader($hdr, $hdrfn); + +print ' +
    + +

    Export will generate one row/entry per committee member.

    + +

    Select Fields to Export:

    +'; + +foreach ($fieldAR as $fieldID => $fieldName) { + if (preg_match("/^skip\d+$/", $fieldID)) { + print '
    '; + continue; + } + print '
    \n"; +} + +print ' + +    +Format: +

    +
    + +

    Note: When opening up a CSV or Tab-delimited file in a spreadsheet, you may need to specify the character encoding: UTF-8.

    + +'; + +printFooter(); + +?> diff --git a/chair/export_reviews-guide.php b/chair/export_reviews-guide.php new file mode 100644 index 0000000..a1a2513 --- /dev/null +++ b/chair/export_reviews-guide.php @@ -0,0 +1,49 @@ + $v) { + print '

    ' . safeHTMLstr($v['short']) . '

    '; + if (($k != 'sessions') && isset($v['values']) && is_array($v['values'])) { + print ''; + } +} + +print ' +

    Review Completed

    + +'; + + +printFooter(); + +?> diff --git a/chair/export_reviews.php b/chair/export_reviews.php new file mode 100644 index 0000000..6244b56 --- /dev/null +++ b/chair/export_reviews.php @@ -0,0 +1,176 @@ + 'Submission ID', + 'reviewerid' => 'Reviewer ID', + 'title' => 'Submission Title', + 'name' => 'Reviewer Name', + 'score' => 'Score' +); +foreach ($OC_reviewQuestionsAR as $k => $v) { + $fieldAR[$k] = $v['short']; +} + +// value needs special handling as it's stored in DB with multiple values in a single field +if (isset($fieldAR['value'])) { + unset($fieldAR['value']); + $fieldAR['_value'] = 'Value'; +} + +// session needs special handling as it's stored in seaprate table +if (isset($fieldAR['sessions'])) { + unset($fieldAR['sessions']); + $fieldAR['_sessions'] = 'Session(s)'; +} + +$fieldAR['completed'] = 'Review Completed (True/False)'; + +// Default list of checked fields +$checkedFieldAR = array_keys($fieldAR); + +// Include extra fields +if (oc_hookSet('chair-export_reviews-fields')) { + foreach ($OC_hooksAR['chair-export_reviews-fields'] as $v) { + require_once $v; + } +} + +if (isset($_POST['submit']) && ($_POST['submit'] == "Generate File") && isset($_POST['fields']) && !empty($_POST['fields'])) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission', $hdr, $hdrfn); + } + // Verify Fields + $fieldARkeys = array_keys($fieldAR); + foreach ($_POST['fields'] as $f) { + if (!in_array($f,$fieldARkeys)) { + err('Invalid field name selection', $hdr, $hdrfn); + } + } + + // Init extra field AR + $extraAR = array(); + + // List of fields to export + $exportFieldsAR = $_POST['fields']; + + // Get extra fields data + // value + if (isset($fieldAR['_value'])) { + $q = "SELECT `paperid`, `reviewerid`, `value` FROM `" . OCC_TABLE_PAPERREVIEWER . "`"; + $r = ocsql_query($q) or err('Unable to retrieve value data for export', $hdr, $hdrfn); + while ($l = ocsql_fetch_assoc($r)) { + if (empty($l['value'])) { continue; } + $val = ''; + $vAR = explode(",", $l['value']); + foreach ($vAR as $v) { + $val .= $OC_reviewQuestionsAR['value']['values'][$v] . "; "; + } + $extraAR[$l['paperid'] . '-' . $l['reviewerid']]['_value'] = rtrim($val, "; "); + } + } + // sessions + if (isset($fieldAR['_sessions'])) { + $q = "SELECT `" . OCC_TABLE_PAPERSESSION . "`.`paperid`, `" . OCC_TABLE_PAPERSESSION . "`.`reviewerid`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short` FROM `" . OCC_TABLE_PAPERSESSION . "`, `" . OCC_TABLE_TOPIC . "` WHERE `" . OCC_TABLE_PAPERSESSION . "`.`topicid`=`" . OCC_TABLE_TOPIC . "`.`topicid`"; + $r = ocsql_query($q) or err('Unable to retrieve session data for export', $hdr, $hdrfn); + while ($l = ocsql_fetch_assoc($r)) { + if (isset($extraAR[$l['paperid'] . '-' . $l['reviewerid']]['_sessions'])) { + $extraAR[$l['paperid'] . '-' . $l['reviewerid']]['_sessions'] .= ',' . useTopic($l['short'], $l['topicname']); + } else { + $extraAR[$l['paperid'] . '-' . $l['reviewerid']]['_sessions'] = useTopic($l['short'], $l['topicname']); + } + } + } + + + if (oc_hookSet('chair-export_reviews-data')) { + foreach ($OC_hooksAR['chair-export_reviews-data'] as $v) { + require_once $v; + } + } + + // Get review data & iterate through each + $q = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.*, CONCAT_WS('-', `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`, `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`) AS `id`, `" . OCC_TABLE_PAPER . "`.`title`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name` FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` ORDER BY `paperid`, `reviewerid`"; + $r = ocsql_query($q) or err('Unable to retrieve data for export', $hdr, $hdrfn); + if (ocsql_num_rows($r) == 0) { + warn("There is no review data to export", $hdr, $hdrfn); + exit; + } else { // Export file + oc_export($scope, $exportFieldsAR, $fieldAR, $r, $extraAR, $OC_reviewQuestionsAR); + exit; + } + +} + +// Display form +printHeader($hdr, $hdrfn); + +print ' +
    + +

    Export will generate one row/entry per submission/reviewer pair.

    + +

    Select Fields to Export:

    +'; + +foreach ($fieldAR as $fieldID => $fieldName) { + if (preg_match("/^skip\d+$/", $fieldID)) { + print '
    '; + continue; + } + print '
    \n"; +} + +print ' +

    +    +Format: +

    + +

    + +
    + +

    Note: When opening up a CSV or Tab-delimited file in a spreadsheet, you may need to specify the character encoding: UTF-8.

    + +'; + +printFooter(); + +?> diff --git a/chair/import_reviewer-template.php b/chair/import_reviewer-template.php new file mode 100644 index 0000000..80afda8 --- /dev/null +++ b/chair/import_reviewer-template.php @@ -0,0 +1,36 @@ + 'id', + 'onprogramcommittee' => 'onprogramcommittee', + 'password' => 'password' +); + +foreach ($OC_reviewerFieldAR as $f => $far) { + if (preg_match("/^password/", $f)) { continue; } + $fieldAR[$f] = str_replace("\"", "\"\"", $far['short']); +} + +oc_export_headers('committee-import-template.csv', 'csv'); +print '"' . strtoupper(implode('","', $fieldAR)) . '"' . "\r\n"; +exit; + +?> \ No newline at end of file diff --git a/chair/import_reviewers.php b/chair/import_reviewers.php new file mode 100644 index 0000000..f62e1f9 --- /dev/null +++ b/chair/import_reviewers.php @@ -0,0 +1,362 @@ + 0) // not empty (redundant w/ERR) + && (($fp = fopen($_FILES['csvfile']['tmp_name'], "r")) !== false) // open ok + ) { + // retrieve existing reviewer IDs, usernames, email addresses + $reviewerIdAR = array(); + $usernameAR = array(); + $emailAR = array(); + $r = ocsql_query("SELECT `reviewerid`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "`"); + while ($l = ocsql_fetch_assoc($r)) { + $reviewerIdAR[] = $l['reviewerid']; + $usernameAR[] = $l['username']; + $emailAR[] = $l['email']; + } + // set list of field names to ID mapping + $fieldIdAR = array( + 'id' => 'reviewerid', + 'onprogramcommittee' => 'onprogramcommittee', + 'password' => 'password' + ); + $fieldNameAR = array( + 'id' => 'reviewerid', + 'onprogramcommittee' => 'onprogramcommittee', + 'password' => 'password' + ); + foreach ($OC_reviewerFieldAR as $fid => $far) { + $lowshort = strtolower($far['short']); + $fieldIdAR[$fid] = $lowshort; + $fieldNameAR[$lowshort] = $fid; + } + // retieve and check header row + $fieldMapAR = array(); + $errAR = array(); + $row = fgetcsv($fp, 0, $_POST['delimiter'], $_POST['enclosure'], $_POST['escape']); + foreach ($row as $rowid => $rowval) { + $col = strtolower($rowval); + if (isset($fieldIdAR[$col])) { + $fieldMapAR[$rowid] = $col; + } elseif (isset($fieldNameAR[$col])) { + $fieldMapAR[$rowid] = $fieldNameAR[$col]; + } elseif (!isset($_POST['skipunknown']) || ($_POST['skipunknown'] != 1)) { + $errAR[] = 'Unknown column ' . safeHTMLstr($rowval); + } + } + + // get short topics + $shortTopicAR = array(); + $shorttopr = ocsql_query("SELECT `topicid`, `short` FROM `" . OCC_TABLE_TOPIC . "`") or err('unable to retrieve short topics'); + while ($shorttopl = ocsql_fetch_assoc($shorttopr)) { + if (empty($shorttopl['short'])) { continue; } + $shortTopicAR[$shorttopl['topicid']] = $shorttopl['short']; + } + + // check for missing required field columns + if (!in_array('name_last', $fieldMapAR) || !in_array('email', $fieldMapAR)) { + $errAR[] = 'Email and Last Name field columns not found'; + } + if (count($errAR) > 0) { + print ''; + } else { + // retrieve and check data + $importAR = array(); + $rownum = 2; // skip header -- value for human consumption only + $reverseFieldMapAR = array_flip($fieldMapAR); + $reverseTopicAR = array_flip($topicAR); + $reverseShortTopicAR = array_flip($shortTopicAR); + while (($row = fgetcsv($fp, 0, $_POST['delimiter'], $_POST['enclosure'], $_POST['escape'])) !== false) { + if (count($row) < 2) { continue; } + if (!isset($row[$reverseFieldMapAR['name_last']]) || empty(trim($row[$reverseFieldMapAR['name_last']])) + || !isset($row[$reverseFieldMapAR['email']]) || empty(trim($row[$reverseFieldMapAR['email']])) + ) { + $errAR[] = 'Row ' . $rownum++ . ' missing Last Name or Email'; + continue; + } + $recordAR = array(); + foreach ($fieldMapAR as $colid => $fid) { + if (empty(trim($row[$colid]))) { + continue; + } + // check/convert encoding + if (isset($_POST['encoding']) && ($_POST['encoding'] != 'UTF-8')) { + $row[$colid] = mb_convert_encoding($row[$colid], 'UTF-8', $_POST['encoding']); + } + if ( + (function_exists('mb_detect_encoding') && (mb_detect_encoding($row[$colid], 'UTF-8', true) != 'UTF-8')) + || + !preg_match("//u", $row[$colid]) + ) { + $errAR[] = 'Row ' . $rownum . ' Invalid UTF-8 encoding for field id ' . $fid; + } + if ($fid == 'password') { + if (preg_match("/^[a-f0-9]{50}$/", $row[$colid]) || preg_match("/^\$\w\w\$\w\w\$/", $row[$colid])) { // OC encrypted password + $recordAR['password'] = $row[$colid]; + } elseif (!preg_match("/^$/", $row[$colid])) { + $recordAR['password'] = oc_password_hash($row[$colid]); + } + } elseif ($fid == 'topics') { + if (($topics = preg_split("/\n/", $row[$colid])) && (count($topics) > 0)) { + $recordAR['topics'] = array(); + foreach ($topics as $topic) { + if (empty(trim($topic))) { continue; } + if (isset($reverseShortTopicAR[$topic])) { // short topic name + $recordAR['topics'][] = $reverseShortTopicAR[$topic]; + } elseif (preg_match("/^\d+$/", $topic) && isset($topicAR[$topic])) { // topic ID + $recordAR['topics'][] = $topic; + } elseif (isset($reverseTopicAR[$topic])) { // full topic name + $recordAR['topics'][] = $reverseTopicAR[$topic]; + } else { + $errAR[] = 'Row ' . $rownum . ' Topic invalid: ' . $topic; + } + } + } else { + $errAR[] = 'Row ' . $rownum . ' Topics invalid'; + } + } elseif ($fid == 'id') { + if (preg_match("/^\d+$/", $row[$colid]) && !in_array($row[$colid], $reviewerIdAR)) { + $recordAR['reviewerid'] = $row[$colid]; + $reviewerIdAR[] = $row[$colid]; + } else { + $errAR[] = 'Row ' . $rownum . ' ID already exists or invalid'; + } + } elseif ($fid == 'email') { + if (validEmail($row[$colid]) && !in_array($row[$colid], $emailAR)) { + $recordAR['email'] = $row[$colid]; + $emailAR[] = $row[$colid]; + } else { + $errAR[] = 'Row ' . $rownum . ' Email already exists or invalid'; + } + } elseif ($fid == 'username') { + if (preg_match("/^[\p{L}\p{Nd}_\.\-\@]{5,50}$/u", $row[$colid]) && !in_array($row[$colid], $usernameAR)) { + $recordAR['username'] = $row[$colid]; + $usernameAR[] = $row[$colid]; + } else { + $errAR[] = 'Row ' . $rownum . ' Username already exists or invalid'; + } + } elseif ($fid == 'onprogramcommittee') { + if (preg_match("/^[TF]$/i", $row[$colid])) { + $recordAR['onprogramcommittee'] = strtoupper($row[$colid]); + } else { + $errAR[] = 'Row ' . $rownum . ' OnProgramCommittee invalid'; + } + } else { + if (preg_match("/^(?:checkbox|picklist)$/", $OC_reviewerFieldAR[$fid]['type'])) { // multi-select field + if (($values = preg_split("/\n/", $row[$colid])) && (count($values) > 0)) { + $recordAR[$fid] = array(); + $reverseValuesAR = array_flip($OC_reviewerFieldAR[$fid]['values']); + foreach ($values as $value) { + if (empty(trim($value))) { continue; } + if (!isset($OC_reviewerFieldAR[$fid]['usekey']) || $OC_reviewerFieldAR[$fid]['usekey']) { + if (isset($OC_reviewerFieldAR[$fid]['values'][$value])) { + $recordAR[$fid][] = $value; + } elseif (isset($reverseValuesAR[$value])) { + $recordAR[$fid][] = $reverseValuesAR[$value]; + } + } elseif (in_array($value, $OC_reviewerFieldAR[$fid]['values'])) { + $recordAR[$fid][] = $value; + } elseif ($fid == 'consent') { // override in case translated value saved + $recordAR[$fid][] = $value; + } else { + $errAR[] = 'Row ' . $rownum . ' ' . $OC_reviewerFieldAR[$fid]['short'] . ' invalid value: ' . $value; + } + } + } else { + $errAR[] = 'Row ' . $rownum . ' ' . $OC_reviewerFieldAR[$fid]['short'] . ' invalid'; + } + } else { // not multi-select field (e.g., text, textarea, dropdown, radio) + if (isset($OC_reviewerFieldAR[$fid]['values']) && !empty($OC_reviewerFieldAR[$fid]['values'])) { + if (!isset($OC_reviewerFieldAR[$fid]['usekey']) || $OC_reviewerFieldAR[$fid]['usekey']) { + $reverseValuesAR = array_flip($OC_reviewerFieldAR[$fid]['values']); + if (isset($OC_reviewerFieldAR[$fid]['values'][$row[$colid]])) { + $recordAR[$fid] = $row[$colid]; + } elseif (isset($reverseValuesAR[$row[$colid]])) { + $recordAR[$fid] = $reverseValuesAR[$row[$colid]]; + } else { + $errAR[] = 'Row ' . $rownum . ' ' . $OC_reviewerFieldAR[$fid]['short'] . ' invalid value: ' . $row[$colid]; + } + } elseif (in_array($row[$colid], $OC_reviewerFieldAR[$fid]['values'])) { + $recordAR[$fid] = $row[$colid]; + } else { + $errAR[] = 'Row ' . $rownum . ' ' . $OC_reviewerFieldAR[$fid]['short'] . ' invalid value: ' . $row[$colid]; + } + } else { + $recordAR[$fid] = $row[$colid]; + } + } + } + } + // fill in missing fields + if (!isset($recordAR['password'])) { + $recordAR['password'] = oc_password_hash(oc_password_generate()); // filler password + } + if (!isset($recordAR['username']) && isset($recordAR['email'])) { // if not present, default username to email + if (!in_array($recordAR['email'], $usernameAR)) { + $recordAR['username'] = $recordAR['email']; + $usernameAR[] = $recordAR['username']; + } else { + $errAR[] = 'Row ' . $rownum . ' cannot use email for username'; + } + } + if (!isset($recordAR['onprogramcommittee'])) { // default to not being on program committee + $recordAR['onprogramcommittee'] = 'F'; + } + if (count($recordAR) > 0) { + $importAR[] = $recordAR; + } + $rownum++; + } + if (count($errAR) == 0) { + if (count($importAR) > 0) { + // import'em Danno + foreach($importAR as $recordID => $record) { + $reviewerid = 0; + $q = "INSERT INTO `" . OCC_TABLE_REVIEWER . "` SET "; + foreach ($record as $fid => $fval) { + if ($fid == 'topics') { + continue; + } elseif ($fid == 'reviewerid') { + $reviewerid = $fval; + } + $q .= "`" . $fid . "`='" . safeSQLstr((is_array($fval) ? implode(',', $fval) : $fval)) . "', "; + } + $q .= "`lastupdate`='" . safeSQLstr(date('Y-m-d')) . "'"; + $r = ocsql_query($q) or warn('Import DB failure: (' . $recordID . ') ' . safeHTMLstr(ocsql_error())); + if ($reviewerid === 0) { + $reviewerid = ocsql_insert_id(); + } + if ( + preg_match("/^[1-9][0-9]*$/", $reviewerid) + && isset($record['topics']) + && is_array($record['topics']) + && (count($record['topics']) > 0) + ) { + $tq = ""; + foreach ($record['topics'] as $topic) { + if (preg_match("/^\d+$/", $topic)) { + $tq .= "(" . $reviewerid . "," . $topic . "),"; + } + } + if (!empty($tq)) { + $tq = "INSERT INTO `" . OCC_TABLE_REVIEWERTOPIC . "` (`reviewerid`, `topicid`) VALUES " . rtrim($tq, ','); + ocsql_query($tq) or warn('Topic import DB failure: (' . $recordID . ') ' . safeHTMLstr(ocsql_error())); + } + } + } + print '

    ' . safeHTMLstr(count($importAR)) . ' records imported

    '; + } else { + print '

    No valid reviewer records found

    '; + } + } else { + print ''; + } + } + } else { + print '

    File did not upload properly or size too large

    '; + } + + // clear out file + if (isset($_FILES['csvfile']['tmp_name']) && is_file($_FILES['csvfile']['tmp_name'])) { + unlink($_FILES['csvfile']['tmp_name']); + } + + print '
    '; +} + +// Display form + +print ' +

    Select the CSV file, then click the Import Committee Members button. The file must be in standard CSV format and have a header row that matches the committee profile form field (short) names or IDs. For a CSV file template, see below.

    + +
    + +

    CSV File:

    +

    +

    Options:

    +
    +

    +     +     + +

    +'; + +if (function_exists('mb_convert_encoding')) { + print ' +

    + +

    +'; +} + +print ' +

    + +

    +

    + +

    +
    +
    + +
    + +

    Template:

    +
    + +

    +
    + +

    Import rules:

    + + +'; + +printFooter(); + +?> diff --git a/chair/import_submissions-template.php b/chair/import_submissions-template.php new file mode 100644 index 0000000..c2c6f0d --- /dev/null +++ b/chair/import_submissions-template.php @@ -0,0 +1,57 @@ + 'Submission ID', + 'password' => 'Password', + 'submissiondate' => 'Submission Date', + 'accepted' => 'Acceptance', + 'pcnotes' => 'Chair Notes' +); + +$authorFieldAR = array(); + +foreach ($OC_submissionFieldSetAR as $fsk=>$fsv) { + foreach ($fsv['fields'] as $f) { + if (preg_match("/^password/", $f) || empty($OC_submissionFieldAR[$f]['name']) || ($OC_submissionFieldAR[$f]['type'] == 'file')) { continue; } + if ($fsk == 'fs_authors') { + $authorFieldAR[] = $f; + } else { + $fieldAR[$f] = str_replace("\"", "\"\"", $OC_submissionFieldAR[$f]['short']); + } + } +} + +for ($author=1; $author<=$_POST['maxauthors']; $author++) { + foreach ($authorFieldAR as $f) { + $fieldAR[$f . $author] = OCC_WORD_AUTHOR . ' ' . $author . ' ' . str_replace("\"", "\"\"", $OC_submissionFieldAR[$f]['short']); + } +} + +oc_export_headers('submissions-import-template.csv', 'csv'); +print '"' . strtoupper(implode('","', $fieldAR)) . '"' . "\r\n"; +exit; + +?> \ No newline at end of file diff --git a/chair/import_submissions.php b/chair/import_submissions.php new file mode 100644 index 0000000..d23fea1 --- /dev/null +++ b/chair/import_submissions.php @@ -0,0 +1,423 @@ + 0) // not empty (redundant w/ERR) + && (($fp = fopen($_FILES['csvfile']['tmp_name'], "r")) !== false) // open ok + ) { + // retrieve existing submission IDs + $submissionIdAR = array(); + $r = ocsql_query("SELECT `paperid` FROM `" . OCC_TABLE_PAPER . "`"); + while ($l = ocsql_fetch_assoc($r)) { + $submissionIdAR[] = $l['paperid']; + } + // set list of field names to ID mapping + $fieldIdAR = array( + 'paperid' => 'paperid', + 'password' => 'password', + 'submissiondate' => 'submissiondate', + 'pcnotes' => 'pcnotes' + ); + $fieldNameAR = array( + 'submission id' => 'paperid', + 'password' => 'password', + 'submission date' => 'submissiondate', + 'chair notes' => 'pcnotes' + + ); + $authorFieldIdAR = array(); + $authorFieldNameAR = array(); + foreach ($OC_submissionFieldSetAR as $fsk=>$fsv) { + foreach ($fsv['fields'] as $fid) { + if (preg_match("/^password/", $fid) || preg_match("/[\'\"]/", $OC_submissionFieldAR[$fid]['short'])) { continue; } + $lowshort = strtolower($OC_submissionFieldAR[$fid]['short']); + if ($fsk == 'fs_authors') { + $authorFieldIdAR[$fid] = $lowshort; + $authorFieldNameAR[$lowshort] = $fid; + } else { + $fieldIdAR[$fid] = $lowshort; + $fieldNameAR[$lowshort] = $fid; + } + } + } + + // retieve and check header row + $fieldMapAR = array(); + $authorFieldMapAR = array(); + $errAR = array(); + $row = fgetcsv($fp, 0, $_POST['delimiter'], $_POST['enclosure'], $_POST['escape']); + foreach ($row as $rowid => $rowval) { + if (preg_match("/^" . OCC_WORD_AUTHOR . " (\d+) (.*)$/i", $rowval, $matches)) { + $authornum = $matches[1]; + $col = strtolower($matches[2]); + if (isset($authorFieldIdAR[$col])) { + $fieldMapAR[$rowid] = $col . '-' . $authornum; + } elseif (isset($authorFieldNameAR[$col])) { + $fieldMapAR[$rowid] = $authorFieldNameAR[$col] . '-' . $authornum; + } elseif (!isset($_POST['skipunknown']) || ($_POST['skipunknown'] != 1)) { + $errAR[] = 'Unknown column ' . safeHTMLstr($rowval); + } + } else { + $col = strtolower($rowval); + if (isset($fieldIdAR[$col])) { + $fieldMapAR[$rowid] = $col; + } elseif (isset($fieldNameAR[$col])) { + $fieldMapAR[$rowid] = $fieldNameAR[$col]; + } elseif (!isset($_POST['skipunknown']) || ($_POST['skipunknown'] != 1)) { + $errAR[] = 'Unknown column ' . safeHTMLstr($rowval); + } + } + } + + // get short topics + $shortTopicAR = array(); + $shorttopr = ocsql_query("SELECT `topicid`, `short` FROM `" . OCC_TABLE_TOPIC . "`") or err('unable to retrieve short topics'); + while ($shorttopl = ocsql_fetch_assoc($shorttopr)) { + if (empty($shorttopl['short'])) { continue; } + $shortTopicAR[$shorttopl['topicid']] = $shorttopl['short']; + } + + // check for missing required field columns + if ( + !in_array('title', $fieldMapAR) + || !in_array('name_last-1', $fieldMapAR) + || !in_array('email-1', $fieldMapAR) + ) { + $errAR[] = 'Title (title), ' . safeHTMLstr(OCC_WORD_AUTHOR) . ' 1 Last Name (name_last-1), or Author 1 Email (email-1) field columns not found'; + } + if (count($errAR) > 0) { + print ''; + } else { + // retrieve and check data + $importAR = array(); + $rownum = 2; // skip header -- value for human consumption only + $reverseFieldMapAR = array_flip($fieldMapAR); + $reverseTopicAR = array_flip($topicAR); + $reverseShortTopicAR = array_flip($shortTopicAR); + $today = date('Y-m-d'); + while (($row = fgetcsv($fp, 0, $_POST['delimiter'], $_POST['enclosure'], $_POST['escape'])) !== false) { + $recordAR = array(); + if (count($row) < 3) { + $errAR[] = 'Row ' . $rownum++ . ' skipped'; + continue; + } + // check for title, author 1 last name & email + if ( + !isset($row[$reverseFieldMapAR['title']]) || empty(trim($row[$reverseFieldMapAR['title']])) + || !isset($row[$reverseFieldMapAR['name_last-1']]) || empty(trim($row[$reverseFieldMapAR['name_last-1']])) + || !isset($row[$reverseFieldMapAR['email-1']]) || !validEmail(trim($row[$reverseFieldMapAR['email-1']])) + ) { + $errAR[] = 'Row ' . $rownum++ . ' missing or invalid Title, ' . safeHTMLstr(OCC_WORD_AUTHOR) . ' 1 Last Name, or ' . safeHTMLstr(OCC_WORD_AUTHOR) . ' 1 Email'; + continue; + } + // check for contact (if > 1) last name & email + if ( + isset($reverseFieldMapAR['contactid']) + && preg_match("/^(?:Author |" . OCC_WORD_AUTHOR . " |)(\d+)$/", $row[$reverseFieldMapAR['contactid']], $cidmatch) + ) { + $recordAR['contactid'] = $cidmatch[1]; + if ( + ($row[$cidmatch[1]] > 1) + && ( + !isset($reverseFieldMapAR['name_last-'.$cidmatch[1]]) + || empty($row[$reverseFieldMapAR['name_last-'.$cidmatch[1]]]) + || !isset($reverseFieldMapAR['email-'.$cidmatch[1]]) + || !validEmail($row[$reverseFieldMapAR['email-'.$cidmatch[1]]]) + ) + ) { + $errAR[] = 'Row ' . $rownum++ . ' missing or invalid ' . safeHTMLstr(OCC_WORD_AUTHOR) . ' ' . $cidmatch[1] . ' Last Name or ' . safeHTMLstr(OCC_WORD_AUTHOR) . ' ' . $cidmatch[1] . ' Email'; + continue; + } + } else { + $recordAR['contactid'] = 1; + } + // check non-empty fields + foreach ($fieldMapAR as $colid => $fid) { + if (empty(trim($row[$colid]))) { + continue; + } + // check/convert encoding + if (isset($_POST['encoding']) && ($_POST['encoding'] != 'UTF-8') && in_array($_POST['encoding'], $encodingAR)) { + $row[$colid] = mb_convert_encoding($row[$colid], 'UTF-8', $_POST['encoding']); + } + if ( + (function_exists('mb_detect_encoding') && (mb_detect_encoding($row[$colid], 'UTF-8', true) != 'UTF-8')) + || + !preg_match("//u", $row[$colid]) + ) { + $errAR[] = 'Row ' . $rownum . (isset($recordAR['paperid']) ? (' (ID ' . safeHTMLstr($recordAR['paperid']) . ') ') : '') . 'Invalid UTF-8 encoding for field id ' . $fid; + } + if ($fid == 'password') { + if (preg_match("/^[a-f0-9]{50}$/", $row[$colid]) || preg_match("/^\$\w\w\$\w\w\$/", $row[$colid])) { // OC encrypted password + $recordAR['password'] = $row[$colid]; + } elseif (!preg_match("/^$/", $row[$colid])) { + $recordAR['password'] = oc_password_hash($row[$colid]); + } + } elseif ($fid == 'topics') { + if (($topics = preg_split("/\n/", $row[$colid])) && (count($topics) > 0)) { + $recordAR['topics'] = array(); + foreach ($topics as $topic) { + if (empty(trim($topic))) { continue; } + if (isset($reverseShortTopicAR[$topic])) { // short topic name + $recordAR['topics'][] = $reverseShortTopicAR[$topic]; + } elseif (preg_match("/^\d+$/", $topic) && isset($topicAR[$topic])) { // topic ID + $recordAR['topics'][] = $topic; + } elseif (isset($reverseTopicAR[$topic])) { // full topic name + $recordAR['topics'][] = $reverseTopicAR[$topic]; + } else { + $errAR[] = 'Row ' . $rownum . (isset($recordAR['paperid']) ? (' (ID ' . safeHTMLstr($recordAR['paperid']) . ') ') : '') . 'Topic invalid: ' . $topic; + } + } + } elseif (!preg_match("/^$/", $row[$colid])) { + $errAR[] = 'Row ' . $rownum . (isset($recordAR['paperid']) ? (' (ID ' . safeHTMLstr($recordAR['paperid']) . ') ') : '') . ' Topics invalid'; + } + } elseif ($fid == 'paperid') { + if (preg_match("/^\d+$/", $row[$colid]) && !in_array($row[$colid], $submissionIdAR)) { + $recordAR['paperid'] = $row[$colid]; + $submissionIdAR[] = $row[$colid]; + } elseif (!preg_match("/^$/", $row[$colid])) { + $errAR[] = 'Row ' . $rownum . ' (ID ' . safeHTMLstr($row[$colid]) . ') Submission ID already exists or invalid'; + } + } elseif ($fid == 'accepted') { + if (in_array($row[$colid], $OC_acceptedValuesAR)) { + $recordAR['accepted'] = $row[$colid]; + } elseif (!preg_match("/^$/", $row[$colid])) { + $errAR[] = 'Row ' . $rownum . (isset($recordAR['paperid']) ? (' (ID ' . safeHTMLstr($recordAR['paperid']) . ') ') : '') . ' Accepted invalid'; + } + } elseif ($fid == 'submissiondate') { + if (preg_match("/^\d{4}-\d\d-\d\d$/", $row[$colid])) { + $recordAR['submissiondate'] = $row[$colid]; + } elseif (!preg_match("/^$/", $row[$colid])) { + $errAR[] = 'Row ' . $rownum . (isset($recordAR['paperid']) ? (' (ID ' . safeHTMLstr($recordAR['paperid']) . ') ') : '') . ' Submission Date invalid'; + } + } else { + if (preg_match("/^(.*)-(\d+)$/", $fid, $fmatches)) { + $usefid = $fmatches[1]; + } else { + $usefid = $fid; + } + if (preg_match("/^(?:checkbox|picklist)$/", $OC_submissionFieldAR[$usefid]['type'])) { // multi-select field + if (($values = preg_split("/\n/", $row[$colid])) && (count($values) > 0)) { + $recordAR[$fid] = array(); + $reverseValuesAR = array_flip($OC_submissionFieldAR[$usefid]['values']); + foreach ($values as $value) { + if (empty(trim($value))) { continue; } + if (!isset($OC_submissionFieldAR[$usefid]['usekey']) || $OC_submissionFieldAR[$usefid]['usekey']) { + if (isset($OC_submissionFieldAR[$usefid]['values'][$value])) { + $recordAR[$fid][] = $value; + } elseif (isset($reverseValuesAR[$value])) { + $recordAR[$fid][] = $reverseValuesAR[$value]; + } + } elseif (in_array($value, $OC_submissionFieldAR[$usefid]['values'])) { + $recordAR[$fid][] = $value; + } elseif ($fid == 'consent') { // override in case translated value saved + $recordAR[$fid][] = $value; + } else { + $errAR[] = 'Row ' . $rownum . ' ' . (isset($recordAR['paperid']) ? ('(ID ' . safeHTMLstr($recordAR['paperid']) . ') ') : '') . $OC_submissionFieldAR[$usefid]['short'] . ' invalid value: ' . $value; + } + } + } else { + $errAR[] = 'Row ' . $rownum . ' ' . $OC_submissionFieldAR[$usefid]['short'] . ' invalid'; + } + } else { // not multi-select field (e.g., text, textarea, dropdown, radio) + if (isset($OC_submissionFieldAR[$usefid]['values']) && !empty($OC_submissionFieldAR[$usefid]['values'])) { + if (!isset($OC_submissionFieldAR[$usefid]['usekey']) || $OC_submissionFieldAR[$usefid]['usekey']) { + $reverseValuesAR = array_flip($OC_submissionFieldAR[$usefid]['values']); + if (isset($OC_submissionFieldAR[$usefid]['values'][$row[$colid]])) { + $recordAR[$fid] = $row[$colid]; + } elseif (isset($reverseValuesAR[$row[$colid]])) { + $recordAR[$fid] = $reverseValuesAR[$row[$colid]]; + } else { + $errAR[] = 'Row ' . $rownum . ' ' . (isset($recordAR['paperid']) ? ('(ID ' . safeHTMLstr($recordAR['paperid']) . ') ') : '') . $OC_submissionFieldAR[$usefid]['short'] . ' invalid value: ' . $row[$colid]; + } + } elseif (in_array($row[$colid], $OC_submissionFieldAR[$usefid]['values'])) { + $recordAR[$fid] = $row[$colid]; + } else { + $errAR[] = 'Row ' . $rownum . ' ' . (isset($recordAR['paperid']) ? ('(ID ' . safeHTMLstr($recordAR['paperid']) . ') ') : '') . $OC_submissionFieldAR[$usefid]['short'] . ' invalid value: ' . $row[$colid]; + } + } else { + $recordAR[$fid] = $row[$colid]; + } + } + } + } + // fill in missing fields + if (!isset($recordAR['password'])) { + $recordAR['password'] = oc_password_hash(oc_password_generate()); // filler password + } + if (!isset($recordAR['submissiondate'])) { + $recordAR['submissiondate'] = $today; + } + + if (count($recordAR) > 0) { + $importAR[] = $recordAR; + } + $rownum++; + } + if (count($errAR) == 0) { + if (count($importAR) > 0) { + // import'em Danno + foreach($importAR as $recordID => $record) { + $paperid = 0; + $authorAR = array(); + $q = "INSERT INTO `" . OCC_TABLE_PAPER . "` SET "; + foreach ($record as $fid => $fval) { + if ($fid == 'topics') { + continue; + } elseif ($fid == 'paperid') { + $paperid = $fval; + } + if (preg_match("/^(.*)-(\d+)$/", $fid, $amatches)) { + $authorAR[$amatches[2]][$amatches[1]] = $fval; + } else { + $q .= "`" . $fid . "`='" . safeSQLstr((is_array($fval) ? implode(',', $fval) : $fval)) . "', "; + } + } + $q .= "`lastupdate`='" . safeSQLstr($today) . "'"; + $r = ocsql_query($q) or warn(safeHTMLstr('Import DB failure: (' . ($recordID+2) . ') ' . ocsql_error())); + if ($paperid === 0) { + $paperid = ocsql_insert_id() or warn('Invalid Submission ID (0) returned by database'); + } + // import topics + if ( + preg_match("/^[1-9][0-9]*$/", $paperid) + && isset($record['topics']) + && is_array($record['topics']) + && (count($record['topics']) > 0) + ) { + $tq = ""; + foreach ($record['topics'] as $topic) { + if (preg_match("/^\d+$/", $topic)) { + $tq .= "(" . $paperid . "," . $topic . "),"; + } + } + if (!empty($tq)) { + $tq = "INSERT INTO `" . OCC_TABLE_PAPERTOPIC . "` (`paperid`, `topicid`) VALUES " . rtrim($tq, ','); + ocsql_query($tq) or warn(safeHTMLstr('Topic import DB failure: (' . ($recordID+2) . ') ' . ocsql_error())); + } + } + // import authors + foreach ($authorAR as $authorpos => $authorinfo) { + $aq = "INSERT INTO `" . OCC_TABLE_AUTHOR . "` SET `paperid`='" . safeSQLstr($paperid) . "', `position`='" . safeSQLstr($authorpos) . "', "; + foreach ($authorinfo as $fid => $fval) { + $aq .= "`" . $fid . "`='" . safeSQLstr((is_array($fval) ? implode(',', $fval) : $fval)) . "', "; + } + ocsql_query(rtrim($aq, ', ')) or warn(safeHTMLstr(OCC_WORD_AUTHOR . ' ' . $authorpos . ' import DB failure: (' . ($recordID+2) . ') ' . ocsql_error())); + } + } + print '

    ' . safeHTMLstr(count($importAR)) . ' records imported. List submissions

    '; + } else { + print '

    No valid submission records found

    '; + } + } else { + print ''; + } + } + } else { + print '

    File did not upload properly or size too large

    '; + } + + // clear out file + if (isset($_FILES['csvfile']['tmp_name']) && is_file($_FILES['csvfile']['tmp_name'])) { + unlink($_FILES['csvfile']['tmp_name']); + } + + print '
    '; +} + +// Display form + +print ' +

    Select the CSV file, then click the Import Submissions button. The file must be in standard CSV format and have a header row that matches the submission form field (short) names or IDs. For a CSV file template, see below.

    + +
    + +

    CSV File:

    +

    +

    Options:

    +
    +

    +     +     + +

    +'; + +if (function_exists('mb_convert_encoding')) { + print ' +

    + +

    +'; +} + +print ' +

    + +

    +

    + +

    +
    +
    + +
    + +

    Template:

    +
    + +

    Maximum number of ' . safeHTMLstr(OCC_WORD_AUTHOR) . 's:

    +
    + +

    Import rules:

    + + +'; + +printFooter(); + +?> diff --git a/chair/index.php b/chair/index.php new file mode 100644 index 0000000..824e577 --- /dev/null +++ b/chair/index.php @@ -0,0 +1,269 @@ +';$zl=''; + +/*** DO NOT MODIFY THE FOLLOWING CODE BLOCK BELOW OR OTHERWISE DISABLE IT ***/if ((OCC_LICENSE != 'Public') && defined('OCC_LICENSE_EVENT')) { if (defined('OCHS')) { print '
    Account Information*

    Event:
    ' . safeHTMLstr(OCC_LICENSE_EVENT) . '

    Hosting End Date:
    ' . safeHTMLstr(OCC_END_DATE) . '

    Prepaid Submissions:*
    ' . safeHTMLstr(OCC_SUBS) . '

    ';$z='f';} else { print '
    License Information*

    License Type:
    ' . safeHTMLstr(OCC_LICENSE_TYPE) . '

    License Expires:*
    ' . safeHTMLstr(OCC_LICENSE_EXPIRES) . '

    Licensed Event:
    '; if (substr(md5($zl=OCC_LICENSE_EVENT.OCC_LICENSE_TYPE.OCC_LICENSE_EXPIRES), 0, 3) == OCC_LICENSE_){$z='f';$zz=safeHTMLstr(OCC_LICENSE_EVENT);}else{$zz=base64_decode('PHNwYW4gY2xhc3M9ImVyciI+VGhpcyBldmVudCBhcHBlYXJzIHRvIGJlIGltcHJvcGVybHkgbGljZW5zZWQ7IGNvbnRhY3QgPGEgaHJlZj0iaHR0cDovL3d3dy5vcGVuY29uZi5jb20vY29udGFjdC8iPk9wZW5Db25mIFN1cHBvcnQ8L2E+PC9zcGFuPg==');$z='ff';} print $zz.'

    '; }}else{$z='f';}/*** DO NOT MODIFY THE PREVIOUS CODE BLOCK BELOW OR OTHERWISE DISABLE IT ***/ + +// Check for new version +if (($OC_configAR['OC_version'] < $OC_configAR['OC_versionLatest']) && isset($_SERVER['SERVER_NAME']) && !preg_match("/openconf\.(?:com|org)$/i", $_SERVER['SERVER_NAME'])){ + print '
    New Version Available

    Download OpenConf ' . $OC_configAR['OC_versionLatest'] . '

    Backup & install files

    Complete upgrade

    '; +} + +/*** DO NOT MODIFY THE FOLLOWING CODE BLOCK BELOW OR OTHERWISE DISABLE IT ***/if (OCC_LICENSE == 'Public') { print '
    Upgrade to OpenConf Professional Edition
    and enhance your experience

    Order Now

    '; }/*** DO NOT MODIFY THE PREVIOUS CODE BLOCK ABOVE OR OTHERWISE DISABLE IT ***/ + +print ''; + +// Upgrade pending +if (is_file('../upgrade/v') && ($version = file_get_contents('../upgrade/v'))) { + $version = trim($version); + if (preg_match("/^\d+\.\d+$/", $version) && ($version > $OC_configAR['OC_version'])) { // notify if upgrade needs to be completed + print '
    Looks like you installed a new version of the software. Click here to complete the upgrade.
    '; + } else { + unlink('../upgrade/v'); // already upgraded; try removing upgrade/v + } +} + +// Top hook +if (isset($OC_hooksAR['chair-menu-top']) && !empty($OC_hooksAR['chair-menu-top'])) { + foreach ($OC_hooksAR['chair-menu-top'] as $v) { + print $v; + } +} + +// Default menus +print ' +

    Summary

    + +

    Email  (log) +'; + +// messages in queue? +$r = ocsql_query("SELECT COUNT(*) FROM `" . OCC_TABLE_EMAIL_QUEUE . "` WHERE `sent` IS NULL AND `tries`<1") or err('Unable to retrieve failed message count'); +$l = ocsql_fetch_row($r); +if (defined('OCC_LI'.'CENSE')) { $zl.=OCC_LICENSE; } +if ($l[0] > 0) { + print ' — messages in queue (send now)'; +} + +print ' +

    +'; + +if (isset($OC_hooksAR['chair-menu-top2']) && !empty($OC_hooksAR['chair-menu-top2'])) { + foreach ($OC_hooksAR['chair-menu-top2'] as $v) { + print $v; + } +} + +// get topic count +$r = ocsql_query("SELECT COUNT(*) FROM `" . OCC_TABLE_TOPIC . "`") or err('Unable to retrieve topic count'); +$l = ocsql_fetch_row($r); +$topicCount = $l[0]; + +print ' +

    Settings:

    + + +

    Submissions:

    + + +

    Committee Members:

    + +'; + +print ' +

    Assignments:

    + + +

    Selection:

    + +'; + +if (oc_hookSet('chair-menu-extras')) { + foreach ($OC_hooksAR['chair-menu-extras'] as $v) { + if (isset($v['title']) && !empty($v['title'])) { + print '

    ' . safeHTMLstr($v['title']) . ':

    \n"; + } else { + print $v['extras']; + } + }} + if (!isset($z)||($z!='f')) { + print ''; +} + +printFooter(); + +?> diff --git a/chair/install-account.php b/chair/install-account.php new file mode 100644 index 0000000..4336745 --- /dev/null +++ b/chair/install-account.php @@ -0,0 +1,81 @@ +Step 2 of 5: Create ' . OCC_WORD_CHAIR . ' Account

    '; + +if (!empty($e)) { + print '

    ' . $e . '

    '; +} + +print ' +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
     5–50 letters or numbers
     
     10+ characters
      
       
    + +
    + +'; + +printFooter(); +?> diff --git a/chair/install-complete.php b/chair/install-complete.php new file mode 100644 index 0000000..60f16ae --- /dev/null +++ b/chair/install-complete.php @@ -0,0 +1,57 @@ +Congratulations, you have completed the OpenConf installation!

    +

    Proceed to your OpenConf Home Page

    +

    OpenConf logo

    +'; + +clearstatcache(); + +if (!is_writable($OC_configAR['OC_paperDir'])) { +print ' +

    NOTE: Before accepting file uploads, you will need to change permissions of the file upload directory (default: data/papers/) so that the Web (HTTP) server process has read-write privileges.

    +'; +} + +printFooter(); + +?> diff --git a/chair/install-db.php b/chair/install-db.php new file mode 100644 index 0000000..094c19d --- /dev/null +++ b/chair/install-db.php @@ -0,0 +1,296 @@ +' . safeHTMLstr(mysqli_connect_error()); + } else { + // Specify UTF-8 use for connection + if (mysqli_query($dbtest, "SET NAMES " . OCC_DB_ENCODING . " COLLATE " . OCC_DB_COLLATION)) { + // Create DB? + if (isset($_POST['dbcreate']) && ($_POST['dbcreate'] == 1)) { + if (preg_match("/^[\w-]+$/", $_POST['dbname'])) { + $q = "CREATE DATABASE `" . $_POST['dbname'] . "` DEFAULT CHARACTER SET " . OCC_DB_ENCODING . " DEFAULT COLLATE " . OCC_DB_COLLATION; + if (!mysqli_query($dbtest, $q) && (mysqli_errno($dbtest) != 1007)) { // 1007=exists + $e = 'Unable to create database ' . safeHTMLstr($_POST['dbname']) . ". DB Error:
    " . safeHTMLstr(mysqli_error($dbtest) . " (" . mysqli_errno($dbtest) . ")"); + } + } else { + $e = 'Database name limited to letters, numbers, hyphen, and underscore'; + } + } + } else { + $e = 'Unable to set database connection with encoding ' . OCC_DB_ENCODING . ' and collation ' . OCC_DB_COLLATION . '. Check the MySQL version.'; + } + if (empty($e)) { + // Check prefix + if (!empty($_POST['dbprefix']) && (!preg_match("/^[\w-]{0,40}$/",$_POST['dbprefix']))) { + $e = 'Invalid table prefix; use up to 40 letters, numbers, and the underscore.'; + } + // Attempt to access DB + elseif (!mysqli_select_db($dbtest, $_POST['dbname'])) { + $e = 'Unable to access database ' . safeHTMLstr($_POST['dbname']); + } + else { // Save db info + if (! $fp = fopen(OCC_LIB_DIR . 'config-sample.php', 'r')) { + err('Config template file (lib/config-sample.php) does not exist. Check that you have a full OpenConf distribution and click the Restart Install link above.', $hdr, $hdrfn, false); + } + if (!$optionFile = fread($fp, filesize(OCC_LIB_DIR . 'config-sample.php'))) { + fclose($fp); + err("Unable to read from config file", $hdr, $hdrfn, false); + } + fclose($fp); + replaceConstantValue('OCC_SESSION_VAR_NAME', 'OPENCONF' . substr(oc_idGen(),3,4), $optionFile); // assign a (hopefully) unique session name in case of multiple installations + replaceConstantValue('OCC_ENC_KEY', oc_idGen(64), $optionFile); // assign a unique encryption key + replaceConstantValue('OCC_DB_USER', $_POST['dbuser'], $optionFile); + replaceConstantValue('OCC_DB_PASSWORD', $_POST['dbpw'], $optionFile); + replaceConstantValue('OCC_DB_HOST', $_POST['dbhost'], $optionFile); + replaceConstantValue('OCC_DB_PORT', $_POST['dbport'], $optionFile); + replaceConstantValue('OCC_DB_NAME', $_POST['dbname'], $optionFile); + replaceConstantValue('OCC_DB_PREFIX', $_POST['dbprefix'], $optionFile); + replaceConstantValue('OCC_DB_USE_SSL', ((isset($_POST['dbssl']) && ($_POST['dbssl'] == 1)) ? 1 : 0), $optionFile); + replaceConstantValue('OCC_DB_SSL_NOVERIFY', ((isset($_POST['dbssl_noverify']) && ($_POST['dbssl_noverify'] == 1)) ? 1 : 0), $optionFile); + replaceConstantValue('OCC_DB_SSL_KEY', varValue('dbssl_key', $_POST), $optionFile); + replaceConstantValue('OCC_DB_SSL_CERT', varValue('dbssl_cert', $_POST), $optionFile); + replaceConstantValue('OCC_DB_SSL_CA', varValue('dbssl_ca', $_POST), $optionFile); + replaceConstantValue('OCC_DB_SSL_CAPATH', varValue('dbssl_capth', $_POST), $optionFile); + replaceConstantValue('OCC_DB_SSL_CIPHER', varValue('dbssl_cipher', $_POST), $optionFile); + if (! $fp = fopen(OCC_CONFIG_FILE,'w')) { + err('Config file (config.php) cannot be created or is not writeable. Try creating a blank config.php file manually and ensure file permissions allow config.php to be written to by the server; then click the Restart Install link above.', $hdr, $hdrfn, false); + } + if (!fwrite($fp, $optionFile)) { + fclose($fp); + err("Unable to write to config file", $hdr, $hdrfn, false); + } + fclose($fp); + + // Load schema + if (isset($_POST['dbschema']) && ($_POST['dbschema'] == 1)) { + if ($dbfile = file_get_contents(OCC_LIB_DIR . "DB.sql")) { + // create tables + if (preg_match_all("/(CREATE [^;]+);/", $dbfile, $matches)) { + foreach ($matches[1] as $m) { + // add table prefix + $m = preg_replace("/(CREATE TABLE `?)/", "$1" . slashQuote(stripslashes($_POST['dbprefix'])), $m); + // add encoding and collation + $m .= " DEFAULT CHARACTER SET " . OCC_DB_ENCODING . " COLLATE " . OCC_DB_COLLATION; + if (!mysqli_query($dbtest, $m)) { + $e = "Error on loading schema -- " . safeHTMLstr(mysqli_error($dbtest)) . ".
    Database may need to be reset"; + break; + } + } + } else { + err("No schema found in DB.sql file", $hdr, $hdrfn, false); + } + // insert data + if (empty($e) && preg_match_all("/(INSERT [^;]+);/", $dbfile, $matches)) { + foreach ($matches[1] as $m) { + // add table prefix + $m = preg_replace("/(INSERT INTO `?)/", "$1" . slashQuote(stripslashes($_POST['dbprefix'])), $m); + if (!mysqli_query($dbtest, $m)) { + $e = "Error on loading schema -- " . safeHTMLstr(mysqli_error($dbtest)) . ".
    Database may need to be reset"; + break; + } + } + } + } else { + $e = 'Unable to load schema from DB.sql. Try loading it manually (see INSTALL instructions).'; + } + } + if (empty($e)) { + mysqli_close($dbtest); + header("Location: install-account.php"); + exit; + } + } + } + mysqli_close($dbtest); + } + } + $dbuser = varValue('dbuser', $_POST); + $dbname = varValue('dbname', $_POST); + $dbhost = varValue('dbhost', $_POST); + $dbport = varValue('dbport', $_POST, 3306); + $dbprefix = varValue('dbprefix', $_POST); + $dbssl = varValue('dbssl', $_POST); + $dbssl_noverify = varValue('dbssl_verify', $_POST); + $dbssl_key = varValue('dbssl_key', $_POST); + $dbssl_cert = varValue('dbssl_cert', $_POST); + $dbssl_ca = varValue('dbssl_ca', $_POST); + $dbssl_capath = varValue('dbssl_capath', $_POST); + $dbssl_cipher = varValue('dbssl_cipher', $_POST); +} else { + $dbuser = (defined('OCC_DB_USER') ? OCC_DB_USER : ''); + $dbname = (defined('OCC_DB_NAME') ? OCC_DB_NAME : ''); + $dbhost = (defined('OCC_DB_HOST') ? OCC_DB_HOST : ''); + $dbport = (defined('OCC_DB_PORT') ? OCC_DB_PORT : 3306); + $dbprefix = (defined('OCC_DB_PREFIX') ? OCC_DB_PREFIX : ''); + $dbssl = (defined('OCC_DB_USE_SSL') ? OCC_DB_USE_SSL : ''); + $dbssl_noverify = (defined('OCC_DB_SSL_NOVERIFY') ? OCC_DB_SSL_NOVERIFY : 1); + $dbssl_key = (defined('OCC_DB_SSL_KEY') ? OCC_DB_SSL_KEY : ''); + $dbssl_cert = (defined('OCC_DB_SSL_CERT') ? OCC_DB_SSL_CERT : ''); + $dbssl_ca = (defined('OCC_DB_SSL_CA') ? OCC_DB_SSL_CA : ''); + $dbssl_capath = (defined('OCC_DB_SSL_CAPATH') ? OCC_DB_SSL_CAPATH : ''); + $dbssl_cipher = (defined('OCC_DB_SSL_CIPHER') ? OCC_DB_SSL_CIPHER : ''); +} + +printHeader($hdr,$hdrfn); + +print '

    Step 1 of 5: Enter Database Settings

    '; + +if (!empty($e)) { + print '

    ' . $e . '

    '; +} + +print ' + + +
    +'; + +print ' +
    +Database General Settings +
    The database user must have the following database privileges: ALTER, CREATE, DELETE, DROP, INSERT, SELECT, TRUNCATE, UPDATE
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +valid characters:  a-z   0-9   _   - +
    +
    + + +optional +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +Database SSL Settings +
    All fields are optional. Enter full path names.
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + +

    + +
    + +

    The above information is stored in config.php'; + +if (defined('OCC_DB_NAME') && (OCC_DB_NAME != '')) { + print '.
    If you already configured config.php and loaded the schema, you may skip to the next step.'; +} + +print ' +

    + + +'; + +printFooter(); +?> diff --git a/chair/install-include.php b/chair/install-include.php new file mode 100644 index 0000000..09897d3 --- /dev/null +++ b/chair/install-include.php @@ -0,0 +1,26 @@ +Install has already been completed. To go through the installation again, first reset OCC_INSTALL_COMPLETE in config.php, then visit/reload this page again. Otherwise, proceed to the OpenConf Home Page'; + printFooter(); + exit; +} + +?> diff --git a/chair/install-license.php b/chair/install-license.php new file mode 100644 index 0000000..32e5c9c --- /dev/null +++ b/chair/install-license.php @@ -0,0 +1,25 @@ +contact OpenConf support.', $hdr, $hdrfn);}elseif ($u==3){warn('The OpenConf License installed is not valid. Please contact OpenConf support for assistance.', $hdr, $hdrfn);}}header("Location: install-db.php"); + } else { + printHeader($hdr,$hdrfn); + print '

    You must agree to the OpenConf License in order to install or use this software.

    '; + } +} else { + header("Location: install.php"); +} + +printFooter(); +?> diff --git a/chair/install.php b/chair/install.php new file mode 100644 index 0000000..427e2f2 --- /dev/null +++ b/chair/install.php @@ -0,0 +1,64 @@ + +

    Welcome to OpenConf! This appears to be a new install, so we will take you through the set-up and configuration of your OpenConf system. Following are the steps to install OpenConf:

    + +

    +1. Enter Database Settings +  –>   +2. Create ' . OCC_WORD_CHAIR . ' Account +  –>   +3. Tailor Configuration Settings +  –>   +4. Set Topics +  –>   +5. Open Submissions & Sign-Up/In +

    + +'; + +function stripDDS($f) { + return(preg_replace("/\.\.\//","",$f)); +} + +$e = ""; +clearstatcache(); +if ((is_file(OCC_CONFIG_FILE) && !is_writable(OCC_CONFIG_FILE)) && (!defined('OCC_DB_NAME') || (OCC_DB_NAME == ''))) { + print ' +

    Before proceeding, you must allow write privilege by the Web server (HTTP) process to the config.php files.

    +'; +} else { + print ' +
    +

    When you are ready to proceed, read the OpenConf License below and click the I Agree button to indicate your agreement to its terms:

    +


    +

    +
    +'; +} + +print ' +
    +

    If you have already installed OpenConf but are still seeing this page, change the value of OCC_INSTALL_COMPLETE in config.php

    + +'; + +printFooter(); + +?> diff --git a/chair/list_advocates.php b/chair/list_advocates.php new file mode 100644 index 0000000..8c44576 --- /dev/null +++ b/chair/list_advocates.php @@ -0,0 +1,195 @@ +\n"; + } + } + print "

    Advocate(s) have been unassigned.

    \n"; + if (isset($_POST['s'])) { + print '

    Return to Advocate Listings

    '; + } + printFooter(); + exit; +} + +if (!isset($_GET['s']) || ($_GET['s'] == "pid")) { + $sortby = "`paperid`"; + $pidsort='S-ID
    ' . $OC_sortImg; + $psort='Submission'; + $nsort='Advocate'; + $aidsort='A-ID'; + $_GET['s'] = 'pid'; +} elseif ($_GET['s'] == "paper") { + $sortby = "`title`"; + $pidsort='S-ID'; + $psort="Submission
    " . $OC_sortImg; + $nsort='Advocate'; + $aidsort='A-ID'; +} elseif ($_GET['s'] == "name") { + $sortby = "`name_last`, `name_first`"; + $pidsort='S-ID'; + $psort='Submission'; + $nsort="Advocate
    " . $OC_sortImg; + $aidsort='A-ID'; +} elseif ($_GET['s'] == "aid") { + $sortby = "`advocateid`"; + $pidsort='S-ID'; + $psort='Submission'; + $nsort='Advocate'; + $aidsort='A-ID
    ' . $OC_sortImg; +} else { + err("Unknown sort source"); +} + +// Display Filter +$aAR = array_keys($OC_acceptanceColorAR); +$aAR[] = 'Pending'; +print ' +
    +
    +  '; +if (count($subTypeAR) > 0) { + print '  '; +} +print ' +
    +
    +'; + +$q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`, `adv_recommendation`, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `title` FROM `" . OCC_TABLE_PAPER . "` LEFT JOIN `" . OCC_TABLE_PAPERADVOCATE . "` ON `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERADVOCATE . "`.`paperid` LEFT JOIN `" . OCC_TABLE_REVIEWER . "` ON `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; +switch($atype) { + case '': + break; + case 'Pending': + $q .= " WHERE (`" . OCC_TABLE_PAPER . "`.`accepted`='' OR `" . OCC_TABLE_PAPER . "`.`accepted` IS NULL) "; + break; + default: + $q .= " WHERE `" . OCC_TABLE_PAPER . "`.`accepted`='" . safeSQLstr($atype) . "' "; + break; +} +switch($stype) { + case '': + break; + default: + $q .= (preg_match("/ WHERE /", $q) ? ' AND ' : ' WHERE ') . "`" . OCC_TABLE_PAPER . "`.`type`='" . safeSQLstr($stype) . "' "; + break; +} +$q .= " ORDER BY " . $sortby; +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + print 'No advocates found.

    '; +} else { + print ' +

    +
    Links:
    +
    Recom. – Show recommendation
    +
    Submission – Show Submission info
    +
    Advocate – Show Advocate info
    +
    + + + +
    + + + + + + '; + $row = 1; + while ($l = ocsql_fetch_array($r)) { + print ''; + if (empty($l['adv_recommendation'])) { + print ""; + } else { + print ''; + } + print ''; + if (empty($l['advocateid'])) { + print ""; + } else { + print '' . + ''; + } + print ""; + if ($row==1) { $row=2; } else { $row=1; } + } + print ' + +
       

    Recom.' . $pidsort . '' . $psort . '' . $aidsort . '' . $nsort . '
     ' . safeHTMLstr($l['adv_recommendation']) . '' . safeHTMLstr($l['paperid']) . '' . safeHTMLstr($l['title']) . '   ' . safeHTMLstr($l['advocateid']) . '' . safeHTMLstr($l['name']) . '


       
    +
    +'; +} + +printFooter(); + +?> diff --git a/chair/list_authors.php b/chair/list_authors.php new file mode 100644 index 0000000..294c917 --- /dev/null +++ b/chair/list_authors.php @@ -0,0 +1,92 @@ +' . $OC_sortImg; + $nsort = '' . OCC_WORD_AUTHOR . ''; +} else { + $sortby = "`name_last`, `name_first`"; + $idsort = 'Submission ID. Title'; + $nsort = '' . OCC_WORD_AUTHOR. '
    ' . $OC_sortImg; +} + +printHeader('All ' . OCC_WORD_AUTHOR . 's', 1); + +$accOptions = ''; +foreach ($OC_acceptanceValuesAR as $idx => $acc) { + $accOptions .= ''; +} + +print ' +
    + +

    + + +

    +
    +'; + +$q = "SELECT `" . OCC_TABLE_AUTHOR . "`.`name_last`, `" . OCC_TABLE_AUTHOR . "`.`name_first`, `" . OCC_TABLE_AUTHOR . "`.`email`, `" . OCC_TABLE_AUTHOR . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title` FROM `" . OCC_TABLE_AUTHOR . "`, `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` " . $accSQL . " ORDER BY $sortby"; +$r = ocsql_query($q) or err("Unable to get " . oc_strtolower(OCC_WORD_AUTHOR) . "s"); +if (ocsql_num_rows($r) == 0) { print 'No submissions have been made yet.

    '; } +else { + $currid = null; + $row = 2; // Seed at 2 to handle same IDs + print ''; + if (isset($_REQUEST['s']) && ($_REQUEST['s'] == "id")) { + while ($l = ocsql_fetch_array($r)) { + if ($l['paperid'] == $currid) { + print ''; + } else { + $row = $rowAR[$row]; + print ''; + $currid = $l['paperid']; + } + } + } else { + while ($l = ocsql_fetch_array($r)) { + if ($l['email'] == $currid) { + print ''; + } else { + $row = $rowAR[$row]; + print ''; + } + $currid = $l['email']; + } + } + print "
    ' . $nsort . '' . $idsort . '
    ' . safeHTMLstr($l['name_first']) . ' ' . safeHTMLstr($l['name_last']) . ' 
    ' . safeHTMLstr($l['name_first']) . ' ' . safeHTMLstr($l['name_last']) . '' . $l['paperid'] . '. ' . safeHTMLstr($l['title']) . '
     ' . $l['paperid'] . '. ' . safeHTMLstr($l['title']) . '
    ' . safeHTMLstr($l['name_first']) . ' ' . safeHTMLstr($l['name_last']) . '' . $l['paperid'] . '. ' . safeHTMLstr($l['title']) . '

    \n"; +} + +printFooter(); + +?> diff --git a/chair/list_authors_country.php b/chair/list_authors_country.php new file mode 100644 index 0000000..89a42b6 --- /dev/null +++ b/chair/list_authors_country.php @@ -0,0 +1,108 @@ + $acc) { + $accOptions .= ''; +} + +print ' +

    + +

    + + +

    +
    +'; + +$q = "SELECT `country`, COUNT(*) AS `num` FROM `" . OCC_TABLE_AUTHOR . "`, `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_AUTHOR . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_AUTHOR . "`.`position`=`" . OCC_TABLE_PAPER . "`.`contactid` $accSQL GROUP BY `country` ORDER BY `num` DESC"; +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + print 'No submissions available

    '; +} else { + print ' +

    Note: Only the country of the contact ' . oc_strtolower(OCC_WORD_AUTHOR) . ' is used for reporting

    + +'; + if (isset($_REQUEST['s']) && ($_REQUEST['s'] == "num")) { + print ''; + $resAR = array(); + $nocountry = 0; + while ($l = ocsql_fetch_array($r)) { + if (empty($l['country']) || !isset($OC_countryAR[$l['country']])) { + $nocountry += $l['num']; + } else { + if (!isset($resAR[$l['num']])) { + $resAR[$l['num']] = array(); + } + $resAR[$l['num']][] = $OC_countryAR[$l['country']]; + } + } + $row = 1; + foreach ($resAR as $num => $countries) { + sort($countries, SORT_LOCALE_STRING); + print '\n"; + if ($row==1) { $row=2; } else { $row=1; } + } + if ($nocountry > 0) { + print '\n"; + } + } else { + print ''; + $resAR = array(); + $nocountry = 0; + while ($l = ocsql_fetch_array($r)) { + if (!empty($l['country']) && isset($OC_countryAR[$l['country']])) { + $resAR[$OC_countryAR[$l['country']]] = $l['num']; + } else { + $nocountry = $l['num']; + } + } + ksort($resAR, SORT_LOCALE_STRING); + $row = 1; + foreach ($resAR as $country => $num) { + print '\n"; + if ($row==1) { $row=2; } else { $row=1; } + } + if ($nocountry > 0) { + print '\n"; + } + } + + print "
    CountryCount
    ' . $OC_sortImg . '
    ' . implode('
    ', $countries) . '
    ' . $num . "
    unknown' . $nocountry . "
    Country
    ' . $OC_sortImg . '
    Count
    ' . $country . '' . $num . "
    unknown' . $nocountry . "
    \n"; +} + +printFooter(); + +?> diff --git a/chair/list_config.php b/chair/list_config.php new file mode 100644 index 0000000..26d6393 --- /dev/null +++ b/chair/list_config.php @@ -0,0 +1,58 @@ + + + +'; + +printHeader('Settings Directory', 1); + +print '

    Advanced Configuration

    '; + +$q = "SELECT `setting`, `name`, `description` FROM `" . OCC_TABLE_CONFIG . "` WHERE `module`='OC' ORDER BY `module`, `setting`"; +$r = ocsql_query($q) or err('Unable to retrieve OpenConf settings'); + +$row = 1; +print ''; +while ($l = ocsql_fetch_assoc($r)) { + print '\n"; + $row = (($row == 1) ? 2 : 1); +} + +$q = "SELECT `module`, `setting`, `name`, `description` FROM `" . OCC_TABLE_CONFIG . "` WHERE `module`!='OC' ORDER BY `module`, `setting`"; +$r = ocsql_query($q) or err('Unable to retrieve module settings'); + +$module = ''; +while ($l = ocsql_fetch_assoc($r)) { + if ($l['module'] != $module) { + $module = $l['module']; + print ''; + } + print '\n"; + $row = (($row == 1) ? 2 : 1); +} + +print '
    SettingNameDescription
    ' . safeHTMLstr($l['setting']) . '' . safeHTMLstr($l['name']) . '' . $l['description'] . "
    ' . safeHTMLstr($OC_modulesAR[$l['module']]['name']) . ' Module' . (oc_moduleActive($l['module']) ? '' : ' - Inactive') . '
    ' . safeHTMLstr($l['setting']) . '' . safeHTMLstr($l['name']) . '' . $l['description'] . "
    '; + +printFooter(); + +?> \ No newline at end of file diff --git a/chair/list_conflicts.php b/chair/list_conflicts.php new file mode 100644 index 0000000..bcedb86 --- /dev/null +++ b/chair/list_conflicts.php @@ -0,0 +1,197 @@ +\n"; + } + } + print '

    Conflicts have been unset.

    '; + print '

    Return to Conflict Listings

    '; + printFooter(); + exit; + } elseif ($_POST['ocaction'] == 'update') { + if (isset($_POST['alloworgconflict']) && ($_POST['alloworgconflict'] == 'no')) { + updateConfigSetting('OC_allowOrgConflict', 0); + $OC_configAR['OC_allowOrgConflict'] = 0; + } else { + updateConfigSetting('OC_allowOrgConflict', 1); + $OC_configAR['OC_allowOrgConflict'] = 1; + } + if (isset($_POST['allowemailconflict']) && ($_POST['allowemailconflict'] == 'no')) { + updateConfigSetting('OC_allowEmailConflict', 0); + $OC_configAR['OC_allowEmailConflict'] = 0; + } else { + updateConfigSetting('OC_allowEmailConflict', 1); + $OC_configAR['OC_allowEmailConflict'] = 1; + } + } +} + +$pq = "SELECT `" . OCC_TABLE_CONFLICT . "`.`paperid`, `" . OCC_TABLE_CONFLICT . "`.`reviewerid`, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `title` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_CONFLICT . "` WHERE `" . OCC_TABLE_CONFLICT . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_CONFLICT . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + +if (empty($_GET['s']) || ($_GET['s'] == "pid")) { + $q = $pq . " ORDER BY `" . OCC_TABLE_CONFLICT . "`.`paperid`, `" . OCC_TABLE_CONFLICT . "`.`reviewerid`"; + $sortid = "paper"; + $pidsort='P-ID
    ' . $OC_sortImg; + $psort='Submission'; + $rsort='Reviewer'; + $ridsort='R-ID'; +} elseif ($_GET['s'] == "paper") { + $q = $pq . " ORDER BY `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_CONFLICT . "`.`reviewerid`"; + $sortid = "paper"; + $pidsort='P-ID'; + $psort="Submission
    " . $OC_sortImg; + $rsort='Reviewer'; + $ridsort='R-ID'; +} elseif ($_GET['s'] == "rid") { + $q = $pq . " ORDER BY `" . OCC_TABLE_CONFLICT . "`.`reviewerid`, `" . OCC_TABLE_CONFLICT . "`.`paperid`"; + $sortid = "reviewer"; + $pidsort='P-ID'; + $psort='Submission'; + $rsort='Reviewer'; + $ridsort='R-ID
    ' . $OC_sortImg; +} elseif ($_GET['s'] == "reviewer") { + $q = $pq . " ORDER BY `" . OCC_TABLE_REVIEWER . "`.`name_last`, `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_CONFLICT . "`.`paperid`"; + $sortid = "reviewer"; + $pidsort='P-ID'; + $psort='Submission'; + $rsort="Reviewer
    " . $OC_sortImg; + $ridsort= 'R-ID'; +} else { + err("Unknown sort source"); +} + +print ' +

    Manually Set Conflicts: [set]

    +'; + +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + print '

          No conflicts have been set.

    '; +} else { + $s = substr($sortid, 0, 1); + + print ' +
    + + + + + + '; + $currid = -1; + $row = 1; + while ($l = ocsql_fetch_array($r)) { + + if ($sortid == "reviewer") { + $ptags = ''; + $rtags = ''; + } else { + $ptags = ''; + $rtags = ''; + } + + $blanktags = ''; + + if ($currid != $l[$sortid.'id']) { + if ($currid != -1) { + if ($row==1) { $row=2; } else { $row=1; } + } + $currid = $l[$sortid.'id']; + } else { + if ($sortid == "reviewer") { $rtags = $blanktags; } + else { $ptags = $blanktags; } + } + + print '' . $ptags . $rtags; + print ''; + + print "\n"; + } + print ' + +
    ' . $pidsort . '' . $psort . '' . $ridsort . '' . $rsort . 'UC
    '.$l['paperid'].'' . safeHTMLstr($l['title']) . '' . $l['reviewerid'] . '' . safeHTMLstr($l['name']) . ''.$l['paperid'].'' . safeHTMLstr($l['title']) . ''.$l['reviewerid'].'' . safeHTMLstr($l['name']) . '  
    '; + if (empty($l['reviewerid'])) { print ' '; } + else { + print ''; + } + print '
    +'; +} + +// Show auto-detected conflicts +print ' +


    +

    Automatically Detected Conflicts:

    +
    + +

             

    +
    +'; + +if (($OC_configAR['OC_allowEmailConflict'] == 1) && ($OC_configAR['OC_allowOrgConflict'] == 1)) { + print '

    Auto-conflict detection is disabled; change settings above.

    '; +} else { + $q = "SELECT `" . OCC_TABLE_AUTHOR . "`.`paperid`, `reviewerid`, `title`, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name` FROM `" . OCC_TABLE_AUTHOR . "`, `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_REVIEWER . "` WHERE " . + "`" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` AND ("; + if ($GLOBALS['OC_configAR']['OC_allowEmailConflict'] == 0) { + $q .= " (`" . OCC_TABLE_AUTHOR . "`.`email`=`" . OCC_TABLE_REVIEWER . "`.`email`)"; + } + if ($GLOBALS['OC_configAR']['OC_allowOrgConflict'] == 0) { + if ($GLOBALS['OC_configAR']['OC_allowEmailConflict'] == 0) { + $q .= " OR"; + } + $q .= " (`" . OCC_TABLE_AUTHOR . "`.`organization` <> '' AND `" . OCC_TABLE_AUTHOR . "`.`organization`=`" . OCC_TABLE_REVIEWER . "`.`organization`)"; + } + $q .= ") GROUP BY `paperid`, `reviewerid`, `title`, `name` ORDER BY `paperid`, `reviewerid`"; + $r = ocsql_query($q) or err("Unable to get auto paper/reviewer conflicts"); + if (ocsql_num_rows($r) < 1) { + print '

          No conflicts detected

    '; + } else { + print ''; + $row = 1; + while ($l=ocsql_fetch_array($r)) { + print ''; + $row = $rowAR[$row]; + } + print '
    SubmissionReviewer
    ' . $l['paperid'] . '. ' . safeHTMLstr($l['title']) . '' . $l['reviewerid'] .'. ' . safeHTMLstr($l['name']) . '

    For a match to occur, the email address or organization name must be exactly the same.

    '; + } +} + +// Check for addt'l (hook) conflict displays +if (isset($OC_hooksAR['list_conflicts-display']) && !empty($OC_hooksAR['list_conflicts-display'])) { + foreach ($OC_hooksAR['list_conflicts-display'] as $hook) { + print '


    '; + require_once $hook; + } +} + +printFooter(); + +?> diff --git a/chair/list_paper_dir.php b/chair/list_paper_dir.php new file mode 100644 index 0000000..0f1f7b1 --- /dev/null +++ b/chair/list_paper_dir.php @@ -0,0 +1,108 @@ +Unable to delete file ' . safeHTMLstr($file) . '

    '; + } + issueSQL("UPDATE `" . OCC_TABLE_PAPER . "` SET " . $formatField . "=NULL WHERE `paperid`='" . safeSQLstr($filematch[1]) . "' AND " . $formatField . "='" . safeSQLstr($filematch[2]) . "' LIMIT 1"); + } + } +} + +// Display files +if ($pdh = opendir($dir)) { + $fAR = array(); + while(($f = readdir($pdh)) !== false) { + if (is_file($dir.$f) && !in_array($f,$skipAR)) { + $fAR[$f] = oc_fileMtime($dir.$f); + } + } + closedir($pdh); + + if (oc_hookSet('chair-list_files')) { + foreach ($GLOBALS['OC_hooksAR']['chair-list_files'] as $hook) { + require_once $hook; + } + } + + $type = ((isset($_GET['oc_multifile_type']) && ctype_digit($_GET['oc_multifile_type'])) ? urlencode($_GET['oc_multifile_type']) : 1); + + if (count($fAR) > 0) { + if (isset($_GET['s']) && ($_GET['s'] == 'date')) { + $dsort = 'Last Updated
    ' . $OC_sortImg; + $fsort = 'File'; + arsort($fAR,SORT_NUMERIC); + } else { + $fsort = 'File
    ' . $OC_sortImg; + $dsort = 'Last Updated'; + ksort($fAR,SORT_NUMERIC); + } + + print '
    icon
    ZIP
    all files
    icon
    ZIP
    accepted only
    '; + + print ' +
    + + + + +'; + $row = 1; + foreach ($fAR as $f => $d) { + print '\n"; + $row = $rowAR[$row]; + } + print ' + +
     ' . $fsort . 'Size' . $dsort . '
    ' . urlencode($f) . '' . safeHTMLstr(oc_formatNumber(oc_fileSize($dir.$f))) . '' . safeHTMLstr(date("d M Y H:i:s", $d)) . "
    + + +
    +
    +
    +'; + } else { // 0 files + print '

    No files found

    '; + } +} else { + print '

    Unable to open files directory

    '; +} + +printFooter(); + +?> diff --git a/chair/list_papers.js b/chair/list_papers.js new file mode 100644 index 0000000..374eac5 --- /dev/null +++ b/chair/list_papers.js @@ -0,0 +1,44 @@ +// +----------------------------------------------------------------------+ +// | OpenConf | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +// +----------------------------------------------------------------------+ +// | This source file is subject to the OpenConf License, available on | +// | the OpenConf web site: www.OpenConf.com | +// +----------------------------------------------------------------------+ + +var oc_ftAR = new Array(); +var oc_accAR = new Array(); + +// Updates checkboxes based on form selection +function selectBoxes() { + var boxSelectID = document.getElementById("boxselect"); + var boxSelect = boxSelectID.options[boxSelectID.selectedIndex].value; + if (boxSelect == "all") { + for (i=0; i= 0) { + document.subsForm.elements[i].checked=true; + } else { + document.subsForm.elements[i].checked=false; + } + } + } + } else if (boxSelect in oc_accAR) { + for (i=0; i= 0) { + document.subsForm.elements[i].checked=true; + } else { + document.subsForm.elements[i].checked=false; + } + } + } + } +} diff --git a/chair/list_papers.php b/chair/list_papers.php new file mode 100644 index 0000000..1a3cdee --- /dev/null +++ b/chair/list_papers.php @@ -0,0 +1,342 @@ +File'; // table header used for file column +$formatField = '`format`'; // paper table format field + +beginChairSession(); + +oc_addJS('chair/list_papers.js'); + +// Retrieve submission types - do it here as used for filtering validation below +$subTypeAR = array(); +$r = ocsql_query("SELECT DISTINCT `type` FROM `" . OCC_TABLE_PAPER . "` WHERE `type` IS NOT NULL AND `type`!='' ORDER BY `type`") or err('Unable to retrieve submission types', 'Submissions', 1); +while ($l = ocsql_fetch_assoc($r)) { + $subTypeAR[$l['type']] = substr($l['type'], 0, 50); +} + +// Filter? +$atype = (isset($_SESSION[OCC_SESSION_VAR_NAME]['chairvars']['accfilter']) ? $_SESSION[OCC_SESSION_VAR_NAME]['chairvars']['accfilter'] : ''); // accepteance type +$stype = (isset($_SESSION[OCC_SESSION_VAR_NAME]['chairvars']['typefilter']) ? $_SESSION[OCC_SESSION_VAR_NAME]['chairvars']['typefilter'] : ''); // submission type +if (isset($_POST['fsubmit']) && ($_POST['fsubmit'] == 'Filter')) { + if (!isset($_POST['atype']) || empty($_POST['atype'])) { + $atype = ''; + } elseif (($_POST['atype'] == 'Pending') || isset($OC_acceptanceColorAR[$_POST['atype']])) { + $atype = $_POST['atype']; + } + $_SESSION[OCC_SESSION_VAR_NAME]['chairvars']['accfilter'] = $atype; + if (!isset($_POST['stype']) || empty($_POST['stype']) || !isset($subTypeAR[$_POST['stype']])) { + $stype = ''; + } else { + $stype = $_POST['stype']; + } + $_SESSION[OCC_SESSION_VAR_NAME]['chairvars']['typefilter'] = $stype; + session_write_close(); +} + +printHeader("Submissions",1); + +$verbAR = array( + 'Delete Submissions' => 'deleted', + 'Delete Withdrawn Submissions' => 'deleted', + 'Withdraw Submissions' => 'withdrawn', + 'Restore Submissions' => 'restored' +); + +if (isset($_POST['subaction']) && isset($verbAR[$_POST['subaction']])) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + if (preg_match("/^(Delete|Withdraw) Submissions$/", $_POST['subaction']) && isset($_POST['papers']) && !empty($_POST['papers'])) { + foreach ($_POST['papers'] as $paperid) { + if (preg_match("/^\d+$/",$paperid)) { + // withdraw? + $log = true; + if ($_POST['subaction'] == 'Withdraw Submissions') { + print "

    withdrawing id $paperid ... "; + if (! withdrawPaper($paperid, OCC_WORD_CHAIR)) { + print 'SUBMISSION NOT FOUND'; + } + print "

    \n"; + $log = false; + } else { + print "

    deleting id $paperid ...

    \n"; + } + // delete paper + deletePaper($paperid, $log); + } else { + print "Unable to process submission id " . safeHTMLstr($paperid) . ".

    \n"; + } + } + if (($miv = ini_get('max_input_vars')) && (count($_POST['papers']) > ($miv - 10))) { + print '

    The number of submissions selected may have been greater than supported by this server. Additional passes may be required.

    '; + } + } elseif (preg_match("/^(Restore|Delete Withdrawn) Submissions$/", $_POST['subaction']) && isset($_POST['wpapers']) && !empty($_POST['wpapers'])) { + foreach ($_POST['wpapers'] as $paperid) { + if (preg_match("/^\d+$/",$paperid)) { + if ($_POST['subaction'] == 'Restore Submissions') { // restore? + print "

    restoring id $paperid ... "; + $ret = restorePaper($paperid); + if ($ret != $paperid) { + if ($ret === null) { + print 'SUBMISSION NOT FOUND'; + } else { + print 'Duplicate ID -- New ID Assigned: ' . safeHTMLstr($ret) . ''; + } + } + print "

    \n"; + } elseif ($_POST['subaction'] == 'Delete Withdrawn Submissions') { // delete withdrawn? + print "

    deleting withdrawn id $paperid ... "; + if ( ! ocsql_query("DELETE FROM `" . OCC_TABLE_WITHDRAWN . "` WHERE `paperid`='" . safeSQLstr($paperid) . "' LIMIT 1") ) { + print 'DELETION FAILED'; + } + print "

    \n"; + } + } else { + print "Unable to process submission id " . safeHTMLstr($paperid) . ".

    \n"; + } + } + if (($miv = ini_get('max_input_vars')) && (count($_POST['wpapers']) > ($miv - 10))) { + print '

    The number of submissions selected may have been greater than supported by this server. Additional passes may be required.

    '; + } + } + + print '

    Return to Submission Listings

    '; + printFooter(); + exit; +} + +// Headers & Sorting +$rsortstr = 'ID'; +$tsortstr = 'Title'; +$nsortstr = 'Contact ' . OCC_WORD_AUTHOR . ''; +$ssortstr = 'Stud.'; +$stsortstr = 'Type'; + +if (!isset($_GET['s'])) { + $_GET['s'] = 'id'; +} +switch ($_GET['s']) { + case 'id': + $sortby = "`paperid`"; + $rsortstr = 'ID
    ' . $OC_sortImg; + break; + case 'title': + $sortby = "`title`"; + $tsortstr = 'Title
    ' . $OC_sortImg; + break; + case 'student': + $sortby = "`student`, `paperid`"; + $ssortstr = 'Stud.
    ' . $OC_sortImg; + break; + case 'type': + $sortby = "`type`, `paperid`"; + $stsortstr = 'Type
    ' . $OC_sortImg; + break; + case 'name': + default: + $sortby = "`name_last`, `name_first`"; + $nsortstr = 'Contact ' . OCC_WORD_AUTHOR . '
    ' . $OC_sortImg; + $_GET['s'] = 'id'; + break; +} + +// Display Filter +$aAR = array_keys($OC_acceptanceColorAR); +$aAR[] = 'Pending'; +print ' +
    +
    +  '; +if (count($subTypeAR) > 0) { + print '  '; +} +print ' +
    +
    +'; + +// Students? +$OC_trackStudent = false; +$sr = ocsql_query("SELECT COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` WHERE `student`='T'") or err('Unable to check student field'); +if (($sl = ocsql_fetch_assoc($sr)) && ($sl['count'] > 0)) { + $OC_trackStudent = true; +} + +// Type? +$OC_trackType = false; +$sr = ocsql_query("SELECT COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` WHERE `type`!='' AND `type` IS NOT NULL") or err('Unable to check type field'); +if (($sl = ocsql_fetch_assoc($sr)) && ($sl['count'] > 0)) { + $OC_trackType = true; +} + +// Extra fields init for hook +$extraFields = ''; + +// Hook +if (oc_hookSet('chair-list_papers-preprocess')) { + foreach ($OC_hooksAR['chair-list_papers-preprocess'] as $v) { + require_once $v; + } +} + +// Iterate through subs +$q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, CONCAT_WS(' ', `name_first`, `name_last`) AS `name`, `" . OCC_TABLE_PAPER . "`.`accepted`, `" . OCC_TABLE_PAPER . "`.`title`, " . $formatField . ", `" . OCC_TABLE_PAPER . "`.`student`, `" . OCC_TABLE_PAPER . "`.`type`" . $extraFields . " FROM `" . OCC_TABLE_PAPER . "` LEFT JOIN `" . OCC_TABLE_AUTHOR . "` ON (`" . OCC_TABLE_AUTHOR . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_AUTHOR . "`.`position`=`" . OCC_TABLE_PAPER . "`.`contactid`) WHERE 1=1 "; +switch($atype) { + case '': + break; + case 'Pending': + $q .= "AND (`accepted`='' OR `accepted` IS NULL) "; + break; + default: + $q .= "AND `accepted`='" . safeSQLstr($atype) . "' "; + break; +} +switch($stype) { + case '': + break; + default: + $q .= "AND `type`='" . safeSQLstr($stype) . "' "; + break; +} +$q .= "ORDER BY $sortby"; +$r = ocsql_query($q) or err("Unable to get submissions"); +if (ocsql_num_rows($r) == 0) { + print '

    No submissions available.

    '; +} else { + print ' +
    + + +

    Number of Submissions: ' . ocsql_num_rows($r) . '

    +

    + + +

    + + + '; + + if ($OC_trackStudent) { + print ''; + } + + if ($OC_trackType) { + print ''; + } + + print $fileTableHeader . ' +'; + + $row = 1; + $missingFileAR = array(); // global var hack bec. call_user_func does not allow pass by reference for non-object + $OC_downloadZipAR = array(); + while ($l = ocsql_fetch_array($r)) { + print ''; + + if ($OC_trackStudent) { + print ''; + } + + if ($OC_trackType) { + print ''; + } + + print oc_printFileCells($l, true) . "\n"; + + $accCountAR[(empty($l['accepted']) ? 'Pending' : $l['accepted'])][] = $l['paperid']; + + if ($row==1) { $row=2; } else { $row=1; } + } + + $skipCells = 4 + ($OC_trackStudent ? 1 : 0) + ($OC_trackType ? 1 : 0); + print ''; + if (class_exists('ZipArchive')) { + if (oc_hookSet('print_file_cells_zip')) { + $str = call_user_func($GLOBALS['OC_hooksAR']['print_file_cells_zip'][0], $row, 0, 0, false); // only one hook allowed here + print $str; + } elseif (isset($OC_downloadZipAR[1]) && ($OC_downloadZipAR[1] > 1)) { + print ''; + } + } + print ' +
    ' . $rsortstr . '' . $tsortstr . '' . $nsortstr . '' . $ssortstr . '' . $stsortstr . '
    ' . $l['paperid'] . '' . safeHTMLstr($l['title']) . '' . safeHTMLstr($l['name']) . ''. (($l['student'] == 'T') ? '' : ' ') . '' . varValue('type', $l, ' ', true) . '
     
    ' . oc_('Download All') . '
    ZIP
    +

    Note: When deleting a submission, all records associated with the submission are permanently removed. When withdrawing a submission, all reviews and assignments, uploaded files, etc, are permanently removed; the submission and ' . oc_strtolower(OCC_WORD_AUTHOR) . ' table data however may be restored if submission-related modules have not been uninstalled.

    +
    + + +'; +} + +$q = "SELECT `paperid`, `title`, `contact_author`, `contact_email`, `withdraw_date`, `withdrawn_by` FROM `" . OCC_TABLE_WITHDRAWN . "` ORDER BY `paperid`"; +$r = ocsql_query($q) or err('Unable to check for withdrawn submissions'); +if ((ocsql_num_rows($r) > 0) && empty($atype) && empty($stype)) { + print ' + +


    + +

    Withdrawn Submissions

    + +
    + + + +'; + + $row = 1; + while ($l = ocsql_fetch_assoc($r)) { + print ''; + if ($row==1) { $row=2; } else { $row=1; } + } + +print ' +
    IDTitleContact ' . OCC_WORD_AUTHOR . 'Withdrawn By / On
    ' . $l['paperid'] . '' . safeHTMLstr($l['title']) . '' . safeHTMLstr($l['contact_author']) . '' . safeHTMLstr($l['withdrawn_by']) . ' / ' . safeHTMLstr($l['withdraw_date']) . '
    +
     
    +

    Note: Restoring a withdrawn submission will not restore all the submission data, only the information stored in the submission (paper) and ' . oc_strtolower(OCC_WORD_AUTHOR) . 's (author) table.

    +
    +'; +} + +printFooter(); + +?> diff --git a/chair/list_reviewers.php b/chair/list_reviewers.php new file mode 100644 index 0000000..f117095 --- /dev/null +++ b/chair/list_reviewers.php @@ -0,0 +1,170 @@ +All Committee Members'; + print ' +
    + +

    + + +

    +
    +'; +} + +if (isset($_POST['faction']) && isset($_POST['revids']) && !empty($_POST['revids'])) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + if ($_POST['faction'] == "Delete Members") { // delete members + foreach ($_POST['revids'] as $reviewerid) { + if (preg_match("/^\d+$/", $reviewerid)) { + oc_deleteAssignments(null, $reviewerid, 'advocate'); + oc_deleteAssignments(null, $reviewerid); + issueSQL("DELETE FROM `" . OCC_TABLE_REVIEWERTOPIC . "` WHERE `reviewerid`='" . safeSQLstr($reviewerid) . "'"); + issueSQL("DELETE FROM `" . OCC_TABLE_REVIEWER . "` WHERE `reviewerid`='" . safeSQLstr($reviewerid) . "'"); + + if (oc_hookSet('delete_reviewer')) { + foreach ($GLOBALS['OC_hooksAR']['delete_reviewer'] as $inc) { + include $inc; + } + } + } + } + } elseif ($_POST['faction'] == "Add to PC") { // add to program committee + foreach ($_POST['revids'] as $reviewerid) { + if (preg_match("/^\d+$/", $reviewerid)) { + issueSQL("UPDATE " . OCC_TABLE_REVIEWER . " SET `onprogramcommittee`='T' WHERE `reviewerid`='" . safeSQLstr($reviewerid) . "' LIMIT 1"); + } + } + } elseif ($_POST['faction'] == "Remove from PC") { // remove from program committee + foreach ($_POST['revids'] as $reviewerid) { + if (preg_match("/^\d+$/", $reviewerid)) { + oc_deleteAssignments(null, $reviewerid, 'advocate'); + issueSQL("UPDATE `" . OCC_TABLE_REVIEWER . "` SET `onprogramcommittee`='F' WHERE `reviewerid`='" . safeSQLstr($reviewerid) . "' LIMIT 1"); + } + } + } +} + +if (!isset($_REQUEST['s']) || empty($_REQUEST['s']) || ($_REQUEST['s'] == "id")) { + $sortby = "`reviewerid`"; + $rsortstr = 'ID
    ' . $OC_sortImg; + $pcsortstr = 'PC'; + $nsortstr = 'Name'; +} elseif ($_REQUEST['s'] == "pc") { + $sortby = "`onprogramcommittee`, `name_last`, `name_first`"; + $pcsortstr = 'PC
    ' . $OC_sortImg; + $rsortstr = 'ID'; + $nsortstr = 'Name'; +} else { // name sort + $sortby = "`name_last`, `name_first`"; + $nsortstr = 'Name
    ' . $OC_sortImg; + $rsortstr = 'ID'; + $pcsortstr = 'PC'; +} + +$q = "SELECT `reviewerid`, CONCAT_WS(' ',`name_first`,`name_last`) AS `name`, `username`, `email`, `onprogramcommittee`, `comments` FROM `" . OCC_TABLE_REVIEWER . "` $cmtAdd ORDER BY $sortby"; +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + print 'No committee members have signed up yet

    '; +} else { + print ' +

    Count: ' . ocsql_num_rows($r) . '

    +

    Note: If you choose to delete committee member(s), all review ' . ($OC_configAR['OC_paperAdvocates'] ? 'and advocacy ' : '') . ' data will also be deleted.

    +
    + + +
    +'; + if (isset($_REQUEST['s'])) { + print ''; + } + print ' + + + +'; + if (empty($_REQUEST['cmt'])) { + print ''; + } + print ''; + $row = 1; + while ($l = ocsql_fetch_array($r)) { + print ''; + if (empty($_REQUEST['cmt'])) { + print ''; + } + print '\n"; + if ($row==1) { $row=2; } else { $row=1; } +} + print ' + +
    +'; + if ($OC_configAR['OC_paperAdvocates']) { + if ($cmt != 'pc') { + print '     '; + } + if ($cmt != 'rev') { + print '     '; + } + } + print ' +
    ' . $rsortstr . '' . $pcsortstr . '' . $nsortstr . 'UsernameComments
    '; + if ($l['onprogramcommittee'] == 'T') { + print ''; + } else { + print " "; + } + print '' . safeHTMLstr($l['name']) . ''.$l['username'].'' . safeHTMLstr($l['comments']) . "  
    +'; + if ($OC_configAR['OC_paperAdvocates']) { + if ($cmt != 'pc') { + print '     '; + } + if ($cmt != 'rev') { + print '     '; + } + } + print ' +
    + +
    +
    +'; +} + +printFooter(); + +?> diff --git a/chair/list_reviewers_country.php b/chair/list_reviewers_country.php new file mode 100644 index 0000000..542354f --- /dev/null +++ b/chair/list_reviewers_country.php @@ -0,0 +1,104 @@ +All Committee Members'; + print ' +
    + +

    + + +

    +
    +'; +} + +$q = "SELECT `country`, COUNT(`reviewerid`) AS `num` FROM `" . OCC_TABLE_REVIEWER . "` $cmtSQL GROUP BY `country` ORDER BY `num` DESC"; +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + print 'No committee members have signed up yet

    '; +} else { + print ' + +'; + if (!isset($_REQUEST['s']) || ($_REQUEST['s'] == "country")) { + print ''; + $resAR = array(); + $nocountry = 0; + while ($l = ocsql_fetch_array($r)) { + if (!empty($l['country']) && isset($OC_countryAR[$l['country']])) { + $resAR[$OC_countryAR[$l['country']]] = $l['num']; + } else { + $nocountry = $l['num']; + } + } + ksort($resAR, SORT_LOCALE_STRING); + $row = 1; + foreach ($resAR as $country => $num) { + print '\n"; + if ($row==1) { $row=2; } else { $row=1; } + } + if ($nocountry > 0) { + print '\n"; + } + } else { + print ''; + $resAR = array(); + $nocountry = 0; + while ($l = ocsql_fetch_array($r)) { + if (empty($l['country']) || !isset($OC_countryAR[$l['country']])) { + $nocountry += $l['num']; + } else { + if (!isset($resAR[$l['num']])) { + $resAR[$l['num']] = array(); + } + $resAR[$l['num']][] = $OC_countryAR[$l['country']]; + } + } + $row = 1; + foreach ($resAR as $num => $countries) { + sort($countries, SORT_LOCALE_STRING); + print '\n"; + if ($row==1) { $row=2; } else { $row=1; } + } + if ($nocountry > 0) { + print '\n"; + } + } + + print "
    Country
    ' . $OC_sortImg . '
    Count
    ' . $country . '' . $num . "
    unknown' . $nocountry . "
    CountryCount
    ' . $OC_sortImg . '
    ' . implode('
    ', $countries) . '
    ' . $num . "
    unknown' . $nocountry . "
    \n"; +} + +printFooter(); + +?> diff --git a/chair/list_reviews.php b/chair/list_reviews.php new file mode 100644 index 0000000..6f913d4 --- /dev/null +++ b/chair/list_reviews.php @@ -0,0 +1,235 @@ +S-ID
    ' . $OC_sortImg; + $psort='Submission'; + $rsort='Reviewer'; + $ridsort='R-ID'; + $_GET['s'] = 'pid'; +} elseif ($_GET['s'] == "paper") { + $q = $pq . " ORDER BY `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + $sortid = "paper"; + $pidsort='S-ID'; + $psort="Submission
    " . $OC_sortImg; + $rsort='Reviewer'; + $ridsort='R-ID'; +} elseif ($_GET['s'] == "rid") { + $q = $pq . " ORDER BY `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `" . OCC_TABLE_PAPER . "`.`paperid`"; + $sortid = "reviewer"; + $pidsort='S-ID'; + $psort='Submission'; + $rsort='Reviewer'; + $ridsort='R-ID
    ' . $OC_sortImg; +} elseif ($_GET['s'] == "reviewer") { + $q = $pq . " ORDER BY `" . OCC_TABLE_REVIEWER . "`.`name_last`, `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_PAPER . "`.`paperid`"; + $sortid = "reviewer"; + $pidsort='S-ID'; + $psort='Submission'; + $rsort="Reviewer
    " . $OC_sortImg; + $ridsort= 'R-ID'; +} else { + err("Unknown sort source"); +} + +// Display Filter +$aAR = array_keys($OC_acceptanceColorAR); +$aAR[] = 'Pending'; +print ' +

    +
    +  '; +if (count($subTypeAR) > 0) { + print '  '; +} +print ' +
    +
    +'; + +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + print 'No reviews found.

    '; +} else { + $s = substr($sortid,0,1); + + print '

    Links:
    '; + + if ($s == "p") { + print '
    R-ID – Show review
    '; + } else { + print '
    S-ID – Show review
    '; + } + print ' +
    Reviewer – Show Reviewer info
    +
    Submission – Show Submission info
    +
    +
    Legend:
    +
    + + + + +
    Review Status:           Marked as Complete            Started            Not Yet Saved
    +'; + + if (isset($OC_reviewQuestionsAR['recommendation'])) { + print '
    + + +
    Recommendation: '; + foreach ($OC_reviewQuestionsAR['recommendation']['values'] as $k => $v) { + print '(' . $k . ') ' . safeHTMLstr(preg_match('/:/', $v) ? substr($v,0,strpos($v,':')) : substr($v,0,30)) . '   '; + } + print ' +
    +'; + } + + print ' +
    +
    + + + +
    + + + + +'; + if (isset($OC_reviewQuestionsAR['recommendation'])) { + print ''; + } + print ' + '; + $currid = -1; + $row = 1; + while ($l = ocsql_fetch_array($r)) { + + if ($l['completed'] == "F" ) { + if ($l['updated']) { $reccolor = ' bgcolor="#ffffcc"'; $rectitle = 'started'; } + else { $reccolor = ' bgcolor="#ffcccc"'; $rectitle = 'not yet saved'; } + } + elseif (isset($l['completed'])) { $reccolor = ' bgcolor="#ccffcc"'; $rectitle = 'marked as complete'; } + else { $reccolor = ''; $rectitle = '';} + + if ($sortid == "reviewer") { + $ptags = ''; + $rtags = ''; + } else { + $ptags = ''; + $rtags = ''; + } + + $blanktags = ''; + + if ($currid != $l[$sortid.'id']) { + if ($currid != -1) { + if ($row==1) { $row=2; } else { $row=1; } + } + $currid = $l[$sortid.'id']; + } else { + if ($sortid == "reviewer") { $rtags = $blanktags; } + else { $ptags = $blanktags; } + } + + print '' . $ptags; + if (isset($OC_reviewQuestionsAR['recommendation'])) { + print ''; + }; + print $rtags . ''; + + print "\n"; + } + print ' + +
    ' . $pidsort . '' . $psort . 'Recom.' . $ridsort . '' . $rsort . '
    '.$l['paperid'].'' . safeHTMLstr($l['title']) . '' . $l['reviewerid'] . '' . safeHTMLstr($l['name']) . '' . $l['paperid'] . '' . safeHTMLstr($l['title']) . ''.$l['reviewerid'].'' . safeHTMLstr($l['name']) . '  
    ' . safeHTMLstr($l['recommendation']) . ' '; + if (empty($l['reviewerid'])) { print ' '; } + else { + print ''; + } + print '
    +
    +'; +} + +printFooter(); + +?> diff --git a/chair/list_scores.js b/chair/list_scores.js new file mode 100644 index 0000000..cad398c --- /dev/null +++ b/chair/list_scores.js @@ -0,0 +1,106 @@ +// +----------------------------------------------------------------------+ +// | OpenConf | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +// +----------------------------------------------------------------------+ +// | This source file is subject to the OpenConf License, available on | +// | the OpenConf web site: www.OpenConf.com | +// +----------------------------------------------------------------------+ + +// Updates checkboxes based on form selection +function selectBoxes() { + var boxSelectID = document.getElementById("boxselect"); + var boxSelect = boxSelectID.options[boxSelectID.selectedIndex].value; + var score = document.getElementById("score").value; + switch (boxSelect) { + case "all": + for (i=0; i= intscore)) { + document.scoresForm.elements[i].checked=true; + } else { + document.scoresForm.elements[i].checked=false; + } + } + } + } + break; + case "eq": + if ((score == "") || isNaN(score)) { + alert("Enter a valid score"+score); + } else { + intscore = parseFloat(score); + for (i=0; i= 48) && (thekey <= 57)) // 0-9 + return true; + switch (thekey) { + case 0: + case 8: // backspace + case 9: // tab + case 37: // left arrow + case 39: // right arrow + case 46: // period + //case 46: // delete + return true; + break; + } + return false; +} diff --git a/chair/list_scores.php b/chair/list_scores.php new file mode 100644 index 0000000..f83861f --- /dev/null +++ b/chair/list_scores.php @@ -0,0 +1,357 @@ +Invalid change request action.

    '; + } + } else { + print '

    Invalid change request. Were submissions selected?

    '; + } +} + +// Get accept/reject/pending count +$r = ocsql_query("SELECT `accepted`, COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` GROUP BY `accepted`") or err("Unable to get score count"); +if (ocsql_num_rows($r) == 0) { + warn('No submissions have been made yet.'); +} +$accCountAR = array(); +while ($l = ocsql_fetch_array($r)) { + if (empty($l['accepted'])) { + $accCountAR['Pending'] = $l['count']; + } else { + $accCountAR[$l['accepted']] = $l['count']; + } +} + + +// Get pending papers advocate recommendation counts +$advcountTotal = 0; +$advCountAR = array(); +if (isset($accCountAR['Pending']) && ($accCountAR['Pending'] > 0)) { + $cq = "SELECT `adv_recommendation`, COUNT(`advocateid`) AS `count` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERADVOCATE . "`.`paperid` AND `" . OCC_TABLE_PAPER . "`.`accepted` IS NULL GROUP BY `adv_recommendation`"; + if ($cr = ocsql_query($cq)) { + while ($cl = ocsql_fetch_array($cr)) { + if (empty($cl['adv_recommendation'])) { + $advCountAR['Pending'] = $cl['count']; + } else { + $advCountAR[$cl['adv_recommendation']] = $cl['count']; + } + $advcountTotal += $cl['count']; + } + } +} + +// Select sort order +$psort='Submission ID. Title'; +$ssort='Score'; +$arsort='Advocate
    Recom.
    '; +$asort='Advocate'; +$pdsort='Final
    Decision
    '; +$stsort='Sub. Type'; +if (!isset($_GET['s'])) { + $_GET['s'] = 'score'; +} +switch ($_GET['s']) { + case 'paper': + $psort="Submission ID. Title
    " . $OC_sortImg; + $sort = "`paperid`"; + break; + case 'advocate': + $asort = "Advocate
    " . $OC_sortImg; + $sort = "`name_last`, `name_first`, `paperid`"; + break; + case 'advrec': + $arsort = 'Adv Recom
    ' . $OC_sortImg; + $sort = "`adv_recommendation`, `recavg` DESC, `paperid`"; + break; + case 'pcdecision': + $pdsort = "Final Decision
    " . $OC_sortImg; + $sort = "`accepted`, `recavg` DESC, `paperid`"; + break; + case 'type': + $stsort = "Type
    " . $OC_sortImg; + $sort = "`type`, `recavg` DESC, `paperid`"; + break; + case 'scoreasc': + $ssort = 'Score
    ' . $OC_sortImgAsc . ''; + $sort = "`recavg` ASC, `paperid`"; + $_GET['s'] = 'scoreasc'; + break; + case 'score': + default: + $ssort = 'Score
    ' . $OC_sortImg . ''; + $sort = "`recavg` DESC, `paperid`"; + $_GET['s'] = 'score'; + break; +} + +// Display Filter +$aAR = array_keys($OC_acceptanceColorAR); +$aAR[] = 'Pending'; +print ' +
    +
    +  '; +if (count($subTypeAR) > 0) { + print '  '; +} +print ' +
    +
    +
    +'; + +// Type? +$OC_trackType = false; +$sr = ocsql_query("SELECT COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` WHERE `type`!='' AND `type` IS NOT NULL") or err('Unable to check type field'); +if (($sl = ocsql_fetch_assoc($sr)) && ($sl['count'] > 0)) { + $OC_trackType = true; +} + +// Get all papers and decisions +$q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`type`, `" . OCC_TABLE_REVIEWER . "`.`username`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, COUNT(`" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`) AS `cr`, COUNT(`score`) AS `crec`, ABS(FORMAT(AVG(`score`),2)) AS `recavg`, MAX(`score`) AS `recmax`, MIN(`score`) AS `recmin`, `title`, `accepted`, `adv_recommendation`, MIN(`completed`) AS `reviewscomplete` FROM `" . OCC_TABLE_PAPER . "` LEFT JOIN `" . OCC_TABLE_PAPERREVIEWER . "` ON `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` LEFT JOIN `" . OCC_TABLE_PAPERADVOCATE . "` ON `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` LEFT JOIN `" . OCC_TABLE_REVIEWER . "` ON `" . OCC_TABLE_REVIEWER . "`.`reviewerid`=`" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid` WHERE 1=1 "; +switch($atype) { + case '': + break; + case 'Pending': + $q .= "AND (`accepted`='' OR `accepted` IS NULL) "; + break; + default: + $q .= "AND `accepted`='" . safeSQLstr($atype) . "' "; + break; +} +switch($stype) { + case '': + break; + default: + $q .= "AND `type`='" . safeSQLstr($stype) . "' "; + break; +} +$q .= "GROUP BY `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`type`, `" . OCC_TABLE_REVIEWER . "`.`username`, `name`, `title`, `accepted`, `adv_recommendation` ORDER BY $sort"; +$r = ocsql_query($q) or err("Unable to get scores"); +if (ocsql_num_rows($r) == 0) { + print 'No submissions available.

    '; +} else { + print ' + +
    +
    +
    Links:
    +
    Score – Show reviews and accept/reject submission
    +
    Submission ID. Title – Show submission info
    +
    +
    Definitions:
    +
    Score = average score across reviews (if no score, ignored)
    +
    Weight = Number of reviews with a score
    +
    Weight* = May include reviews marked as incomplete (unassign)
    +
    Range = Min - Max scores
    +'; + + if ($OC_configAR['OC_paperAdvocates']) { + print ' +
    Advocate Recom. = Advocate Recommendation
    +'; + if ($advcountTotal > 0) { + print ' +
    +
    Pending Submissions\' Advocate Recommendation Count:
    +

    +'; + $c = 0; + foreach ($OC_acceptanceValuesAR as $acc) { + if ($c++ == 3) { + print "
    \n"; + $c = 0; + } + print '' . safeHTMLstr($acc['value']) . ' - ' . (isset($advCountAR[$acc['value']]) ? $advCountAR[$acc['value']] : 0) . '     '; + } + print ' +None - ' . (isset($advCountAR['Pending']) ? $advCountAR['Pending'] : 0) . ' +
    +'; + } + } + + print ' +
    +
            +Legend:
    + +'; + +foreach ($OC_acceptanceValuesAR as $acc) { + print ''; + +} + + print ' + +'; + + if ($OC_configAR['OC_paperAdvocates']) { + print ' + +'; + } + + print ' +
          ' . safeHTMLstr($acc['value']) . ' (' . (isset($accCountAR[$acc['value']]) ? $accCountAR[$acc['value']] : 0) . ')
          Pending (' . (isset($accCountAR['Pending']) ? $accCountAR['Pending'] : 0) . ')
          Decision != Recom.
    +
    +
    + +

    + + + + +

    +'; + + if ($OC_configAR['OC_paperAdvocates']) { + print ''; + } + + print ''; + if ($OC_trackType) { + print ''; + } + if ($OC_configAR['OC_paperAdvocates']) { + print ''; + } + print ''; + while ($l = ocsql_fetch_array($r)) { + $advpcmatch = ''; + $scorelink = 'show_scores.php?pid=' . $l['paperid'] . '&s=' . safeHTMLstr($_GET['s']); + print ''; + if (isset($l['adv_recommendation']) && !empty($l['adv_recommendation']) && ($l['adv_recommendation'] != $l['accepted'])) { + $advpcmatch = ' bgcolor="#FFFFCC"'; + } + } + else { + print ' style="background-color: #e6e6e6">'; + } + if ($l['recavg'] != '') { + $usescore = number_format($l['recavg'], 2); + $useweight = $l['crec']; + if ($l['reviewscomplete'] == 'F') { $useweight .= '*'; } + else { $useweight .= ' '; } + } else { + $usescore = '–'; + $useweight = ' '; + } + if ($l['recmin'] === $l['recmax']) { $userange = $l['recmin']; } + else { $userange = $l['recmin'] . '-' . $l['recmax']; } + if ($OC_configAR['OC_paperAdvocates']) { + print ''; + } + print ''; + if ($OC_trackType) { + print ''; + } + if ($OC_configAR['OC_paperAdvocates']) { + print ''; + } + + print "\n"; + } + print ' + +
     ' . $pdsort . '' . $arsort . '' . $ssort . 'WeightRange' . $psort . '' . $stsort . '' . $asort . '
    ' . safeHTMLstr($l['accepted']) . ' ' . safeHTMLstr($l['adv_recommendation']) . '' . $usescore . '' . $useweight . '' . $userange . '' . $l['paperid'] . '. ' . safeHTMLstr($l['title']) . '' . safeHTMLstr($l['type']) . '' . safeHTMLstr($l['name']) . '


    +
    +'; +} + +printFooter(); + +?> diff --git a/chair/list_topics.php b/chair/list_topics.php new file mode 100644 index 0000000..7d737c2 --- /dev/null +++ b/chair/list_topics.php @@ -0,0 +1,74 @@ +No papers to display.

    '; } +else { + print ' +

    +
    Functions:
    +
    Click on Score links to see individual reviewer scores and accept/reject submission
    +
    Click on Submission ID. Title links to see submission information
    +
    +
    Definitions:
    +
    score = average score (if no score, ignored)
    +
    +'; + + // Get topic names author listed their paper under + $topicAR = array(); + $q2 = "SELECT `" . OCC_TABLE_PAPERTOPIC . "`.`paperid`, `topicname`, `short` FROM `" . OCC_TABLE_PAPERTOPIC . "`, `" . OCC_TABLE_TOPIC . "` WHERE `" . OCC_TABLE_PAPERTOPIC . "`.`topicid`=`" . OCC_TABLE_TOPIC . "`.`topicid` ORDER BY `" . OCC_TABLE_PAPERTOPIC . "`.`paperid`"; + $r2 = ocsql_query($q2) or err("Unable to get submission topics"); + while ($l2 = ocsql_fetch_array($r2)) { + if (array_key_exists($l2['paperid'],$topicAR)) { + $topicAR[$l2['paperid']] .= "
  • " . useTopic($l2['short'],$l2['topicname']) . "\n"; + } else { + $topicAR[$l2['paperid']] = "
  • " . useTopic($l2['short'],$l2['topicname']) . "\n"; + } + } + + // Get topic (sesion) names reviewers listed papers as belonging to + $sessionAR = array(); + $q3 = "SELECT `" . OCC_TABLE_PAPERSESSION . "`.`paperid`, `topicname`, `short` FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_PAPERSESSION . "`, `" . OCC_TABLE_TOPIC . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`score` IS NOT NULL AND `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`=`" . OCC_TABLE_PAPERSESSION . "`.`paperid` AND `" . OCC_TABLE_TOPIC . "`.`topicid`=`" . OCC_TABLE_PAPERSESSION . "`.`topicid` GROUP BY `" . OCC_TABLE_PAPERSESSION . "`.`paperid`, `topicname`, `short` ORDER BY `" . OCC_TABLE_PAPERSESSION . "`.`paperid`"; + $r3 = ocsql_query($q3) or err("Unable to get reviewer sessions"); + while ($l3 = ocsql_fetch_array($r3)) { + if (array_key_exists($l3['paperid'],$sessionAR)) { + $sessionAR[$l3['paperid']] .= "
  • " . useTopic($l3['short'],$l3['topicname']) . "\n"; + } else { + $sessionAR[$l3['paperid']] = "
  • " . useTopic($l3['short'],$l3['topicname']) . "\n"; + } + } + + while ($l = ocsql_fetch_array($r)) { + if (!empty($l['recavg'])) { + $usescore = number_format($l['recavg'], 2); + } else { + $usescore = '–'; + } + + print '
    ' . $l['paperid'] . ". " . safeHTMLstr($l['title']) . '

    Score: ' . $usescore . "

    \nKeywords: " . safeHTMLstr($l['keywords']) . "

    \n" . OCC_WORD_AUTHOR . " Topics:

      \n" . varValue($l['paperid'], $topicAR) . "
    \n"; + + print "Reviewer Sessions:
      \n" . varValue($l['paperid'], $sessionAR) . "
    \n"; + + } +} + +printFooter(); + +?> diff --git a/chair/list_topics_b.inc b/chair/list_topics_b.inc new file mode 100644 index 0000000..4e8b2e2 --- /dev/null +++ b/chair/list_topics_b.inc @@ -0,0 +1,17 @@ +oc_' . 'ch' . 'eck' . 'B' . '(); +'; +} diff --git a/chair/list_topics_p.php b/chair/list_topics_p.php new file mode 100644 index 0000000..79fb47b --- /dev/null +++ b/chair/list_topics_p.php @@ -0,0 +1,101 @@ +' . $OC_sortImg; + $tsort = 'Topic (ID)'; + $sortfld = 'paperid'; +} else { + $sort = '`topicid`, `paperid`'; + $psort = 'Submission ID. Title'; + $tsort = 'Topic (ID)
    ' . $OC_sortImg; + $sortfld = 'topicid'; +} + +printHeader("Submission Topics", 1); + +$accOptions = ''; +foreach ($OC_acceptanceValuesAR as $idx => $acc) { + $accOptions .= ''; +} + +print ' +

    Show Count Only

    + +
    + +

    + + +

    +
    +'; + +$q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_TOPIC . "`.`topicid`, `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_TOPIC . "`, `" . OCC_TABLE_PAPERTOPIC . "` WHERE `" . OCC_TABLE_PAPERTOPIC . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_PAPERTOPIC . "`.`topicid`=`" . OCC_TABLE_TOPIC . "`.`topicid` $accSQL ORDER BY $sort"; +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + print 'No submissions available

    '; +} else { + print ' + + + '; + $currid = null; + $row = 1; + + if (isset($_REQUEST['s']) && ($_REQUEST['s'] == 'paperid')) { + while ($l = ocsql_fetch_array($r)) { + if ($l['paperid'] == $currid) { + print ''; + } else { + $row = $rowAR[$row]; + print ''; + } + $currid = $l['paperid']; + } + } else { + while ($l = ocsql_fetch_array($r)) { + if ($l['topicid'] == $currid) { + print ''; + } else { + $row = $rowAR[$row]; + print ''; + } + $currid = $l['topicid']; + } + } + print '
    ' . $tsort . '' . $psort . '
    ' . safeHTMLstr(useTopic($l['short'], $l['topicname']) . ' (' . $l['topicid'] . ')') . ' 
    ' . safeHTMLstr(useTopic($l['short'], $l['topicname']) . ' (' . $l['topicid'] . ')') . '' . $l['paperid'] . '. ' . safeHTMLstr($l['title']) . '
     ' . $l['paperid'] . '. ' . safeHTMLstr($l['title']) . '
    ' . safeHTMLstr(useTopic($l['short'], $l['topicname']) . ' (' . $l['topicid'] . ')') . '' . $l['paperid'] . '. ' . safeHTMLstr($l['title']) . '
    '; +} + +printFooter(); + +?> diff --git a/chair/list_topics_pcount.php b/chair/list_topics_pcount.php new file mode 100644 index 0000000..c9ff6a3 --- /dev/null +++ b/chair/list_topics_pcount.php @@ -0,0 +1,75 @@ + $acc) { + $accOptions .= ''; +} + +print ' +

    Show Submissions

    + +
    + +

    + + +

    +
    +'; + +$q = "SELECT `" . OCC_TABLE_TOPIC . "`.`topicid`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short`, COUNT(*) AS `num` FROM `" . OCC_TABLE_TOPIC . "`, `" . OCC_TABLE_PAPERTOPIC . "`, `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_TOPIC . "`.`topicid`=`" . OCC_TABLE_PAPERTOPIC . "`.`topicid` AND `" . OCC_TABLE_PAPERTOPIC . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` $accSQL GROUP BY `" . OCC_TABLE_TOPIC . "`.`topicid`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short` ORDER BY "; +if (!isset($_REQUEST['s']) || ($_REQUEST['s']=="topicname")) { + $q .= "`topicname`"; + $tsort = 'Topic
    ' . $OC_sortImg; + $nsort = 'Count'; +} else { + $q .= "`num`"; + $nsort = 'Count
    ' . $OC_sortImg; + $tsort = 'Topic'; +} +$r = ocsql_query($q) or err('Unable to get information'); +if (ocsql_num_rows($r) == 0) { + print 'No submissions available

    '; +} else { + print ''; + $row = 1; + while ($l = ocsql_fetch_array($r)) { + print '\n"; + if ($row==1) { $row=2; } else { $row=1; } + } + print "
    ' . $tsort . '' . $nsort .'
    ' . safeHTMLstr(useTopic($l['short'],$l['topicname'])) . '' . $l['num'] . "
    "; +} + +printFooter(); + +?> diff --git a/chair/list_topics_r.php b/chair/list_topics_r.php new file mode 100644 index 0000000..abd86c5 --- /dev/null +++ b/chair/list_topics_r.php @@ -0,0 +1,111 @@ +Show Count Only

    '; + +if ($OC_configAR['OC_paperAdvocates']) { + $options = ''; + print ' +
    + +

    + + +

    +
    +'; +} + +if (!isset($_REQUEST['s']) || empty($_REQUEST['s']) || ($_REQUEST['s'] == "topic")) { + $sortby = ($OC_configAR['OC_topicDisplayAlpha'] ? '`short`, `topicname`' : '`topicid`') . ', `reviewerid`'; + $topicsortstr = 'Topic ' . $OC_sortImg; + $memberidsortstr = 'ID'; + $membernamesortstr = 'Name'; +} elseif ($_REQUEST['s'] == "memberid") { + $sortby = "`reviewerid`"; + $topicsortstr = 'Topic'; + $memberidsortstr = 'ID ' . $OC_sortImg; + $membernamesortstr = 'Name'; +} else { // member sort + $sortby = "`name_last`, `name_first`"; + $topicsortstr = 'Topic'; + $memberidsortstr = 'ID'; + $membernamesortstr = 'Name ' . $OC_sortImg; +} + +$q = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `" . OCC_TABLE_TOPIC . "`.`topicid`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `onprogramcommittee`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_TOPIC . "`, `" . OCC_TABLE_REVIEWERTOPIC . "` WHERE `" . OCC_TABLE_REVIEWERTOPIC . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` AND `" . OCC_TABLE_REVIEWERTOPIC . "`.`topicid`=`" . OCC_TABLE_TOPIC . "`.`topicid` $cmtAdd ORDER BY " . $sortby; +$r = ocsql_query($q) or err('Unable to get information '); +if (ocsql_num_rows($r) == 0) { + print 'No committee members with topics found.

    '; +} else { + print ' + + +'; + $currid = null; + $row = 2; // Set to 2 to handle same IDs + + if (!isset($_REQUEST['s']) || empty($_REQUEST['s']) || ($_REQUEST['s'] == "topic")) { + + while ($l = ocsql_fetch_array($r)) { + if ($currid == $l['topicid']) { + print ''; + } else { + $row = $rowAR[$row]; + print ''; + $currid = $l['topicid']; + } + print '\n"; + } + } else { + while ($l = ocsql_fetch_array($r)) { + if ($currid == $l['reviewerid']) { + print ''; + } else { + $row = $rowAR[$row]; + $currid = $l['reviewerid']; + print ''; + } + print "\n"; + } + } + + print '
    ' . $topicsortstr . 'Committee Member ' . $memberidsortstr . '. ' . $membernamesortstr . '
     
    ' . safeHTMLstr(useTopic($l['short'],$l['topicname'])) . '' . $l['reviewerid'] . '. ' . safeHTMLstr($l['name']) . ''; + if (($cmt != 'pc') && ($l['onprogramcommittee'] == 'T')) { + print " [PC]"; + } + print "
    ' . safeHTMLstr(useTopic($l['short'],$l['topicname'])) . ' 
    ' . safeHTMLstr(useTopic($l['short'],$l['topicname'])) . '' . $l['reviewerid'] . '. ' . safeHTMLstr($l['name']) . ''; + if (($cmt != 'pc') && ($l['onprogramcommittee'] == 'T')) { + print " [PC]"; + } + print '
    '; +} + +printFooter(); + +?> diff --git a/chair/list_topics_rcount.php b/chair/list_topics_rcount.php new file mode 100644 index 0000000..c453ac8 --- /dev/null +++ b/chair/list_topics_rcount.php @@ -0,0 +1,69 @@ +Show Committee Members

    '; + +if ($OC_configAR['OC_paperAdvocates']) { + $options = ''; + print ' +
    + +

    + + +

    +
    +'; +} + +$q = "SELECT `" . OCC_TABLE_TOPIC . "`.`topicid`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short`, COUNT(`" . OCC_TABLE_REVIEWERTOPIC . "`.`reviewerid`) AS `num` FROM `" . OCC_TABLE_TOPIC . "`, `" . OCC_TABLE_REVIEWERTOPIC . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_TOPIC . "`.`topicid`=`" . OCC_TABLE_REVIEWERTOPIC . "`.`topicid` AND `" . OCC_TABLE_REVIEWERTOPIC . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` $cmtAdd GROUP BY `" . OCC_TABLE_TOPIC . "`.`topicid`, `" . OCC_TABLE_TOPIC . "`.`topicname`, `" . OCC_TABLE_TOPIC . "`.`short` ORDER BY "; +if (!isset($_REQUEST['s']) || ($_REQUEST['s']=="topic")) { + $q .= "`topicname`"; + $tsort = 'Topic
    ' . $OC_sortImg; + $nsort = 'Count'; +} else { + $q .= "`num`"; + $nsort = 'Count
    ' . $OC_sortImg; + $tsort = 'Topic'; +} +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + print 'No reviewers have signed up yet

    '; +} else { + print ''; + $row = 1; + while ($l = ocsql_fetch_array($r)) { + print '\n"; + if ($row==1) { $row=2; } else { $row=1; } + } + print "
    ' . $tsort . '' . $nsort .'
    ' . safeHTMLstr(useTopic($l['short'],$l['topicname'])) . '' . $l['num'] . "
    "; +} + +printFooter(); + +?> diff --git a/chair/log-search.php b/chair/log-search.php new file mode 100644 index 0000000..6292b7b --- /dev/null +++ b/chair/log-search.php @@ -0,0 +1,144 @@ + +

    +
    + + + + +  + +
    + +'; + +// submission? +if (isset($_POST['subaction'])) { + // delete? + if (($_POST['subaction'] == 'Delete Log Entries') && isset($_POST['logids']) && is_array($_POST['logids']) && !empty($_POST['logids'])) { + foreach ($_POST['logids'] as $id) { + if ( ! ocsql_query("DELETE FROM `" . OCC_TABLE_LOG . "` WHERE `logid`='" . safeSQLstr($id) . "' LIMIT 1") ) { + print '

    Failed to delete Log ID ' . safeHTMLstr($id) . '

    '; + } + } + } elseif (($_POST['subaction'] == 'Delete Messages') && isset($_POST['queueids']) && is_array($_POST['queueids']) && !empty($_POST['queueids'])) { + foreach ($_POST['queueids'] as $id) { + if ( ! ocsql_query("DELETE FROM `" . OCC_TABLE_EMAIL_QUEUE . "` WHERE `id`='" . safeSQLstr($id) . "' LIMIT 1") ) { + print '

    Failed to delete Message ID ' . safeHTMLstr($id) . '

    '; + } + } + } + + // search + if (isset($_POST['q']) && !empty($_POST['q'])) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + print '


    Log Entries:
    '; + + // log + $r = ocsql_query("SELECT * FROM `" . OCC_TABLE_LOG . "` WHERE " . ((isset($_POST['type']) && !empty($_POST['type'])) ? ("`type`='" . safeSQLstr($_POST['type']) . "' AND ") : "") . "(`entry` LIKE '%" . safeSQLstr($_POST['q']) . "%' OR `extra` LIKE '%" . safeSQLstr($_POST['q']) . "%') ORDER BY `datetime` DESC, `logid` DESC") or err('Unable to search log'); + if (ocsql_num_rows($r) > 0) { + print ' + + + + '; + $row = 1; + while ($l = ocsql_fetch_assoc($r)) { + print ''; + if ($row == 1) { + $row = 2; + } else { + $row = 1; + } + } + print ' + +
    Log IDDate / Time (UTC)TypeEntry
    ' . safeHTMLstr($l['logid']) . '' . safeHTMLstr($l['datetime']) . '' . safeHTMLstr($l['type']) . '' . safeHTMLstr(substr($l['entry'], 0, 80)) . ((strlen($l['entry']) > 80) ? '…' : '') . '
    + '; + } else { + print '

    No log entries found

    '; + } + + // queue + if (isset($_POST['checkqueue']) && ($_POST['checkqueue'] == 1)) { + print '


    Messages:
    '; + $r = ocsql_query("SELECT * FROM `" . OCC_TABLE_EMAIL_QUEUE . "` WHERE (`to` LIKE '%" . safeSQLstr($_POST['q']) . "%' OR `subject` LIKE '%" . safeSQLstr($_POST['q']) . "%' OR `body` LIKE '%" . safeSQLstr($_POST['q']) . "%') ORDER BY `queued` DESC") or err('Unable to search messages'); + if (ocsql_num_rows($r) > 0) { + print ' + + + + '; + $row = 1; + while ($l = ocsql_fetch_assoc($r)) { + print ''; + if ($row == 1) { + $row = 2; + } else { + $row = 1; + } + } + print ' + +
    Msg IDQueued (UTC)ToSubject
    ' . safeHTMLstr($l['id']) . '' . safeHTMLstr($l['queued']) . '' . safeHTMLstr($l['to']) . '' . safeHTMLstr(substr($l['subject'], 0, 80)) . ((strlen($l['subject']) > 80) ? '…' : '') . '
    + '; + } else { + print '

    No messages found

    '; + } + } + } +} + +print '
    '; + +printFooter(); + +?> diff --git a/chair/log.php b/chair/log.php new file mode 100644 index 0000000..8c3208d --- /dev/null +++ b/chair/log.php @@ -0,0 +1,96 @@ +show ' . (!empty($type) ? safeHTMLstr($type) : '') . ' entries | search

    '; + $q = "SELECT * FROM `" . OCC_TABLE_LOG . "` WHERE `logid`='" . safeSQLstr($_GET['id']) . "'"; + $r = ocsql_query($q) or err('Unable to retrieve log entry'); + if (ocsql_num_rows($r) == 0) { + warn('Log entry not found'); + } else { + $l = ocsql_fetch_assoc($r); + print 'Date/Time: ' . safeHTMLstr($l['datetime']); + if ($l['type'] == 'email') { + print '   (view individual messages/status)'; + } + print '
    +Type: ' . safeHTMLstr($l['type']) . '
    +Entry: ' . safeHTMLstr($l['entry']) . '
    +


    +' . nl2br(safeHTMLstr($l['extra'])) . '
    +'; + } +} else { // all entries + if (isset($_GET['limit']) && ($_GET['limit'] == 0)) { // limit entries? + $limit = ''; + } else { + $limit = ' LIMIT 30'; + print '

    show all ' . safeHTMLstr($type) . ' entries | search

    '; + } + + // Get email entries with failed messages + $failedMessageAR = array(); + $q = "SELECT `queued` FROM `" . OCC_TABLE_EMAIL_QUEUE . "` WHERE `sent` IS NULL GROUP BY `queued`"; + $r = ocsql_query($q) or err('Unable to retrieve email log entries'); + while ($l = ocsql_fetch_assoc($r)) { + $failedMessageAR[] = $l['queued']; + } + + // retrieve entries + $q = "SELECT * FROM `" . OCC_TABLE_LOG . "` WHERE `type`" . (empty($type) ? "!='sql'" : ("='" . safeSQLstr($type) . "'")) . " ORDER BY `datetime` DESC" . $limit; + $r = ocsql_query($q) or err('Unable to retrieve log entries'); + if (ocsql_num_rows($r) == 0) { + warn('No log entries were found'); + } + + // display entries + if ($GLOBALS['OC_configAR']['OC_timeZone'] != 'UTC') { + print '

    The Date/Time column is shown in Coordinated Universal Time (UTC).
    UTC ' . date('P') . ' = ' . safeHTMLstr($GLOBALS['OC_configAR']['OC_timeZone'] ) . '

    '; + } + print ''; + $row = 1; + while ($l = ocsql_fetch_assoc($r)) { + print '\n"; + if ($row == 1) { + $row = 2; + } else { + $row = 1; + } + } + print '
    Date / Time (UTC)TypeEntry
    '; + if (!empty($l['extra'])) { // extra stuff? if so link it in + print '' . safeHTMLstr($l['datetime']) . ''; + } else { + print safeHTMLstr($l['datetime']); + } + print '' . safeHTMLstr($l['type']); + if (($l['type'] == 'email') && in_array($l['datetime'], $failedMessageAR)) { + print ' – failed'; + } + print '' . safeHTMLstr($l['entry']) . "
    '; +} + +printFooter(); + +?> diff --git a/chair/notification_templates.php b/chair/notification_templates.php new file mode 100644 index 0000000..3b0168a --- /dev/null +++ b/chair/notification_templates.php @@ -0,0 +1,144 @@ + $l['name'], 'variables' => $l['variables']); + } +} + +$defaultVariables = array( + 'OC_pcemail' => OCC_WORD_CHAIR . ' Email Address', + 'OC_confirmmail' => 'Notification Email Address', + 'OC_confName' => 'Event/Journal Short Name', + 'OC_confNameFull' => 'Event/Journal Full Name', + 'OC_confURL' => 'Event/Journal Web Address', + 'OC_openconfURL' => 'OpenConf Web Address', +); + +clearstatcache(); + +function oc_templateForm($tid, $subject, $body) { + print ' +

    all templates

    +
    +
    + + + + + + + + + + + +
    Template:' . safeHTMLstr($GLOBALS['templateAR'][$tid]['name']) . ' 
     
     
    +'; + + print ' +[:variables:] +

    + +'; + foreach ($GLOBALS['defaultVariables'] as $k => $v) { + print ''; + } + if (!empty($GLOBALS['templateAR'][$tid]['variables'])) { + $vars = json_decode($GLOBALS['templateAR'][$tid]['variables']); + foreach ($vars as $k => $v) { + print ''; + } + } + + print ' +
    [:' . safeHTMLstr($k) . ':]'. safeHTMLstr($v) . '
    [:' . safeHTMLstr($k) . ':]'. safeHTMLstr($v) . '
    +
    +
    +

    The variables appearing next to the message field may be used in your email by enclosing each instance in [:variable:] . These will be substituted for their value prior to the email being sent. For example, to include the conference (short) name in your message use [:OC_confName:] . Some variables are only available for certain types of notification.

    +'; + + printFooter(); + exit; +} + +if (isset($_GET['ocaction']) && ($_GET['ocaction'] == 'edit') && isset($_GET['tid']) && isset($templateAR[$_GET['tid']])) { + $r = ocsql_query("SELECT `name`, `subject`, `body`, `variables` FROM `" . OCC_TABLE_TEMPLATE . "` WHERE `type`='notification' AND `templateid`='" . safeSQLstr($_GET['tid']) . "'") or err('Unable to retrieve template'); + if (ocsql_num_rows($r) == 1) { + $l = ocsql_fetch_assoc($r); + oc_templateForm($_GET['tid'], $l['subject'], $l['body']); + } else { + print '

    Template not found

    '; + } +} elseif (isset($_POST['ocaction']) && ($_POST['ocaction'] == 'Save Template')) { + $templateid = (isset($_POST['templateid']) ? trim($_POST['templateid']) : ''); + $subject = (isset($_POST['subject']) ? trim($_POST['subject']) : ''); + $body = (isset($_POST['body']) ? trim($_POST['body']) : ''); + + $err = ''; + if ( ! preg_match("/^[\w-]+$/", $templateid) || ! isset($templateAR[$templateid]) ) { + warn('Template ID invalid'); + } elseif (preg_match("/[\r\n]/", $subject)) { + $err = 'Subject invalid'; + } else { + $q = "UPDATE `" . OCC_TABLE_TEMPLATE . "` SET `subject`='" . safeSQLstr($subject) . "', `body`='" . safeSQLstr($body) . "', `updated`='" . safeSQLstr(date("Y-m-d")) . "' WHERE `templateid`='" . safeSQLstr($templateid) . "' AND `type`='notification' LIMIT 1"; + if ( ! ocsql_query($q) ) { + $err = 'Unable to add/update database'; + } + } + + if (empty($err)) { + print '

    Template saved

    '; + } else { + print '

    ' . $err . '

    '; + } + + oc_templateForm($templateid, $subject, $body); + + exit; +} + +print ' +

    click name to edit

    + +'; + +$row = 2; +foreach ($templateAR as $templateID => $templateInfo) { + print ''; + $row = $rowAR[$row]; +} + +print ' +
    + +

    If modifying a template and non-English language(s)
    in use, include translation(s) in the template.

    +'; + +printFooter(); + +?> diff --git a/chair/privacy.php b/chair/privacy.php new file mode 100644 index 0000000..82bb47b --- /dev/null +++ b/chair/privacy.php @@ -0,0 +1,163 @@ + + + +'; + +beginChairSession(); +printHeader("Privacy Settings", 1); + +$OC_configVars = array('OC_privacy_display', 'OC_privacy_link', 'OC_privacy_banner_options'); + +$OC_privacyDisplayOptionsAR = array( + 0 => 'none', + 1 => 'menu', + 2 => 'page footer' +); + +function ef($fsf, $ochsf) { + if (preg_match("/(,?)" . $fsf . "(,?)/", $ochsf, $efmatches)) { + if (($efmatches[1] == ',') && ($efmatches[2] == ',')) { + $efreplace = ','; + } else { + $efreplace = ''; + } + $ochsf = preg_replace("/,?" . $fsf . ",?/", $efreplace, $ochsf); + } + return($ochsf); +} + +$oc_bannerAR = json_decode($OC_configAR['OC_privacy_banner_options'], true) or err('Invalid banner options setting'); + +if (isset($_POST['submit']) && ($_POST['submit'] == 'Save Settings')) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + $err = array(); + + // Check input + if (!preg_match("/^[01]$/", $_POST['OC_privacy_banner_display'])) { + $err[] = 'Banner Display option invalid'; + } + if (!isset($_POST['OC_privacy_display']) || !isset($OC_privacyDisplayOptionsAR[$_POST['OC_privacy_display']])) { + $err[] = 'Policy Link Display invalid'; + } + if (isset($_POST['OC_privacy_display']) && (oc_strlen($_POST['OC_privacy_display']) > 250)) { + $err[] = 'Policy Web Address too long'; + } + + if (!empty($err)) { + print '

    Please re-enter your settings, noting the following:

    • ' . implode('
    • ', $err) . '



    '; + } else { + // Update bannerAR + $oc_bannerAR['display'] = $_POST['OC_privacy_banner_display']; + $oc_bannerAR['message'] = $_POST['OC_privacy_banner_message']; + $oc_bannerAR['dismiss'] = $_POST['OC_privacy_banner_dismiss']; + $_POST['OC_privacy_banner_options'] = json_encode($oc_bannerAR); + // Update config + updateAllConfigSettings($OC_configVars, $_POST, 'OC'); + // Update Template + if ( ! ocsql_query("UPDATE `" . OCC_TABLE_TEMPLATE . "` SET `subject`='', `body`='" . safeSQLstr(varValue('OC_privacy_policy', $_POST)) . "', `updated`='" . safeSQLstr(date("Y-m-d")) . "' WHERE `templateid`='privacy_policy' AND `type`='other' LIMIT 1") ) { + warn('Failed to save privacy policy'); + } + // Update consent form fields if necessary + if (OCC_LICENSE == 'Public') { + if (($_POST['OC_privacy_display'] == 0)) { + if ( ! preg_match("/fs_consent:consent/", $OC_configAR['OC_hideSubFields']) ) { + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`=CONCAT(`value`, ',fs_consent:consent') WHERE `module`='OC' AND `setting`='OC_hideSubFields' LIMIT 1"); + } + if ( ! preg_match("/fs_consent:consent/", $OC_configAR['OC_hideCmtFields']) ) { + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`=CONCAT(`value`, ',fs_consent:consent') WHERE `module`='OC' AND `setting`='OC_hideCmtFields' LIMIT 1"); + } + } else { + if (preg_match("/fs_consent:consent/", $OC_configAR['OC_hideSubFields'])) { + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='" . safeSQLstr(ef('fs_consent:consent', $OC_configAR['OC_hideSubFields'])) . "' WHERE `module`='OC' AND `setting`='OC_hideSubFields' LIMIT 1"); + } + if (preg_match("/fs_consent:consent/", $OC_configAR['OC_hideCmtFields'])) { + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='" . safeSQLstr(ef('fs_consent:consent', $OC_configAR['OC_hideCmtFields'])) . "' WHERE `module`='OC' AND `setting`='OC_hideCmtFields' LIMIT 1"); + } + } + } + // notify user + print '

    Settings Saved

    '; + } + + $OC_privacy_policy = $_POST['OC_privacy_policy']; +} else { + // retrieve policy template + list($none, $OC_privacy_policy) = oc_getTemplate('privacy_policy'); +} + +print ' +
    + + + + +
    +Banner (collapse) + +
    +
    When Display Banner is set to Yes, a banner with the Message below is shown until the Dismiss Button is clicked. If the Privacy Policy is enabled, a link to the policy is automatically included in the banner.
    + +
    ' . generateRadioOptions('OC_privacy_banner_display', $yesNoAR, $oc_bannerAR['display']) . '
    + +
    + +
    + + +
    +
    + +
    +Privacy Policy (collapse) +
    +
    Select whether to include a Privacy Policy link in the menu or page footer, and either provide a link to the policy on your own web site or customize the one below. Although not required, it is strongly recommended that a privacy policy be provided. Translations of the privacy policy are not included, however may be entered below. A Display option other than "none" must be set for the Privacy Policy to be viewed.
    + +
    ' . generateRadioOptions('OC_privacy_display', $OC_privacyDisplayOptionsAR, varValue('OC_privacy_display', $OC_configAR)) . '
    Location to display Privacy Policy link.' . ((OCC_LICENSE == 'Public') ? ' If location set, consent fields are added to non-custom forms.' : '') . '
    + +
    Enter the full URL of the privacy policy on your web site or leave blank to display the policy below
    + +
    + + +
    +
    + +
    +'; + +oc_replaceCKEditor(array('OC_privacy_policy'), true, 600, 400); + +printFooter(); + +?> \ No newline at end of file diff --git a/chair/reset.php b/chair/reset.php new file mode 100644 index 0000000..9e2456c --- /dev/null +++ b/chair/reset.php @@ -0,0 +1,55 @@ +Functionality disabled

    '; +} +elseif (isset($_POST['submit']) && ($_POST['submit'] == "Reset Password") && preg_match("/^\w+$/",$_POST['uname'])) { + if (oc_strtolower($OC_configAR['OC_chair_uname']) != oc_strtolower($_POST['uname'])) { + print '

    ' . OCC_WORD_CHAIR . ' username entered is invalid.

    '; + } + else { // username valid + $newpwd = oc_password_generate(); + updateConfigSetting('OC_chair_pwd', oc_password_hash($newpwd)) or err('Unable to create new password'); + $msg = ' +Per your request, we have issued you a new ' . OCC_WORD_CHAIR. ' password for accessing the ' . $OC_configAR['OC_confName'] . ' OpenConf system. The new password is: + + ' . $newpwd . ' + +You may change this password at any time by signing in to the OpenConf system and updating your profile. + +'; + if (sendEmail($OC_configAR['OC_pcemail'], OCC_WORD_CHAIR . " Password Reset", $msg)) { + print '

    We have emailed you a new password. Once you receive it, please sign in and change it.

    '; + } else { + warn('We have generated a new password for you, but were unable to email it. Please contact the OpenConf administrator'); + } + } +} else { + print ' +

    Enter ' . OCC_WORD_CHAIR . '\'s username and click the Reset Password button

    +
    + + + +

    +
    +

    +'; +} + +printFooter(); + +?> diff --git a/chair/search.inc b/chair/search.inc new file mode 100644 index 0000000..110ca53 --- /dev/null +++ b/chair/search.inc @@ -0,0 +1,296 @@ + substr($OC_fieldAR[$f]['short'], 0, 30), + 'type' => $OC_fieldAR[$f]['type'], + 'fieldset' => $fsAR['fieldset'] + ); + if ($OC_fieldAR[$f]['type'] == 'date') { + $dateFieldsAR[] = $f; + } + if (isset($OC_fieldAR[$f]['values']) && is_array($OC_fieldAR[$f]['values']) && (count($OC_fieldAR[$f]['values']) > 0)) { + if (!isset($OC_fieldAR[$f]['usekey']) || $OC_fieldAR[$f]['usekey']) { + $fieldsAR[$f]['values'] = $OC_fieldAR[$f]['values']; + } else { + $fieldsAR[$f]['values'] = array(); + foreach ($OC_fieldAR[$f]['values'] as $v) { + $fieldsAR[$f]['values'][$v] = $v; + } + } + } + } + } + } +} + +function queryFieldWrapper($table, $field, $fieldType, $fieldValue, $operator, $tableFieldOverride=null) { + if ($tableFieldOverride !== null) { + $tableField = $tableFieldOverride; + } else { + $tableField = "`" . $table . "`.`" . safeSQLstr($field) . "`"; + } + $qf = ''; + if (($fieldType == 'checkbox') || ($fieldType == 'picklist')) { + $qf = "FIND_IN_SET('" . safeSQLstr($fieldValue) . "', " . $tableField . ") "; + } else { + if ($operator == 'contains') { + $qf = $tableField . " LIKE '%" . safeSQLstr(preg_replace(array('/_/', '/%/'), array('\\_', '\\%'), oc_strtolower($fieldValue))) . "%'" ; + } elseif ($operator == 'before') { + $qf = "( (" . $tableField . "<'" . safeSQLstr(oc_strtolower($fieldValue)) . "') OR (" . $tableField . " IS NULL) )"; + } elseif ($operator == 'after') { + $qf = $tableField . ">'" . safeSQLstr(oc_strtolower($fieldValue)) . "'"; + } elseif ($operator == 'onbefore') { + $qf = "( (" . $tableField . "<='" . safeSQLstr(oc_strtolower($fieldValue)) . "') OR (" . $tableField . " IS NULL) )"; + } elseif ($operator == 'onafter') { + $qf = $tableField . ">='" . safeSQLstr(oc_strtolower($fieldValue)) . "'"; + } else { + $qf = $tableField . "='" . safeSQLstr(oc_strtolower($fieldValue)) . "'"; + } + } + return($qf); +} + +function displayResultsHeader() { + header('Content-type: text/html; charset=utf-8'); + print ' + +Search + +' . +( + ( defined('OCC_LANGUAGE_LTR') && ( ! OCC_LANGUAGE_LTR ) ) + ? + '' + : + '' +) . ' + + +'; +} + +function displayResultsFooter() { + print ' + + +'; +} + +function validateSearchFields($i, &$fieldsAR, &$intFieldsAR, &$dateFieldsAR, $decFieldsAR=array()) { + if ( + // field selected exists and is valid + isset($_POST['searchfield'.$i]) && isset($fieldsAR[$_POST['searchfield'.$i]]) + && + // field operator exists and is valid + isset($_POST['searchoperator'.$i]) && preg_match("/^(?:is|contains|before|after)$/", $_POST['searchoperator'.$i]) + && + // field value entered/selected + isset($_POST['searchvalue'.$i]) && !empty($_POST['searchvalue'.$i]) + && + // field value exists if selection + ( + !isset($fieldsAR[$_POST['searchvalue'.$i]]['values']) + || + isset($fieldsAR[$_POST['searchvalue'.$i]]['values'][$_POST['searchvalue'.$i]]) + ) + && + // int field format valid + ( + !in_array($_POST['searchfield'.$i], $intFieldsAR) + || + preg_match("/^\d+$/", $_POST['searchvalue'.$i]) + ) + && + // decimal field format valid + ( + !in_array($_POST['searchfield'.$i], $decFieldsAR) + || + preg_match("/^\d+(\.\d{1,2})?$/", $_POST['searchvalue'.$i]) + ) + && + // date field format valid + ( + !in_array($_POST['searchfield'.$i], $dateFieldsAR) + || + preg_match("/^\d{4}-\d\d-\d\d$/", $_POST['searchvalue'.$i]) + ) + ) { + return(true); + } else { + return(false); + } +} + +function displayEmailForm(&$emailAddresses, $recipient, $submitText) { + print ' +

    + + + + + + + +'; + foreach ($emailAddresses as $eAddress) { + print ''; + } + print ' +

    +
    +'; +} + +function displaySearchForm(&$fieldsAR, &$dateFieldsAR, &$intFieldsAR, &$decFieldsAR, &$searchFieldNum) { + print ' + + + +

    Select one or more fields to search on and enter your query, then click the Search button. The search will find submissions matching all non-empty queries. When selecting fields with pre-defined values, the text query box will be replaced with a drop-down list of the values.

    + +
    + +'; + + for ($i=1; $i <= $searchFieldNum; $i++) { + print ' +
    + +
    +'; + } + + print ' +

    +
    + + +'; + +} \ No newline at end of file diff --git a/chair/search_committee.php b/chair/search_committee.php new file mode 100644 index 0000000..dcd0c3f --- /dev/null +++ b/chair/search_committee.php @@ -0,0 +1,131 @@ + 'Member ID', + 'type' => 'int', + 'fieldset' => '', +); +$intFieldsAR[] = 'reviewerid'; + +if ($OC_configAR['OC_paperAdvocates']) { + $fieldsAR['onprogramcommittee'] = array( + 'short' => 'PC Member', + 'type' => 'dropdown', + 'fieldset' => '', + 'values' => array('T' => 'Yes', 'F' => 'No') + ); +} + +setupFieldsAR($fieldsAR, $OC_reviewerFieldSetAR, $OC_reviewerFieldAR, $dateFieldsAR, $skipFieldTypeAR, $skipFieldIdAR); + +$fieldsAR['signupdate'] = array( + 'short' => 'Sign Up Date', + 'type' => 'date', + 'fieldset' => 'Extras', +); +$dateFieldsAR[] = 'signupdate'; + +$fieldsAR['lastsignin'] = array( + 'short' => 'Last Sign In', + 'type' => 'date', + 'fieldset' => 'Extras', +); +$dateFieldsAR[] = 'lastsignin'; + +// Hooks +// -- Use 'Extras' for fieldset name +if (oc_hookSet('search-committee')) { + foreach ($GLOBALS['OC_hooksAR']['search-committee'] as $v) { + require_once $v; + } +} + +// Search Submission POST +if (isset($_POST['ocsubmit']) && ($_POST['ocsubmit'] == 'Search')) { + displayResultsHeader(); + + // Check for valid submission + if (!validToken('chair')) { + print '

    Invalid submission

    '; + } else { + $q = ''; + $includeTopic = false; + for ($i=1; $i <= $searchFieldNum; $i++) { + if (validateSearchFields($i, $fieldsAR, $intFieldsAR, $dateFieldsAR)) { + $f = $_POST['searchfield'.$i]; + $fval = $_POST['searchvalue'.$i]; + if ($f == 'topics') { + $q .= " AND " . queryFieldWrapper(OCC_TABLE_REVIEWERTOPIC, 'topicid', 'dropdown', $fval, false); + $includeTopic = true; + } else { + $q .= " AND " . queryFieldWrapper(OCC_TABLE_REVIEWER, $f, $fieldsAR[$f]['type'], $fval, $_POST['searchoperator'.$i]); + } + } + } + + if (!empty($q)) { + $q = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `" . OCC_TABLE_REVIEWER . "`.`username`, `" . OCC_TABLE_REVIEWER . "`.`onprogramcommittee`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `" . OCC_TABLE_REVIEWER . "`.`email` FROM `" . OCC_TABLE_REVIEWER . "`" . ($includeTopic ? (", `" . OCC_TABLE_REVIEWERTOPIC . "`") : '') . " WHERE 1=1 " . ($includeTopic ? ("AND `" . OCC_TABLE_REVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWERTOPIC . "`.`reviewerid` ") : '') . $q . " GROUP BY `" . OCC_TABLE_REVIEWER . "`.`reviewerid` ORDER BY `reviewerid`"; + if ($r = ocsql_query($q)) { + if (($num = ocsql_num_rows($r)) > 0) { + print ' +

    Matches: ' . safeHTMLstr($num) . '

    + +'; + $emailAddresses = array(); + $row = 1; + while ($l = ocsql_fetch_assoc($r)) { + print ''; + if ($row==1) { $row=2; } else { $row=1; } + $emailAddresses[] = $l['reviewerid'] . '/' . $l['email']; + } + print ' +
    IDPCNameUsername
    ' . safeHTMLstr($l['reviewerid']) . '' . (($l['onprogramcommittee'] == 'T') ? '' : '') . '' . safeHTMLstr($l['name']) . '' . safeHTMLstr($l['username']) . '
    +'; + displayEmailForm($emailAddresses, 'reviewer_pc_all', 'Email Committee Member(s)'); + } else { + print '

    No matches found

    '; + } + } else { + print '

    Error encoutered while searching

    '; + } + } else { + print '

    Missing or invalid search parameters

    '; + } + } + + displayResultsFooter(); + exit; +} + +// Display search form +printHeader('Committee Members Search', 1); +displaySearchForm($fieldsAR, $dateFieldsAR, $intFieldsAR, $decFieldsAR, $searchFieldNum); +printFooter(); + +?> \ No newline at end of file diff --git a/chair/search_submissions.php b/chair/search_submissions.php new file mode 100644 index 0000000..929e194 --- /dev/null +++ b/chair/search_submissions.php @@ -0,0 +1,182 @@ + 'Submission ID', + 'type' => 'int', + 'fieldset' => '', +); +$intFieldsAR[] = 'paperid'; + +setupFieldsAR($fieldsAR, $OC_submissionFieldSetAR, $OC_submissionFieldAR, $dateFieldsAR, $skipFieldTypeAR, $skipFieldIdAR); + +$fieldsAR['submissiondate'] = array( + 'short' => 'Submission Date', + 'type' => 'date', + 'fieldset' => 'Extras', +); +$dateFieldsAR[] = 'submissiondate'; + +$fieldsAR['lastupdate'] = array( + 'short' => 'Last Updated', + 'type' => 'date', + 'fieldset' => 'Extras', +); +$dateFieldsAR[] = 'lastupdate'; + +$fieldsAR['accepted'] = array( + 'short' => 'Acceptance Decision', + 'type' => 'dropdown', + 'fieldset' => 'Extras', + 'values' => array() +); +// values also used for adv_recommendation below +foreach ($OC_acceptanceValuesAR as $acc) { + $fieldsAR['accepted']['values'][$acc['value']] = $acc['value']; +} +$fieldsAR['accepted']['values']['_NULL_'] = 'pending'; + +if ($OC_configAR['OC_paperAdvocates']) { + $fieldsAR['adv_recommendation'] = array( + 'short' => 'Advocate Recommendation', + 'type' => 'dropdown', + 'fieldset' => 'Extras', + 'values' => $fieldsAR['accepted']['values'] + ); + $fieldsAR['advocateid'] = array( + 'short' => 'Advocate ID (assigned)', + 'type' => 'int', + 'fieldset' => 'Extras' + ); + $intFieldsAR[] = 'advocateid'; +} + +$fieldsAR['reviewerid'] = array( + 'short' => 'Reviewer ID (assigned)', + 'type' => 'int', + 'fieldset' => 'Extras' +); +$intFieldsAR[] = 'reviewerid'; + +$fieldsAR['score'] = array( + 'short' => 'Reviews Score (average)', + 'type' => 'int', + 'fieldset' => 'Extras', +); +$decFieldsAR[] = 'score'; + +// Hooks +// -- Use 'Extras' for fieldset name +if (oc_hookSet('search-submissions')) { + foreach ($GLOBALS['OC_hooksAR']['search-submissions'] as $v) { + require_once $v; + } +} + +// Search Submission POST +if (isset($_POST['ocsubmit']) && ($_POST['ocsubmit'] == 'Search')) { + displayResultsHeader(); + + // Check for valid submission + if (!validToken('chair')) { + print '

    Invalid submission

    '; + } else { + $q = ''; + $includeTopic = false; + $includeAdvocate = false; + $includeReviewer = false; + for ($i=1; $i <= $searchFieldNum; $i++) { + if (validateSearchFields($i, $fieldsAR, $intFieldsAR, $dateFieldsAR, $decFieldsAR)) { + $f = $_POST['searchfield'.$i]; + $fval = $_POST['searchvalue'.$i]; + if ($f == 'topics') { + $q .= " AND " . queryFieldWrapper(OCC_TABLE_PAPERTOPIC, 'topicid', 'dropdown', $fval, false); + $includeTopic = true; + } elseif ( ($f == 'accepted') && ($fval == '_NULL_') ) { + $q .= " AND `" . OCC_TABLE_PAPER . "`.`accepted` IS NULL"; + } elseif ($OC_configAR['OC_paperAdvocates'] && ($f == 'adv_recommendation')) { + $q .= " AND " . queryFieldWrapper(OCC_TABLE_PAPERADVOCATE, 'adv_recommendation', 'dropdown', $fval, false); + $includeAdvocate = true; + } elseif ($OC_configAR['OC_paperAdvocates'] && ($f == 'advocateid')) { + $q .= " AND " . queryFieldWrapper(OCC_TABLE_PAPERADVOCATE, 'advocateid', 'int', $fval, $_POST['searchoperator'.$i]); + $includeAdvocate = true; + } elseif ($f == 'reviewerid') { + $q .= " AND " . queryFieldWrapper(OCC_TABLE_PAPERREVIEWER, 'reviewerid', 'int', $fval, $_POST['searchoperator'.$i]); + $includeReviewer = true; + } elseif ($f == 'score') { + $q .= " AND `" . OCC_TABLE_PAPER . "`.`paperid` IN (SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid` FROM `" . OCC_TABLE_PAPERREVIEWER . "` GROUP BY `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid` HAVING " . queryFieldWrapper(OCC_TABLE_PAPERREVIEWER, 'score', 'dropdown', $fval, $_POST['searchoperator'.$i], "AVG(`" . OCC_TABLE_PAPERREVIEWER . "`.`score`)") . ")"; + } elseif (in_array($f, $OC_submissionFieldSetAR['fs_authors']['fields'])) { + $q .= " AND " . queryFieldWrapper(OCC_TABLE_AUTHOR, $f, $fieldsAR[$f]['type'], $fval, $_POST['searchoperator'.$i]); + } else { + $q .= " AND " . queryFieldWrapper(OCC_TABLE_PAPER, $f, $fieldsAR[$f]['type'], $fval, $_POST['searchoperator'.$i]); + } + } + } + + // Display results + if (!empty($q)) { + $q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_PAPER . "`.`type`, CONCAT_WS(' ', `" . OCC_TABLE_AUTHOR . "`.`name_first`, `" . OCC_TABLE_AUTHOR . "`.`name_last`) AS `name`, `" . OCC_TABLE_AUTHOR . "`.`email` FROM `" . OCC_TABLE_PAPER . "`, `" . OCC_TABLE_AUTHOR . "`" . ($includeTopic ? (", `" . OCC_TABLE_PAPERTOPIC . "`") : '') . ($includeAdvocate ? (", `" . OCC_TABLE_PAPERADVOCATE . "`") : '') . ($includeReviewer ? (", `" . OCC_TABLE_PAPERREVIEWER . "`") : '') . " WHERE `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_AUTHOR . "`.`paperid` AND `" . OCC_TABLE_PAPER . "`.`contactid`=`" . OCC_TABLE_AUTHOR . "`.`position` " . ($includeTopic ? ("AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERTOPIC . "`.`paperid` ") : '') . ($includeAdvocate ? ("AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERADVOCATE . "`.`paperid` ") : '') . ($includeReviewer ? ("AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . OCC_TABLE_PAPERREVIEWER . "`.`paperid` ") : '') . $q . " GROUP BY `paperid` ORDER BY `paperid`"; + if ($r = ocsql_query($q)) { + if (($num = ocsql_num_rows($r)) > 0) { + print ' +

    Matches: ' . safeHTMLstr($num) . '

    + +' . (isset($fieldsAR['type']) ? '' : '') . ''; + $emailAddresses = array(); + $row = 1; + while ($l = ocsql_fetch_assoc($r)) { + print '' . (isset($fieldsAR['type']) ? ('') : '') . ''; + if ($row==1) { $row=2; } else { $row=1; } + $emailAddresses[] = $l['paperid'] . '/' . $l['email']; + } + print ' +
    IDTitleContactType
    ' . safeHTMLstr($l['paperid']) . '' . safeHTMLstr($l['title']) . '' . safeHTMLstr($l['name']) . '' . safeHTMLstr($l['type']) . '
    +'; + displayEmailForm($emailAddresses, 'authors_all', 'Email Contact Author(s)'); + } else { + print '

    No matches found

    '; + } + } else { + print '

    Error encoutered while searching

    '; + } + } else { + print '

    Missing or invalid search parameters

    '; + } + } + + displayResultsFooter(); + + exit; +} + +// Display search form +printHeader('Submissions Search', 1); +displaySearchForm($fieldsAR, $dateFieldsAR, $intFieldsAR, $decFieldsAR, $searchFieldNum); +printFooter(); + +?> \ No newline at end of file diff --git a/chair/set_config.php b/chair/set_config.php new file mode 100644 index 0000000..1c19a03 --- /dev/null +++ b/chair/set_config.php @@ -0,0 +1,585 @@ + + + +'; + +if (!OCC_INSTALL_COMPLETE && isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + require_once "install-include.php"; + $token = ''; +} else { + beginChairSession(); + printHeader("Configuration", 1); + $token = $_SESSION[OCC_SESSION_VAR_NAME]['chairtoken']; + // Display active modules config + if (isset($OC_activeModulesAR) && !empty($OC_activeModulesAR)) { + $modules = array(); + foreach ($OC_activeModulesAR as $module) { + if (is_file('../modules/' . $module . '/settings.inc')) { + $modules[$module] = $OC_modulesAR[$module]['name']; + } + } + asort($modules); + $moduleOptions = ''; + foreach ($modules as $mid => $mname) { + $moduleOptions .= ''; + } + if (!empty($moduleOptions)) { + print ' +
    +

    + +Config Module: + +

    +
    +'; + } + } +} + +// YesNo fields +$yesNoFieldsAR = array('OC_notifyIncludeIP', 'OC_reviewerReadPapers', 'OC_reviewerSeeAssignedReviews', 'OC_reviewerCompleteBeforeSAR', 'OC_reviewerSeeOtherReviews', 'OC_reviewerSeeDecision', 'OC_reviewerSeeOtherReviewers', 'OC_reviewerSeeAuthors', 'OC_reviewerUnassignReviews', 'OC_reviewerSeeAdvocate', 'OC_advocateReadPapers', 'OC_advocateSeeOtherReviews', 'OC_advocateSeeAuthors', 'OC_advocateSeeDecision', 'OC_paperAdvocates', 'OC_editAcceptedOnly', 'OC_authorOneContact', 'OC_authorViewSubIfEditClosed'); + +// Notification array +$notifyAR = array( + 'OC_notifyAuthorSubmit' => OCC_WORD_AUTHOR . ' makes a submission', + 'OC_notifyAuthorEdit' => OCC_WORD_AUTHOR . ' updates (edits) submission', + 'OC_notifyAuthorEmailPapers' => OCC_WORD_AUTHOR . ' requests own submission list emailed', + 'OC_notifyAuthorUpload' => OCC_WORD_AUTHOR . ' uploads a file', + 'OC_notifyAuthorReset' => OCC_WORD_AUTHOR . ' requests password reset', + 'OC_notifyAuthorWithdraw' => OCC_WORD_AUTHOR . ' withdraws submission', + 'OC_notifyReviewerSignup' => 'Committee member signs up for account', + 'OC_notifyReviewerProfileUpdate' => 'Committee member updates profile', + 'OC_notifyReviewerReset' => 'Committee member resets password', + 'OC_notifyReviewerEmailUsername' => 'Committee member requests username emailed' +); + +// Fields that may be updated through this form +$settingsAR = array_merge($yesNoFieldsAR, array_keys($notifyAR), array( + 'OC_confNameFull', 'OC_confName', 'OC_confURL', 'OC_headerImage', 'OC_homePageNotice', 'OC_pcemail', 'OC_confirmmail', 'OC_keycode_reviewer', 'OC_reviewerSignUpNotice', 'OC_committeeFooter', 'OC_keycode_program', 'OC_programSignUpNotice', 'startid', 'OC_paperSubNote', 'OC_subConfirmNotice', 'OC_authorsMinDisplay', 'OC_authorsMax', 'OC_extar', 'OC_locales', 'OC_localeDefault', 'OC_timeZone', 'OC_wordForAuthor', 'OC_wordForChair' +)); + +if (OCC_ADVANCED_CONFIG) { + $emailAuthorRecipientsAR = array( + 1 => 'All', + 0 => 'Contact Only' + ); + + $settingsAR[] = 'OC_emailAuthorRecipients'; +} + +// Allow submission start ID to change? +if (($air = ocsql_query("SELECT COUNT(`paperid`) AS `count` FROM `" . OCC_TABLE_PAPER . "`")) && ($ail = ocsql_fetch_assoc($air)) && ($ail['count'] == 0) + && ($air = ocsql_query("SHOW TABLE STATUS WHERE `name`='" . OCC_TABLE_PAPER . "'")) && (ocsql_num_rows($air) == 1) && ($ail = ocsql_fetch_assoc($air)) +) { + $startid = $ail['Auto_increment']; +} + +// Submission? +$e = array(); +if (isset($_POST['submit']) && ($_POST['submit'] == "Save Settings")) { + // Check for valid submission + if (OCC_INSTALL_COMPLETE && !validToken('chair')) { + warn('Invalid submission', $hdr, $hdrfn); + } + // Check input + if (!isset($_POST['OC_confName']) || !preg_match("/\p{L}/u", $_POST['OC_confName'])) { + $e[] = 'Entity Short Name must include at least one alphanumeric character'; + } elseif (preg_match("/\"/", $_POST['OC_confName'])) { + $e[] = 'Entity Short Name must not contain quotes'; + } + if (!isset($_POST['OC_confNameFull']) || !preg_match("/\p{L}/u", $_POST['OC_confNameFull'])) { + $e[] = 'Entity Full Name must include at least one alphanumeric character'; + } + if (isset($_POST['OC_confURL']) && !empty($_POST['OC_confURL']) && !preg_match("/^(?:https?:\/\/|\/)/i", $_POST['OC_confURL'])) { + $e[] = 'Entity Web Address should start with https:// (if on another server) or / (for local server)'; + } + if (isset($_POST['OC_headerImage']) && !empty($_POST['OC_headerImage']) && !preg_match("/^(?:https?:\/\/|\/)/i", $_POST['OC_headerImage'])) { + $e[] = 'Header Image should start with https:// (if on another server) or / (if on local server)'; + } + if (!isset($_POST['OC_pcemail'])) { + $e[] = OCC_WORD_CHAIR . ' Email address invalid.'; + } elseif (preg_match("/,/", $_POST['OC_pcemail'])) { // Multiple addresses + $cmAR = explode(",", $_POST['OC_pcemail']); + foreach ($cmAR as $cm) { + $cm = trim($cm); + if (!validEmail($cm)) { + $e[] = OCC_WORD_CHAIR . ' Email does not appear to be valid'; + break; + } + } + } elseif (!validEmail($_POST['OC_pcemail'])) { // Single address + $e[] = OCC_WORD_CHAIR . ' Email does not appear to be valid'; + } + if (!isset($_POST['OC_confirmmail'])) { + $e[] = 'Notification Email address invalid. Try setting it the same as the ' . OCC_WORD_CHAIR . ' Email'; + } elseif (preg_match("/,/", $_POST['OC_confirmmail'])) { // Multiple addresses + $cmAR = explode(",", $_POST['OC_confirmmail']); + foreach ($cmAR as $cm) { + $cm = trim($cm); + if (!validEmail($cm)) { + $e[] = 'Notification Email does not appear to be valid'; + break; + } + } + } elseif (!validEmail($_POST['OC_confirmmail'])) { // Single address + $e[] = 'Notification Email does not appear to be valid'; + } + if (isset($_POST['startid']) && ! preg_match("/^[1-9]\d*$/", $_POST['startid'])) { + $e[] = 'Submission Starting ID invalid'; + } + if (isset($_POST['OC_authorsMinDisplay'])) { + if (! preg_match("/^[1-9][0-9]?$/", $_POST['OC_authorsMinDisplay'])) { + $e[] = 'Min Authors to Display must be a number between 1-99'; + } elseif (isset($_POST['OC_authorsMax']) && ($_POST['OC_authorsMinDisplay'] > $_POST['OC_authorsMax'] )) { + $e[] = 'Min Authors must be less than or equal to the Max Authors Allowed value'; + } + } + if (isset($_POST['OC_authorsMax']) && ! preg_match("/^[1-9][0-9]?$/", $_POST['OC_authorsMax'])) { + $e[] = 'Max Authors Allowed must be a number between 1-99'; + } + if (!isset($_POST['OC_extar']) || count($_POST['OC_extar']) == 0) { + $e[] = 'Select at least one file format'; + } else { // check formats are valid + foreach ($_POST['OC_extar'] as $fmat) { + if (!isset($OC_formatAR[$fmat])) { + $e[] = 'Invalid format selected'; + continue; + } + } + } + + $notifyKeysAR = array_keys($notifyAR); + foreach ($notifyKeysAR as $nk) { + if (!isset($_POST[$nk])) { + $_POST[$nk] = 0; + } elseif (!preg_match("/^[01]$/", $_POST[$nk])) { + $e[] = 'Invalid notification selection'; + continue; + } + } + foreach ($yesNoFieldsAR as $ynf) { + if (!isset($_POST[$ynf]) || ($_POST[$ynf] != 1)) { // catch case where checkbox used (e.g., rev/adv permissions) + $_POST[$ynf] = 0; + } + } + if (isset($_POST['OC_wordForAuthor']) && !in_array($_POST['OC_wordForAuthor'], $OC_wordForAuthorAR)) { + $e[] = 'Word for Author is invalid'; + } + if (isset($_POST['OC_wordForChair']) && !in_array($_POST['OC_wordForChair'], $OC_wordForChairAR)) { + $e[] = 'Word for Chair is invalid'; + } + if (!isset($_POST['OC_timeZone']) || !oc_validateTimeZone($_POST['OC_timeZone'])) { + $e[] = 'Time Zone is invalid'; + } + if (!isset($_POST['OC_locales']) || empty($_POST['OC_locales']) || !is_array($_POST['OC_locales'])) { + $e[] = 'At least one language must be selected'; + $_POST['OC_locales'] = array(); + } else { + if (!isset($_POST['OC_localeDefault']) || !isset($OC_languageAR[$_POST['OC_localeDefault']])) { + $e[] = 'Default Language is invalid'; + } elseif (!in_array($_POST['OC_localeDefault'], $_POST['OC_locales'])) { + $_POST['OC_locales'][] = $_POST['OC_localeDefault']; // auto-select default language + } + foreach ($_POST['OC_locales'] as $locale) { + if (!isset($OC_languageAR[$locale])) { + $e[] = 'Invalid locale selected: ' . safeHTMLstr($locale); + } + } + } + if (empty($e)) { + // Update form's OC_ fields + $_POST['OC_extar'] = implode(',', $_POST['OC_extar']); + $_POST['OC_locales'] = implode(',', $_POST['OC_locales']); + foreach (array_keys($_POST) as $p) { + if (preg_match("/^OC_[\w-]+$/", $p) && in_array($p, $settingsAR) && isset($OC_configAR[$p]) && ($OC_configAR[$p] != $_POST[$p])) { + updateConfigSetting($p, $_POST[$p], 'OC'); + $OC_configAR[$p] = $_POST[$p]; + } + } + + // Auto increment? + if (isset($startid) && ($startid != $_POST['startid'])) { + ocsql_query("ALTER TABLE `" . OCC_TABLE_PAPER . "` AUTO_INCREMENT=" . (int) $_POST['startid']); + } + + // if install, redirect + if (isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + header("Location: set_topics.php?install=1"); + exit; + } + + print '

    Configuration successfully updated

    '; + + // reset special vars to array + $_POST['OC_extar'] = explode(',', $OC_configAR['OC_extar']); + $_POST['OC_locales'] = explode(',', $OC_configAR['OC_locales']); + } +} else { // not submit; init POST with config values + $_POST = $OC_configAR; + $_POST['OC_locales'] = explode(',', $OC_configAR['OC_locales']); + // Allow submission auto increment to be set? + if (isset($startid)) { + $_POST['startid'] = $startid; + } +} + +if ((!OCC_INSTALL_COMPLETE) && isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + printHeader($hdr,$hdrfn); + print '

    Step 3 of 5: Tailor Configuration Settings

    '; +} + +if (!empty($e)) { + print '
    Please correct the following:
    • ' . implode('
    • ',$e) . '
    '; +} + +if (!preg_match("/^OpenConf/", $OC_configAR['OC_confNameFull']) && (OCC_LICENSE != 'Public')) { + $checkName = true; + print ' + +'; +} else { + $checkName = false; +} + +print ' +
    + +'; + +if ((!OCC_INSTALL_COMPLETE) && isset($_REQUEST['install'])) { + print ' + +'; +} + +print ' + +'; + +if (!isset($_POST['submit'])) { + print '

    Make desired changes, then click any Save Settings button

    '; +} + +print ' +
    +General Info (collapse) +
    +'; + +if ((OCC_LICENSE != 'Public') && defined('OCC_LICENSE_EVENT') && !defined('OCHS')) { + print ' +
    ' . safeHTMLstr(OCC_LICENSE_EVENT) . '
    For an entity or year other than the one listed above, please purchase and install a new OpenConf license.
    Each license permits a single installation of the OpenConf software.
    +'; +} + +print ' +
    Full name of event/journal for use on Web pages and in email messages
    +
    Abbreviated name, primarily used in email from and subject lines. Quotes not permitted.
    +
    Complete website address (including https:// )
    +
    Complete web address (including https:// ) for image to display atop every page. Leave blank to display Full Name.
    +
    + + +
    +
    + +
    +' . safeHTMLstr(OCC_WORD_CHAIR) . ' Email & Notification (collapse) +
    +
    Used for the From header of outgoing messages, as the general contact email address, and in case of errors or other follow-up. Although a comma-delimited list of addresses (without spaces) is permitted, this is not recommended as mail servers may reject messages with more than one. For any email issues, see the troubleshooting guide.
    +
    Receives a copy of confirmation emails sent to ' . oc_strtolower(OCC_WORD_AUTHOR) . 's and committee members; see options below. A comma-delimited list of addresses (without spaces) is permitted.
    + + +
    +'; + +foreach ($notifyAR as $nk => $nv) { + print '
    '; +} + +print ' +
    +

    Include IP address in notifications?

    ' . generateRadioOptions('OC_notifyIncludeIP', $yesNoAR, $_POST['OC_notifyIncludeIP']) . '

    +
    +
    + + +
    +
    + +
    +Reviewers (collapse) +
    +
    Keycode for signing up as a review committee member. May enter a comma-delimited list (no spaces).
    +
    + +
    + +
    + + +
    +
    +
    +'; + +if ($OC_configAR['OC_paperAdvocates']) { + print '
    '; +} + +print ' +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + +
    +Advocates (Program Committee) (collapse) +
    +
    ' . generateRadioOptions('OC_paperAdvocates', $yesNoAR, $_POST['OC_paperAdvocates'], 1, 'onclick="oc_showHideDiv(\'OC_paperAdvocates1\', \'advocates\')"') . '
    Select whether to make use of Advocates
    + +
    +
    Keycode for signing up as a program committee member. May enter a comma-delimited list (no spaces).
    +
    + +
    + + +
    +
    +
    +
    +
    +

    NOTE: Reviewer permissions are evaluated before advocate\'s

    +
    +
    + +
    + +
    + + +
    +Submissions (collapse) +
    +'; + +// Allow submission ID auto increment value? +if (isset($_POST['startid'])) { + print '
    Starting ID for submissions. Available only if there are no submissions in the system.
    '; +} + +print ' +
    + +
    + +
    Minimum number of ' . oc_strtolower(OCC_WORD_AUTHOR) . 's to display on submission form
    + +
    Maximum number of ' . oc_strtolower(OCC_WORD_AUTHOR) . 's allowed per submission (max: 99)
    + +
    ' . generateRadioOptions('OC_authorOneContact', $yesNoAR, $_POST['OC_authorOneContact']) . '
    Auto set ' . OCC_WORD_AUTHOR . ' 1 as contact and hide Contact ID field on submission form
    +'; + +if (OCC_ADVANCED_CONFIG) { + print ' +
    ' . generateRadioOptions('OC_emailAuthorRecipients', $emailAuthorRecipientsAR, $_POST['OC_emailAuthorRecipients']) . '
    ' . OCC_WORD_AUTHOR . '(s) to receive notices and ' . OCC_WORD_CHAIR . ' emails
    +'; +} + +print ' +
    ' . generateRadioOptions('OC_editAcceptedOnly', $yesNoAR, $_POST['OC_editAcceptedOnly']) . '
    Restrict Edit Submission to accepted submissions only
    + +
    ' . generateRadioOptions('OC_authorViewSubIfEditClosed', $yesNoAR, $_POST['OC_authorViewSubIfEditClosed']) . '
    Allow ' . oc_strtolower(OCC_WORD_AUTHOR) . ' to view submission if editing is closed
    + + +
    +
    +'; + +if (oc_hookSet('set-config-fileupload')) { + foreach ($GLOBALS['OC_hooksAR']['set-config-fileupload'] as $hook) { + require_once $hook; + } +} else { + print ' +
    +Files (collapse) +
    +
    + + +
    +
    +'; +} + +print ' +
    +Localization (collapse) +
    +
    Selecting multiple languages will enable a menu on the main OpenConf page to select one\'s language choice. Both ' . oc_strtolower(OCC_WORD_AUTHOR) . ' and reviewer pages are then displayed in the selected language. For additional information, or to assist with translations, visit www.OpenConf.com/translate/.' . (function_exists('gettext') ? '' : ' PHP must have gettext enabled.') . '
    +
    + +
    + +'; + +$wordUse = false; +if (in_array(OCC_WORD_AUTHOR, $OC_wordForAuthorAR)) { + $wordUse = true; + print ' +
    ***
    +'; +} + +if (in_array(OCC_WORD_CHAIR, $OC_wordForChairAR)) { + $wordUse = true; + print ' +
    ***
    +'; +} + +print ' +
    +'; + +if ($wordUse) { + print '

    *** Used for English (US) only. Some Chair features will still show Author/Chair.'; + if (oc_moduleValid('oc_customforms')) { + print ' If Custom Forms module in use, form fields may need to be manually updated to reflect desired Author/Chair words.'; + } + print '

    '; +} + +print ' + +
    +
    + +
    + + +'; + +oc_replaceCKEditor(array('OC_homePageNotice', 'OC_reviewerSignUpNotice', 'OC_committeeFooter', 'OC_programSignUpNotice', 'OC_paperSubNote', 'OC_subConfirmNotice')); + +printFooter(); +?> \ No newline at end of file diff --git a/chair/set_config_adv-module.php b/chair/set_config_adv-module.php new file mode 100644 index 0000000..b1a2e33 --- /dev/null +++ b/chair/set_config_adv-module.php @@ -0,0 +1,45 @@ + 'Advanced configuration disabled'); +} +elseif (!validToken('chair')) { // Check for valid submission + $res = array('error' => 'Invalid Token'); +} +elseif (isset($_POST['m']) && (($_POST['m'] == 'OC') || in_array($_POST['m'], $OC_activeModulesAR))) { + $q = "SELECT `setting` FROM `" . OCC_TABLE_CONFIG . "` WHERE `module`='" . safeSQLstr(urldecode($_POST['m'])) . "' ORDER BY `setting`"; + if ($r = ocsql_query($q)) { + if (ocsql_num_rows($r) == 0) { + $res = array('error' => 'Module has no configuration settings'); + } else { + $res = array('error' => '', 'settings' => array()); + while ($l = ocsql_fetch_assoc($r)) { + if (preg_match("/^OC_hide/", $l['setting'])) { continue; } + $res['settings'][] = $l['setting']; + } + } + } else { + $res = array('error' => 'DB Error: ' . safeHTMLstr(ocsql_error())); + } +} else { + $res = array('error' => 'Invalid module'); +} + +echo json_encode($res); + +exit; + +?> \ No newline at end of file diff --git a/chair/set_config_adv-setting.php b/chair/set_config_adv-setting.php new file mode 100644 index 0000000..cd1c660 --- /dev/null +++ b/chair/set_config_adv-setting.php @@ -0,0 +1,44 @@ + 'Advanced configuration disabled'); +} +elseif (!validToken('chair')) { // Check for valid submission + $res = array('error' => 'Invalid Token'); +} +elseif (isset($_POST['m']) && (($_POST['m'] == 'OC') || in_array($_POST['m'], $OC_activeModulesAR)) && isset($_POST['s']) && array_key_exists($_POST['s'], $OC_configAR)) { + $q = "SELECT * FROM `" . OCC_TABLE_CONFIG . "` WHERE `module`='" . safeSQLstr(urldecode($_POST['m'])) . "' AND `setting`='" . safeSQLstr(urldecode($_POST['s'])) . "'"; + if ($r = ocsql_query($q)) { + if (ocsql_num_rows($r) != 1) { + $res = array('error' => 'Setting not found'); + } else { + $res = array( + 'error' => '', + 'setting' => ocsql_fetch_assoc($r) + ); + } + } else { + $res = array('error' => 'DB Error: ' . safeHTMLstr(ocsql_error())); + } +} else { + $res = array('error' => 'Invalid module or setting'); +} + +echo json_encode($res); + +exit; + +?> \ No newline at end of file diff --git a/chair/set_config_adv-update.php b/chair/set_config_adv-update.php new file mode 100644 index 0000000..82646a4 --- /dev/null +++ b/chair/set_config_adv-update.php @@ -0,0 +1,45 @@ + 'Advanced configuration disabled'); +} +elseif (!validToken('chair')) { // Check for valid submission + $res = array('error' => 'Invalid Token'); +} +elseif (isset($_POST['m']) && (($_POST['m'] == 'OC') || in_array($_POST['m'], $OC_activeModulesAR)) && isset($_POST['s']) && array_key_exists($_POST['s'], $OC_configAR) && isset($_POST['v'])) { + if ($OC_configAR[$_POST['s']] == $_POST['v']) { + $res = array('error' => 'Setting unchanged'); + } else { + $q = "UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='" . safeSQLstr(urldecode($_POST['v'])) . "' WHERE `module`='" . safeSQLstr($_POST['m']) . "' AND `setting`='" . safeSQLstr($_POST['s']) . "' LIMIT 1"; + if ($r = ocsql_query($q)) { + if (ocsql_affected_rows() != 1) { + $res = array('error' => 'Setting failed to update properly'); + } else { + $res = array('error' => '', 'success' => 'Setting updated'); + } + } else { + $res = array('error' => 'DB Error: ' . safeHTMLstr(ocsql_error())); + } + } +} else { + $res = array('error' => 'Invalid module, setting, or value'); +} + +echo json_encode($res); + +exit; + +?> \ No newline at end of file diff --git a/chair/set_config_adv.css b/chair/set_config_adv.css new file mode 100644 index 0000000..4020190 --- /dev/null +++ b/chair/set_config_adv.css @@ -0,0 +1,32 @@ +/* +// +----------------------------------------------------------------------+ +// | OpenConf | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +// +----------------------------------------------------------------------+ +// | This source file is subject to the OpenConf License, available on | +// | the OpenConf web site: www.OpenConf.com | +// +----------------------------------------------------------------------+ +*/ + +#oc_notice { + position: fixed; + top: 0; + left: 100px; + min-width: 300px; + padding: 10px; + font-weight: bold; + font-size: 1.1em; + border: 4px solid #333; + display: none; + z-index: 100; +} +#oc_notice.ocnotice { + background-color: #9f9; + color: #000; +} +#oc_notice.ocerror { + background-color: #f99; + color: #000; +} + diff --git a/chair/set_config_adv.js b/chair/set_config_adv.js new file mode 100644 index 0000000..9802a8d --- /dev/null +++ b/chair/set_config_adv.js @@ -0,0 +1,178 @@ +// +----------------------------------------------------------------------+ +// | OpenConf | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +// +----------------------------------------------------------------------+ +// | This source file is subject to the OpenConf License, available on | +// | the OpenConf web site: www.OpenConf.com | +// +----------------------------------------------------------------------+ + +// init http request +var config_http = false; +try { + config_http = new XMLHttpRequest(); +} catch (trymicrosoft) { + try { + config_http = new ActiveXObject("Msxml2.XMLHTTP"); + } catch (othermicrosoft) { + try { + config_http = new ActiveXObject("Microsoft.XMLHTTP"); + } catch (failed) { + config_http = false; + } + } +} +// number of notices awaiting call back +var OC_notices = 0; +// notice div ID (see init()) +var OC_notice = false; +// default timeout +var TimeOut = 2000; + +function oc_init() { + OC_notice = document.getElementById("oc_notice"); +} +function hideNotice() { + OC_notices--; + if (OC_notices <= 0) { + document.getElementById("oc_notice").style.display = "none"; + } +} +function showNotice(noticeClass, noticeHTML, noticeTimeout) { + OC_notice.className = noticeClass; + OC_notice.innerHTML = noticeHTML; + TimeOut = noticeTimeout; + // display notice + OC_notice.style.display = "block"; + // set timeout to hide notice box, but only after last notice done displaying + OC_notices++; + setTimeout('hideNotice()', TimeOut); +} +function clearFields() { + document.getElementById('fields').style.display = 'none'; + document.getElementById('name').innerHTML = ''; + document.getElementById('description').innherHTML = ''; + document.getElementById('parse').innherHTML = ''; + document.getElementById('value').value = ''; +} + +function updateSettingValueCallback() { + if (config_http.readyState == 4) { + // Check for invalid response - likely due to time out? + if ((config_http.status != 200) || (config_http.responseText == '')) { + showNotice('ocerror', 'Unable to update setting.
    Use standard configuration page or edit value in database config table', 30000); + } else { // display server response as appropriate + var Response = eval("(" + config_http.responseText + ")"); + if (Response['error'] == '') { + if (Response['success']) { + showNotice('ocnotice', Response['success'], 3000); + } else { + showNotice('ocerror', 'Unable to update setting', 5000); + } + } else { + showNotice('ocerror', Response['error'], 5000); + } + } + } +} +function updateSettingValue(octoken) { + if (config_http) { + var params = "m=" + encodeURIComponent(document.getElementById('module').value) + + "&s=" + encodeURIComponent(document.getElementById('setting').value) + + "&v=" + encodeURIComponent(document.getElementById('value').value) + + "&token=" + encodeURIComponent(octoken); + config_http.open("POST","set_config_adv-update.php", true); + config_http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + config_http.onreadystatechange = updateSettingValueCallback; + config_http.send(params); + return(false); + } else { + return(true); + } +} + +function updateSettingCallback() { + if (config_http.readyState == 4) { + // Check for invalid response - likely due to time out? + if ((config_http.status != 200) || (config_http.responseText == '')) { + showNotice('ocerror', 'Unable to retrieve module settings.
    Use standard configuration page or edit value in database config table', 30000); + } else { // display server response as appropriate + var Response = eval("(" + config_http.responseText + ")"); + if (Response['error'] == "") { + if (Response['setting']) { + document.getElementById('name').innerHTML = Response['setting']['name']; + document.getElementById('description').innerHTML = Response['setting']['description']; + if (Response['setting']['parse'] == 1) { + document.getElementById('parse').innerHTML = 'Yes'; + } else { + document.getElementById('parse').innerHTML = 'No'; + } + document.getElementById('value').value = Response['setting']['value']; + document.getElementById('fields').style.display = 'block'; + } + } else { + showNotice('ocerror', Response['error'], 5000); + } + } + } +} +function updateSetting(obj, octoken) { + clearFields(); + document.getElementById("oc_notice").style.display = "none"; + if (obj.value != '') { + if (config_http) { + var params = "m=" + encodeURIComponent(document.getElementById('module').value) + + "&s=" + encodeURIComponent(obj.value) + + "&token=" + encodeURIComponent(octoken); + config_http.open("POST","set_config_adv-setting.php", true); + config_http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + config_http.onreadystatechange = updateSettingCallback; + config_http.send(params); + } else { + alert('Your browser has denied this operation. Please use standard config form, or edit values in the database config table'); + return(false); + } + } +} + +function updateModuleCallback() { + if (config_http.readyState == 4) { + // Check for invalid response - likely due to time out? + if (config_http.status != 200) { + showNotice('ocerror', 'Unable to retrieve module settings. Use standard configuration page or edit value in database config table', 30000); + } else { // display server response as appropriate + var Response = eval("(" + config_http.responseText + ")"); + if (Response['error'] == "") { + if (Response['settings']) { + var i = 1; + for (v in Response['settings']) { + document.getElementById('setting').options[i++] = new Option(Response['settings'][v], Response['settings'][v], false, false); + } + document.getElementById('settingMenu').style.display = "block"; + } + } else { + showNotice('ocerror', Response['error'], 5000); + } + } + } +} +function updateModule(obj, octoken) { + clearFields(); + document.getElementById("oc_notice").style.display = "none"; + document.getElementById("settingMenu").style.display = "none"; + var settingObj = document.getElementById('setting'); + settingObj.options.length = 1; + if (obj.value != '') { + if (config_http) { + var params = "m=" + encodeURIComponent(obj.value) + + "&token=" + encodeURIComponent(octoken); + config_http.open("POST","set_config_adv-module.php", true); + config_http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + config_http.onreadystatechange = updateModuleCallback; + config_http.send(params); + } else { + alert('Your browser has denied this operation. Please use standard config form, or edit values in the database config table'); + return(false); + } + } +} \ No newline at end of file diff --git a/chair/set_config_adv.php b/chair/set_config_adv.php new file mode 100644 index 0000000..0b04d6a --- /dev/null +++ b/chair/set_config_adv.php @@ -0,0 +1,100 @@ +Setting unchanged

    '; + } else { + $q = "UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='" . safeSQLstr($_POST['value']) . "' WHERE `module`='" . safeSQLstr($_POST['module']) . "' AND `setting`='" . safeSQLstr($_POST['setting']) . "' LIMIT 1"; + $r = ocsql_query($q) or err('Unable to update setting'); + if (ocsql_affected_rows() != 1) { + err('Setting failed to update properly'); + } else { + print '

    Setting updated

    '; + } + } + } else { + err('Invalid module, setting, or value'); + } +} + +print ' +

    Use caution when updating settings through the advanced configuration page as no validation of setting value is provided. If your browser does not support the functionality of this page, you should use the standard configuration update page or edit a setting\'s value in the database config table. A directory of configuration settings is available (open in new window).


    + +
    +
    + + + + +

    Module: +

    + +
    +

    +

    +
    + + + +
    +'; + +printFooter(); + +?> diff --git a/chair/set_conflicts.php b/chair/set_conflicts.php new file mode 100644 index 0000000..4e2ba1c --- /dev/null +++ b/chair/set_conflicts.php @@ -0,0 +1,136 @@ +Please go back and select at least one submission and one reviewer

    '; + } else { + foreach ($_POST['reviewers'] as $i) { + if (!preg_match("/^\d+$/", $i)) { + err('Reviewer ID invalid'); + } + foreach ($_POST['papers'] as $j) { + if (!preg_match("/^\d+$/", $j)) { + err('Submission ID invalid'); + } + $q = "INSERT INTO `" . OCC_TABLE_CONFLICT . "` (`paperid`, `reviewerid`) VALUES ($j,$i)"; + ocsql_query($q); + if (($merr = ocsql_errno()) != 0) { + if ($merr == 1062) { // Duplicate entry + print "

    ! Submission $j and reviewer $i already registered as a conflict.

    \n"; + } else { + print "

    ! Error registering submission $j and reviewer $i as a conflict

    \n"; + } + } else { print "

    Submission $j and reviewer $i registered as a conflict.\n"; } + } + } + print ' +

    » Set additional conflicts

    +

    » View conflicts

    + +'; + } +} else { + $pq = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title` FROM `" . OCC_TABLE_PAPER . "` ORDER BY `" . OCC_TABLE_PAPER . "`.`paperid`"; + $pr = ocsql_query($pq) or err("Unable to get submissions"); + // Get pad size for paper id's - yes, we really need the max id, but this should do:) + $rows = ocsql_num_rows($pr); + $psize = oc_strlen((string) $rows); + if ($rows == 0) { + print 'No submissions have been made yet

    '; + } + else { + if (!isset($_GET['s']) || ($_GET['s'] == "id")) { + $idsortstr = 'ID'; + $nsortstr = 'Name'; + $legend = "[ Reviewer ID - $nsortstr ]"; + $sortby = "`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + } else { + $idsortstr = 'ID'; + $nsortstr = 'Name'; + $legend = "[ Reviewer Name - $idsortstr ]"; + $sortby = "`" . OCC_TABLE_REVIEWER . "`.`name_last`, `" . OCC_TABLE_REVIEWER . "`.`name_first`"; + } + $rq = "SELECT `" . OCC_TABLE_REVIEWER . "`.`reviewerid`, `onprogramcommittee`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name` FROM `" . OCC_TABLE_REVIEWER . "` ORDER BY $sortby"; + $rr = ocsql_query($rq) or err("Unable to get reviewers"); + // Get pad size for reviewer id's - yes, we really need the max id, but this should do:) + $rsize = oc_strlen((string) ocsql_num_rows($rr)); + if (ocsql_num_rows($rr) == 0) { + print 'No reviewers have signed up yet

    '; + } + else { + print ' +

    + + +
    +

    Select Submission(s):

    +

    [ Submission ID - Title ]

    + +
    +
    +

    Select Reviewer(s):

    +

    ' . $legend . '

    + +

    Tip: Click the ID or Name links above
    to re-sort this list (page will reload)

    +
    + +
    + +

    +
    + '; + } + } +} + +printFooter(); + +?> diff --git a/chair/set_format.php b/chair/set_format.php new file mode 100644 index 0000000..5f60a65 --- /dev/null +++ b/chair/set_format.php @@ -0,0 +1,108 @@ +List Files Directory

    '; + +$format = $extAR[0]; +if (isset($_POST['submit']) && ($_POST['submit'] == "Set Format")) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + // Validate fields + if (!preg_match("/^\d+$/",$_POST['id'])) { // check for valid paper ID format + $e = "Invalid submission ID"; + } elseif (!in_array($_POST['format'], $extAR)) { // check for valid paper format + $e = "File format not in list of accepted formats"; + } else { + // check paper exists + $q = "SELECT `" . $formatDBFldName . "` FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`='" . safeSQLstr($_POST['id']) . "'"; + $r = ocsql_query($q) or err("Unable to retrieve submission ID " . $_POST['id']); + if (ocsql_num_rows($r) != 1) { + $e = "Submission ID not found"; + } else { + // rename file? only if file name w/new ext does not exist (but w/old ext does) + $l = ocsql_fetch_array($r); + if (in_array($l[$formatDBFldName], $extAR)) { + $oldFileName = $uploadDir . $_POST['id'] . '.' . $l[$formatDBFldName]; + $newFileName = $uploadDir . $_POST['id'] . '.' . $_POST['format']; + if (!oc_isFile($newFileName) && oc_isFile($oldFileName)) { + oc_renameFile($oldFileName, $newFileName) or err("Unable to update file name"); + } else { + print '

    Failed to update file name

    '; + } + } + // update format in db + $q = "UPDATE `" . OCC_TABLE_PAPER . "` SET `" . $formatDBFldName . "`='" . safeSQLstr($_POST['format']) . "' WHERE `paperid`='" . safeSQLstr($_POST['id']) . "'"; + ocsql_query($q) or err("Unable to update submission format"); + print '

    File format has been updated

    '; + } + } +} + +if (!empty($e)) { print '

    ' . $e . "

    \n"; } + +print ' +
    + + + +'; + +if (oc_hookSet('chair-set_format-formtop')) { + foreach ($GLOBALS['OC_hooksAR']['chair-set_format-formtop'] as $hook) { + require_once $hook; + } +} + +print ' + + + + + + + + + +
    Submission ID:
    Format:
     
    + +
    + +

    This will set the submission\'s file format in the database.
    +Also, if a file with the new extension does not already exist,
    the file is renamed from the old format extension to the new.

    +'; + +printFooter(); +?> diff --git a/chair/set_password.php b/chair/set_password.php new file mode 100644 index 0000000..52e4ac3 --- /dev/null +++ b/chair/set_password.php @@ -0,0 +1,166 @@ + 'disabled', + '$OC_pcemail' => 'Chair Email Address: ' . $OC_configAR['OC_pcemail'], + '$OC_confirmmail' => 'Notification Address: ' . $OC_configAR['OC_confirmmail'] +); +if (!empty($OC_configAR['OC_chairMFA']) && !isset($mfaAddresses[$OC_configAR['OC_chairMFA']]) && validEmail($OC_configAR['OC_chairMFA'])) { + $mfaAddresses[$OC_configAR['OC_chairMFA']] = $OC_configAR['OC_chairMFA']; +} + +// setup mfa? +if (isset($_GET['a']) && ($_GET['a'] == 'mfasetup')) { + if ( + isset($_GET['c']) + && (strlen($_GET['c']) == 32) + && preg_match("/^SETUP\|\|([^\|]+)\|\|([^\|]+)$/", $OC_configAR['OC_chairMFAcode'], $matches) + && ($_GET['c'] == $matches[1]) + && isset($mfaAddresses[$matches[2]]) + ) { + updateConfigSetting('OC_chairMFA', $matches[2]) or err('Unable to configure authentication address'); + $OC_configAR['OC_chairMFA'] = $matches[2]; + updateConfigSetting('OC_chairMFAcode', ''); + print '

    Authentication Address Set

    '; + } else { + print '

    Authentication Address verification failed

    '; + } + printFooter(); + exit; +} + +$e = ""; +if (isset($_POST['submit']) && ($_POST['submit'] == "Submit Changes")) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + if (!oc_password_verify($_POST['currpwd'], $OC_configAR['OC_chair_pwd'])) { + $e = 'Current password is incorrect'; + } else { + // password change? + if (isset($_POST['pwd1']) && !empty($_POST['pwd1']) && isset($_POST['pwd2']) && !empty($_POST['pwd2'])) { + if ($_POST['pwd1'] != $_POST['pwd2']) { + $e = 'New passwords do not match'; + } elseif ($_POST['pwd1'] == $OC_configAR['OC_chair_uname']) { + $e = 'Password may not match ' . OCC_WORD_CHAIR . ' username'; + } elseif (oc_strlen($_POST['pwd1']) < 10) { + $e = 'Password must be 10+ characters long'; + } else { + updateConfigSetting('OC_chair_pwd', oc_password_hash($_POST['pwd1'])) or err('Unable to change password'); + print '

    Password has been changed

    '; + } + } + // auth change? + if (isset($_POST['mfa']) && isset($mfaAddresses[$_POST['mfa']]) && ($_POST['mfa'] != $OC_configAR['OC_chairMFA'])) { + if ($_POST['mfa'] == '') { + updateConfigSetting('OC_chairMFA', '') or err('Unable to remove authentication address'); + $OC_configAR['OC_chairMFA'] = ''; + } elseif (preg_match("/^\\\$(?:OC_pcemail|OC_confirmmail)$/", $_POST['mfa'])) { + $code = oc_idGen(32); + $link = OCC_BASE_URL . 'chair/set_password.php?a=mfasetup&c=' . urlencode($code); + if (strlen($code) == 32) { + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='SETUP||" . safeHTMLstr($code) . '||' . safeHTMLstr($_POST['mfa']) . "' WHERE `module`='OC' AND `setting`='OC_chairMFAcode' LIMIT 1") or err('Unable to set authentication code'); + $subject = $OC_configAR['OC_confName'] . ' Multi-Factor Authentication Setup -- action required'; + $body = 'Hello, + +A request has been received to setup multi-factor authentication for the ' . $OC_configAR['OC_confName'] . ' ' . OCC_WORD_CHAIR . ' account. In order to complete the request, please click the link below prior to signing out of the account: + +' . $link . ' + +Thank you +'; + if (oc_mail($OC_configAR[substr($_POST['mfa'], 1)], $subject, $body)) { + print '

    An email has been sent to the Authentication Address below.
    Click the link in the email prior to signing out.

    '; + } else { + $e .= '
    Sending of message to complete multi-factor authentication failed'; + } + } else { + $e .= '
    Unable to generate authentication code'; + } + } else { + $e .= '
    Invalid auth setting'; + } + // to change to a custom email address, use the advanced settings feature + } + } +} + +if (!empty($e)) { + print '

    ' . $e . '

    '; +} + +print ' +
    +
    + + +
    +New Password (collapse) +
    +
    Enter your new password twice. May be left blank if only changing multi-factor authentication setting below.
    + +
    10+ characters
    + +
    + +
    +
    + + +
    +Multi-Factor Authentication (collapse) +
    +
    With an authentication address set, when the Chair enters their username and password a code is sent to the selected address which must be entered to complete the sign in process.
    + +
    When changing this option to a new address, a message is sent to the address with a link that must be clicked in order to confirm messages are received prior to the new address taking effect; click the link right away and before signing out.
    + +
    +
    + + +
    +Submit (collapse) +
    +
    Enter your current password and click the Submit Changes button.
    + +
    + + + +
    +
    + +
    +'; + +if (empty($OC_configAR['OC_chairMFA'])) { + print ' + +'; +} + +printFooter(); +?> diff --git a/chair/set_status.php b/chair/set_status.php new file mode 100644 index 0000000..4a0a9fa --- /dev/null +++ b/chair/set_status.php @@ -0,0 +1,291 @@ + + + +'); + +function oc_statusTime($h, $m) { + $time = ''; + $ampm = ''; + if ($h > 12) { + $time = ($h - 12) . ':' . $m; + $ampm = 'pm'; + } elseif ($h == 0) { + if ($m == 0) { + $time = 'midnight'; + } else { + $time = '12:30'; + $ampm = 'am'; + } + } elseif ($h == 12) { + if ($m == 0) { + $time = 'noon'; + } else { + $time = '12:30'; + $ampm = 'pm'; + } + } else { + $time = ltrim($h, '0') . ':' . $m; + $ampm = 'am'; + } + return($h . ':' . $m . ' || ' . $time . $ampm); +} + +function oc_statusEvent(&$l) { + $ret = ''; + if (!empty($l['open'])) { + $opendate = new DateTime($l['open']); + $ret .= '
    » will open on ' . safeHTMLstr($opendate->format('j F Y, H:i / g:ia')) . ' ' . safeHTMLstr($GLOBALS['OC_configAR']['OC_timeZone']) . '
    '; + } + if (!empty($l['close'])) { + $closedate = new DateTime($l['close']); + $ret .= '
    » will close on ' . safeHTMLstr($closedate->format('j F Y, H:i / g:ia')) . ' ' . safeHTMLstr($GLOBALS['OC_configAR']['OC_timeZone']) . '
    '; + } + return($ret); +} + +if (isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + require_once "install-include.php"; + $token = ''; +} else { + beginChairSession(); + printHeader("Open/Close Status",1); + $token = $_SESSION[OCC_SESSION_VAR_NAME]['chairtoken']; +} + +if (isset($_POST['ocsubmit']) && !empty($_POST['ocsubmit'])) { + // Check for valid submission + if (OCC_INSTALL_COMPLETE && !validToken('chair')) { + warn('Invalid submission'); + } + + if ($_POST['ocsubmit'] == "Set Status") { + if (preg_match("/deleteevent,((?:open|close)),(\w+),(\w+),_x/", implode("|", array_keys($_POST)), $matches)) { // delete scheduled event + if (ocsql_query("UPDATE `" . OCC_TABLE_STATUS . "` SET `" . safeSQLstr($matches[1]) . "`=NULL WHERE `module`='" . safeSQLstr($matches[2]) . "' AND `setting`='" . safeSQLstr($matches[3]) . "' LIMIT 1")) { + print '

    Event deleted

    '; + } else { + print '

    unable to delete event

    '; + } + } else { // regular Set Status + // Update form's OC_ fields - w/exceptions below requiring special handling + if ((!isset($_REQUEST['install'])) && isset($_POST['OC_submissions_open']) && ($_POST['OC_submissions_open'] == 1) && ($OC_statusAR['OC_submissions_open'] == 0) && (defined('OCC_LICENSE_EXPIRES')) && (strtotime(OCC_LICENSE_EXPIRES) < time())) { + unset($_POST['OC_submissions_open']); + print '

    ' . base64_decode('TmV3IFN1Ym1pc3Npb25zIG1heSBub3QgYmUgb3BlbmVkIGFzIHRoZSBsaWNlbnNlIGhhcyBleHBpcmVkLiAgRXh0ZW5kIHRoZSBzdXBwb3J0IHBlcmlvZCBvciBwdXJjaGFzZSBhIG5ldyBsaWNlbnNlIGlmIHRoaXMgaXMgYSBuZXcgZXZlbnQu') . '

    '; + } + foreach (array_keys($_POST) as $p) { + if (preg_match("/^[\w-]+/",$p) && isset($OC_statusAR[$p]) && preg_match("/^[01]$/i",$_POST[$p]) && ($OC_statusAR[$p] != $_POST[$p])) { + updateStatusSetting($p, $_POST[$p]); + $OC_statusAR[$p] = $_POST[$p]; + } + } + + // Success - if install, redirect, else let user know + if (isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + header("Location: install-complete.php"); + exit; + } else { + print '

    Status saved

    '; + } + } + } elseif ($_POST['ocsubmit'] == "Schedule") { // add an event + if ( + isset($_POST['status']) && preg_match("/^([a-z0-9_]+)\:([a-z0-9_]+)$/i", $_POST['status'], $matches) + && isset($_POST['openclose']) && preg_match("/^(?:open|close)$/", $_POST['openclose']) + && isset($_POST['day']) && preg_match("/^\d\d$/", $_POST['day']) + && isset($_POST['month']) && preg_match("/^\d\d$/", $_POST['month']) + && isset($_POST['year']) && preg_match("/^\d{4}$/", $_POST['year']) + && isset($_POST['time']) && preg_match("/^\d\d\:\d\d$/", $_POST['time']) + ) { + $module = $matches[1]; + $setting = $matches[2]; + if (($module != 'OC') && !oc_moduleActive($module)) { + print '

    module inactive

    '; + } elseif (!isset($OC_statusAR[$setting])) { + print '

    status not found

    '; + } else { + $date = $_POST['year'] . '-' . $_POST['month'] . '-' . $_POST['day']; + $todayDT = new DateTime(date('Y-m-d')); // date() used otherwise in case same day which would cause todayDT > dateDT + $dateDT = new DateTime($date); + if ($dateDT < $todayDT) { + print '

    event date must be in the future

    '; + } else { + if (ocsql_query("UPDATE `" . OCC_TABLE_STATUS . "` SET `" . (($_POST['openclose'] == 'open') ? 'open' : 'close') . "`='" . safeSQLstr($date . ' ' . $_POST['time'] . ':00') . "' WHERE `module`='" . safeSQLstr($module) . "' AND `setting`='" . safeSQLstr($setting) . "' LIMIT 1")) { + print '

    Event scheduled

    '; + } else { + print '

    unable to schedule event

    '; + } + } + } + } else { + print '

    invalid event field(s)

    '; + } + } else { + warn('Unknown action'); + } +} + +if (isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + printHeader($hdr,$hdrfn); + print '

    Step 5 of 5: Open Submissions & Sign-Up/In

    '; + $installFields = ''; +} else { + $installFields = ''; +} + +$ocq = "SELECT * FROM `" . OCC_TABLE_STATUS . "` WHERE `module`='OC' ORDER BY `order`, `setting`"; +$ocr = ocsql_query($ocq) or err('Unable to retrieve status settings'); + +$nonocq = "SELECT * FROM `" . OCC_TABLE_STATUS . "` WHERE `module`!='OC' ORDER BY `module`, `order`, `setting`"; +$nonocr = ocsql_query($nonocq) or err('Unable to retrieve additional status settings'); + +$divnum = 1; + +if (empty($installFields)) { // not installing OC + if (!isset($_POST['ocsubmit'])) { + print '

    Make desired changes then click any Set Status button, or schedule an event below:

    '; + } + + print ' +
    +
    + + +Set to
    on + + +
    +at ' . safeHTMLstr($OC_configAR['OC_timeZone']) . '
    +
    +
    +
    +
    +'; +} + +print ' + +
    + + +' . $installFields; + +print ' +
    +General (collapse) +
    +'; + +while ($l = ocsql_fetch_assoc($ocr)) { + if (!isset($l['dependency']) || empty($l['dependency']) || $OC_configAR[$l['dependency']]) { + print '
    ' . generateRadioOptions($l['setting'], $OC_statusValueAR, $l['status']) . '
    ' . oc_statusEvent($l); + if (!empty($l['description'])) { + print '
    ' . safeHTMLstr($l['description']) . '
    '; + } + } +} + +$module = ''; + +while ($l = ocsql_fetch_assoc($nonocr)) { + // skip inactive modules + if (!oc_moduleActive($l['module'])) { + continue; + } + // show module heading + if ($module != $l['module']) { + $module = $l['module']; + print '
    ' . safeHTMLstr($OC_modulesAR[$module]['name']) . ' Module (collapse)
    '; + } + if (!isset($l['dependency']) || empty($l['dependency']) || $OC_configAR[$l['dependency']]) { + print '
    ' . generateRadioOptions($l['setting'], $OC_statusValueAR, $l['status']) . '
    ' . oc_statusEvent($l); + if (!empty($l['description'])) { + print '
    ' . safeHTMLstr($l['description']) . '
    '; + } + print '
    '; + } +} + +print ' +

    +
    + +
    + +
    +'; + +printFooter(); +?> diff --git a/chair/set_topics.php b/chair/set_topics.php new file mode 100644 index 0000000..34a24f9 --- /dev/null +++ b/chair/set_topics.php @@ -0,0 +1,188 @@ + $tval) { + if (preg_match("/^name-(\d+)$/", $tid, $tmatch) && !empty($tval)) { + $q2 = "INSERT INTO `" . OCC_TABLE_TOPIC . "` (`topicid`, `topicname`, `short`) VALUES ('" . safeSQLstr($j) . "','" . safeSQLstr(substr($tval,0,250)) . "','" . safeSQLstr(substr($_POST["short-".$tmatch[1]],0,20)) . "')"; + issueSQL($q2); + $j++; + } + } + + // Success - if install, redirect, else let user know + if (isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + header("Location: set_status.php?install=1"); + exit; + } else { + print '

    Options successfully updated

    '; + } +} + +$displayWarning = false; +if (isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + printHeader($hdr,$hdrfn); + print '

    Step 4 of 5: Set Topics

    '; +} else { + $countsr = ocsql_query("SELECT COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "`") or err('Unable to check for existing submissions'); + $countsl = ocsql_fetch_assoc($countsr); + $countcr = ocsql_query("SELECT COUNT(*) AS `count` FROM `" . OCC_TABLE_REVIEWER . "`") or err('Unable to check for existing committee member'); + $countcl = ocsql_fetch_assoc($countcr); + + if (($countsl['count'] > 0) || ($countcl['count'] > 0)) { + $displayWarning = true; + } +} + +print ' +
    + + +

    Topics are used when making automated assignments. By default, both ' . oc_strtolower(OCC_WORD_AUTHOR) . 's and committee members are asked to select topics. Enter a sequential list of topics below. When you click on Set Topics, topics will be added sequentially regardless of the Topic ID listed, with blank topics skipped; thus topics should only be deleted until a submission has been made or committee member signed up. The Short Name field is optional; if present, it is used where a long topic name may be cumbersome.

    +'; + +if ($displayWarning) { + print '

    NOTE: As submissions have been made or committee members signed up already, deleting, changing, or re-ordering topics may result in data corruption. Instead, add new topics at the end, and rename topics no longer in use to "N/A" (without quotes) to have it skipped on applicable forms.

    '; +} + +if (isset($_REQUEST['install']) && ($_REQUEST['install'] == 1)) { + print ''; +} + +print ' + + +'; + +// Display existing topics +$q = "SELECT * FROM `" . OCC_TABLE_TOPIC . "`"; +$r = ocsql_query($q) or err("Unable to query topics"); +$topicNum = ocsql_num_rows($r); +$tAR = array(); +$row=1; +while ($l=ocsql_fetch_array($r)) { + print ' +'; + if ($row==1) { $row=2; } else { $row=1; } +} + +// Display additional rows +$addRows = ((($topicNum + 4) < $minTopics) ? ($minTopics - $topicNum) : 4); + +for ($i=1; $i <= $addRows; $i++) { + $topicNum++; + print ' +'; + if ($row==1) { $row=2; } else { $row=1; } +} + +print ' +
    Topic IDTopic NameShort Name*
    ' . $l['topicid'] . '
    ' . $topicNum . '
    + + + +
    +'; + +if (!oc_moduleActive('oc_customforms')) { + print ' +

    Allow ' . oc_strtolower(OCC_WORD_AUTHOR) . 's to select multiple submission topics? ' . generateRadioOptions('OC_multipleSubmissionTopics', $yesNoAR, $OC_configAR['OC_multipleSubmissionTopics']) . '
    +Select Yes to allow multiple topics, or No to limit ' . oc_strtolower(OCC_WORD_AUTHOR) . ' to one topic.

    + +

    Allow committee members to select multiple submission topics? ' . generateRadioOptions('OC_multipleCommitteeTopics', $yesNoAR, $OC_configAR['OC_multipleCommitteeTopics']) . '
    +Select Yes to allow multiple topics, or No to limit committee member to one topic.

    +'; +} + +print ' +

    Display topics alphabetically? ' . generateRadioOptions('OC_topicDisplayAlpha', $yesNoAR, $OC_configAR['OC_topicDisplayAlpha']) . '
    +Select Yes to display topics alphabetically on submission and committee sign up forms, or No to use order above.

    + + + +
    +'; + +printFooter(); + +?> diff --git a/chair/settings-export.php b/chair/settings-export.php new file mode 100644 index 0000000..a5392e8 --- /dev/null +++ b/chair/settings-export.php @@ -0,0 +1,201 @@ + array(), + 'configuration' => array(), + 'license' => ((OCC_LICENSE == 'Public') ? 'Public' : 'PlusPro'), + 'version' => $GLOBALS['OC_configAR']['OC_version'], + 'modules' => array() + ); + + // Module prep + if (oc_hookSet('settings-export-prep')) { + foreach ($OC_hooksAR['settings-export-prep'] as $f) { + require_once $f; + } + } + + // Check for selected settings + if (!isset($_POST['settings']) || (!is_array($_POST['settings'])) || (count($_POST['settings']) == 0)) { + warn('No settings selected', $hdr, $hdrfn); + exit; + } + + // Configuration settings + $settings['options'][] = 'configuration'; + $r = ocsql_query("SELECT `module`, `setting`, `value` FROM `" . OCC_TABLE_CONFIG . "` ORDER BY `module`, `setting`"); + while ($l = ocsql_fetch_assoc($r)) { + if (((in_array('configuration', $_POST['settings']) && ($l['module'] == 'OC')) || isset($settings['modules'][$l['module']])) + && !in_array($l['setting'], $excludeSettingsAR) + ) { + if (in_array($l['module'] . ':' . $l['setting'], $oc_encryptedSettingsAR)) { + $settings['configuration'][$l['module'] . ':' . $l['setting'] . ':occrypt'] = oc_decrypt($l['value']); + } else { + $settings['configuration'][$l['module'] . ':' . $l['setting']] = $l['value']; + } + } + } + + // Topics + if (in_array('topics', $_POST['settings'])) { + $settings['options'][] = 'topics'; + $r = ocsql_query("SELECT * FROM `" . OCC_TABLE_TOPIC . "` ORDER BY `topicid`"); + $settings['topics'] = array(); + while ($l = ocsql_fetch_assoc($r)) { + $settings['topics'][$l['topicid']] = array( + 'topicname' => $l['topicname'], + 'short' => $l['short'] + ); + } + } + + // Reviewers + if (in_array('reviewers', $_POST['settings'])) { + $settings['options'][] = 'reviewers'; + $r = ocsql_query("SELECT * FROM `" . OCC_TABLE_REVIEWER . "` ORDER BY `reviewerid`"); + $settings['reviewers'] = array(); + while ($l = ocsql_fetch_assoc($r)) { + foreach ($l as $k => $v) { + $settings['reviewers'][$l['reviewerid']][$k] = $v; + } + } + + // Reviewer Topics + if (in_array('topics', $_POST['settings'])) { + $settings['options'][] = 'reviewertopics'; + $r = ocsql_query("SELECT * FROM `" . OCC_TABLE_REVIEWERTOPIC . "` ORDER BY `reviewerid`, `topicid`"); + $settings['reviewertopics'] = array(); + while ($l = ocsql_fetch_assoc($r)) { + if (!isset($settings['reviewertopics'][$l['reviewerid']])) { + $settings['reviewertopics'][$l['reviewerid']] = array($l['topicid']); + } else { + $settings['reviewertopics'][$l['reviewerid']][] = $l['topicid']; + } + } + } + } + + // Templates + if (in_array('templates', $_POST['settings'])) { + $settings['options'][] = 'templates'; + $r = ocsql_query("SELECT * FROM `" . OCC_TABLE_TEMPLATE . "`"); + $settings['templates'] = array(); + while ($l = ocsql_fetch_assoc($r)) { + foreach ($l as $k => $v) { + $settings['templates'][$l['templateid']][$k] = $v; + } + } + } + + // Module settings + if (oc_hookSet('settings-export-process')) { + foreach ($OC_hooksAR['settings-export-process'] as $f) { + require_once $f; + } + } + + // Output file + oc_sendNoCacheHeaders(); + $fileName = 'openconf-settings'; + if (preg_match("/^\w+$/", $GLOBALS['OC_configAR']['OC_confName'])) { + $fileName .= '-' . $GLOBALS['OC_configAR']['OC_confName']; + } + $fileName .= '.oc'; + header('Content-Type: application/binary'); + header('Content-Disposition: attachment; filename="' . $fileName . '"'); + if (isset($_POST['pw2']) && !empty($_POST['pw2'])) { + print oc_encrypt(json_encode($settings), $_POST['pw2']); + } else { + print json_encode($settings); + } + exit; +} + +printHeader($hdr, $hdrfn); + +print ' +

    In order to save your settings for use in another OpenConf installation, select what you would like exported below, optionally enter an encryption password, then click the Export Settings button. A file dialog box will open up for you to save the settings file on your computer. When importing the settings, the same modules for which settings are exported must be pre-installed, and the same password entered. This file may contain sensitive information and should be protected accordingly.

    + + + +
    + + + +
    +
    + +
    +
    +
    +'; + +// Module settings +if (oc_hookSet('settings-export-options')) { + foreach ($OC_hooksAR['settings-export-options'] as $f) { + require_once $f; + } +} + +print ' +
    + +

        do not forget it!

    +
    + +

    Save the generated file to your computer instead of trying to open it. The file will have a .oc extension and your computer will likely be unable to open it as it is not intended for human consumption. If you would still like to look at it, use a text editor.

    + +

    If the optional encryption password is entered, the contents of the settings file will be encrypted. In order to import the settings, you will need to enter the same password. It will not be possible to recover the exported settings if the password is forgotten.

    +'; + + +printFooter(); +?> diff --git a/chair/settings-import.php b/chair/settings-import.php new file mode 100644 index 0000000..a711f54 --- /dev/null +++ b/chair/settings-import.php @@ -0,0 +1,201 @@ + $GLOBALS['OC_configAR']['OC_version'])) { + warn('The file is from a newer version of OpenConf. Upgrade this installation first, then try importing the settings once agian.'); + } + + // Check modules + if (isset($settings['modules']) && (count($settings['modules']) > 0)) { + $modules = array(); + foreach ($settings['modules'] as $module) { + $modules[] = safeHTMLstr($module); + } + sort($modules); + foreach ($settings['modules'] as $moduleID => $moduleName) { + if (!preg_match("/^[\w-]+$/", $moduleID) || !oc_module_installed($moduleID)) { + warn('The file includes settings for uninstalled modules. Please install the modules first, then import the settings. Modules included in the file are:
    • ' . implode('
    • ', $modules) . '
    '); + } + } + } + + // Module prep + if (oc_hookSet('settings-import-prep')) { + foreach ($OC_hooksAR['settings-import-prep'] as $f) { + require_once $f; + } + } + + // Configuration settings + if (isset($settings['configuration']) && is_array($settings['configuration']) && (count($settings['configuration']) > 0)) { + foreach($settings['configuration'] as $k => $v) { + if (preg_match("/^([^\:]+)\:([^\:]+)\:?(occrypt|)$/", $k, $matches) + && !in_array($matches[2], $excludeSettingsAR) + ) { + $module = $matches[1]; + $setting = $matches[2]; + if (isset($matches[3]) && ($matches[3] == 'occrypt')) { + $v = oc_encrypt($v); + } + updateConfigSetting($setting, $v, $module); + } + } + print '

    Configuration settings imported (including modules) ...

    '; + } + + // Topics + if (isset($settings['topics']) && is_array($settings['topics']) && (count($settings['topics']) > 0)) { + ocsql_query("TRUNCATE `" . OCC_TABLE_TOPIC . "`") or err('Unable to reset topic table'); + $q = "INSERT INTO `" . OCC_TABLE_TOPIC . "` (`topicid`, `topicname`, `short`) VALUES "; + foreach($settings['topics'] as $k => $kAR) { + $q .= "('" . safeSQLstr($k) . "', '" . safeSQLstr($kAR['topicname']) . "', '" . safeSQLstr($kAR['short']) . "'),"; + } + $q = rtrim($q, ','); + ocsql_query($q) or err('Unable to load topics - ' . safeHTMLstr(ocsql_error())); + print '

    Topics imported ...

    '; + } + + // Module settings -- run here in case Custom Forms modifies reviewer table + if (oc_hookSet('settings-import-process')) { + foreach ($OC_hooksAR['settings-import-process'] as $f) { + require_once $f; + } + } + + // Reviewers + if (isset($settings['reviewers']) && !empty($settings['reviewers'])) { + ocsql_query("TRUNCATE `" . OCC_TABLE_REVIEWER . "`") or err('Unable to reset reviewer table'); + foreach($settings['reviewers'] as $k => $kAR) { + $q = "INSERT INTO `" . OCC_TABLE_REVIEWER . "` SET "; + foreach ($kAR as $fld => $val) { + if ($val === null) { // special case for date fields which cannot be '' + $q .= "`" . $fld . "`=null,"; + } else { + $q .= "`" . $fld . "`='" . safeSQLstr($val) . "',"; + } + } + $q = rtrim($q, ','); + ocsql_query($q) or err('Unable to import reviewer - ' . safeHTMLstr(ocsql_error())); + } + print '

    Reviewers imported ...

    '; + } + + // Reviewer Topics + if (isset($settings['reviewertopics']) && is_array($settings['reviewertopics']) && (count($settings['reviewertopics']) > 0)) { + ocsql_query("TRUNCATE `" . OCC_TABLE_REVIEWERTOPIC . "`") or err('Unable to reset reviewertopic table'); + foreach($settings['reviewertopics'] as $k => $kAR) { + $q = "INSERT INTO `" . OCC_TABLE_REVIEWERTOPIC . "` (`reviewerid`, `topicid`) VALUES "; + foreach ($kAR as $topicid) { + $q .= "('" . safeSQLstr($k) . "', '" . safeSQLstr($topicid) . "'),"; + } + $q = rtrim($q, ','); + ocsql_query($q) or err('Unable to import reviewertopics - ' . safeHTMLstr(ocsql_error())); + } + print '

    Reviewer Topics imported ...

    '; + } + + // Templates + if (isset($settings['templates']) && !empty($settings['templates'])) { + foreach($settings['templates'] as $k => $kAR) { + if ( + isset($kAR['module']) + && + ( + ($kAR['module'] == 'OC') + || + oc_module_installed($kAR['module']) + ) + ) { + $qflds = ''; + foreach ($kAR as $fld => $val) { + if ( ! empty($val) && ($fld != 'templateid')) { + $qflds .= "`" . $fld . "`='" . safeSQLstr($val) . "',"; + } + } + $qflds = rtrim($qflds, ','); + $q = "INSERT INTO `" . OCC_TABLE_TEMPLATE . "` SET `templateid`='" . safeSQLstr($kAR['templateid']) . "', " . $qflds . " ON DUPLICATE KEY UPDATE " . $qflds; + ocsql_query($q) or err('Unable to import template - ' . safeHTMLstr(ocsql_error())); + } + } + print '

    Templates imported ...

    '; + } + + // Confirm + print '

    Settings have been imported – be sure to review your configuration.

    '; + +} else { + + print ' +

    In order to import settings from another OpenConf installation, select the settings file you previously exported, then click the Import Settings button. If this is not a new installation, you should first backup your database. Existing topics and committee member accounts will be deleted if any are in import file.

    + +
    + + +

    + +

    if password was entered when exporting; leave blank otherwise

    + +
    + + +
    +'; + +} + +printFooter(); + +?> diff --git a/chair/show_adv_review.php b/chair/show_adv_review.php new file mode 100644 index 0000000..3b3e1dd --- /dev/null +++ b/chair/show_adv_review.php @@ -0,0 +1,44 @@ + +Submission ID:' . safeHTMLstr($_GET['p']) . ' +Title:' . safeHTMLstr($l['title']) . ' +Advocate:' . safeHTMLstr($l['name']) . ' +Recommendation:'.$l['adv_recommendation'].' +Comments:'; +if (!empty($l['adv_comments'])) { print safeHTMLstr($l['adv_comments']); } else { print " "; } +print ' + +'; + +print '

    Return to Advocate Listings

    '; + +printFooter(); + +?> diff --git a/chair/show_paper.php b/chair/show_paper.php new file mode 100644 index 0000000..f294f88 --- /dev/null +++ b/chair/show_paper.php @@ -0,0 +1,116 @@ +View All Submissions

    '; + +if (!isset($_GET['pid']) || !ctype_digit($_GET['pid'])) { + err("Submission id is invalid"); +} + +// Get sub info +$spq = "SELECT * FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`='" . safeSQLstr($_GET['pid']) . "'"; +$spr = ocsql_query($spq) or err("Unable to get submissions "); + +if (ocsql_num_rows($spr)!=1) { + err("There does not appear to be a submission with that id (or there is more than one)"); +} + +$spl = ocsql_fetch_array($spr); + +// Get authors +$oc_authorNum = 0; +$qa = "SELECT * FROM `" . OCC_TABLE_AUTHOR . "` WHERE `paperid`='" . safeSQLstr($_GET['pid']) . "' ORDER BY `position`"; +$ra = ocsql_query($qa) or err("Unable to get " . oc_strtolower(OCC_WORD_AUTHOR) . "s "); +while ($a = ocsql_fetch_array($ra)) { + $apos = $a['position']; + foreach ($a as $akey => $aval) { + if (preg_match("/^(?:paperid|position)$/", $akey)) { continue; } + $spl[$akey . $apos] = $aval; + } +} +$oc_authorNum = $apos; + +// Get topics +$qt = "SELECT `topicid` FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `paperid`='" . safeSQLstr($_GET['pid']) . "'"; +$rt = ocsql_query($qt) or err("Unable to get topics "); +$spl['topics'] = array(); +while ($t = ocsql_fetch_array($rt)) { + $spl['topics'][] = $t['topicid']; +} + +require_once OCC_FORM_INC_FILE; +require_once OCC_SUBMISSION_INC_FILE; + +$files = 'File'; +if ($spl['format'] && oc_isFile($pfile = $OC_configAR['OC_paperDir'] . preg_replace("/\D/", "", $_GET['pid']) . "." . $spl['format'])) { + $files .= "" . safeHTMLstr($_GET['pid']) . ".".$spl['format']." (" . oc_formatNumber(oc_fileSize($pfile)) . ')'; +} else { + $files .= "not uploaded"; +} +$files .= ''; + +$advocate = ''; +if ($OC_configAR['OC_paperAdvocates']) { + $qadv = "SELECT `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `" . OCC_TABLE_REVIEWER . "`.`organization` FROM `" . OCC_TABLE_PAPERADVOCATE . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`='" . safeSQLstr($_GET['pid']) . "' AND `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + $radv = ocsql_query($qadv) or err("Unable to get advocate info "); + if (ocsql_num_rows($radv) == 1) { + $spladv = ocsql_fetch_array($radv); + $advocate .= 'Advocate:' . safeHTMLstr($spladv['name']) . ', ' . $spladv['organization'] . ''; + } +} + +$reviewers = ''; +$qrev = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `" . OCC_TABLE_REVIEWER . "`.`organization` FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`='" . safeSQLstr($_GET['pid']) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; +$rrev = ocsql_query($qrev) or err("Unable to get reviewers info "); +if (($rows = ocsql_num_rows($rrev)) > 0) { + $reviewers .= 'Reviewer(s):'; + while ($splrev = ocsql_fetch_array($rrev)) { + $reviewers .= (($rows > 1) ? '• ' : '') . '' . safeHTMLstr($splrev['name']) . ', ' . $splrev['organization'] . '
    '; + } + $reviewers .= ''; +} + +if (OCC_CHAIR_PWD_TRUMPS) { + print ' +
         
    +
    +'; +} + +print ' + + + + +'; + +oc_showFieldSet($OC_submissionFieldSetAR, $OC_submissionFieldAR, $spl); + +$extra = ''; +if (oc_hookSet('chair-show_paper')) { + foreach ($GLOBALS['OC_hooksAR']['chair-show_paper'] as $hook) { + require_once $hook; + } +} + +print $files . $extra . $advocate . $reviewers; + +print '
    ID:' . safeHTMLstr($_GET['pid']) . '
    Submitted:' . safeHTMLstr($spl['submissiondate']) . '
    Last Updated:' . safeHTMLstr($spl['lastupdate']) . '
    '; + +printFooter(); + +?> diff --git a/chair/show_review.php b/chair/show_review.php new file mode 100644 index 0000000..36aecf4 --- /dev/null +++ b/chair/show_review.php @@ -0,0 +1,42 @@ +Submission: ' . safeHTMLstr($_GET['pid']) . ' - ' . safeHTMLstr($l['title']) . '

    +

    Reviewer: ' . safeHTMLstr($_GET['rid']) . ' - ' . safeHTMLstr($l['name']) . '

    +'; + +displayReview($l, $_GET['rid'], $l['type']); + +printFooter(); + +?> diff --git a/chair/show_reviewer.php b/chair/show_reviewer.php new file mode 100644 index 0000000..4ae2993 --- /dev/null +++ b/chair/show_reviewer.php @@ -0,0 +1,105 @@ +View All Committee Members

    '; + +if (!isset($_GET['rid']) || !ctype_digit($_GET['rid'])) { + err('Reviewer ID is invalid'); +} + +require_once OCC_FORM_INC_FILE; +require_once OCC_COMMITTEE_INC_FILE; + +$extra = ''; + +// Get reviewer +$q = "SELECT * FROM `" . OCC_TABLE_REVIEWER . "` WHERE `reviewerid`='" . safeSQLstr($_GET['rid']) . "'"; +$r = ocsql_query($q) or err("Unable to get information"); +$l = ocsql_fetch_array($r); + +// Get topics +$qt = "SELECT `topicid` FROM `" . OCC_TABLE_REVIEWERTOPIC . "` WHERE `reviewerid`='" . safeSQLstr($_GET['rid']) . "'"; +$rt = ocsql_query($qt) or err("Unable to get topics "); +$l['topics'] = array(); +while ($t = ocsql_fetch_array($rt)) { + $l['topics'][] = $t['topicid']; +} + +$advocating = ''; +if ($OC_configAR['OC_paperAdvocates']) { + $aq = "SELECT `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title` FROM `" . OCC_TABLE_PAPERADVOCATE . "`, `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`='" . safeSQLstr($_GET['rid']) . "' AND `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid`"; + $ar = ocsql_query($aq) or err("Unable to get advocating info"); + if (ocsql_num_rows($ar) > 0) { + $advocating .= 'Advocating:'; + while ($al = ocsql_fetch_array($ar)) { + $advocating .= '' . $al['paperid'] . '. ' . safeHTMLstr($al['title']) . '
    '; + } + $advocating .= ''; + } +} + +$reviewing = ''; +$rq = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`title` FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`='" . safeSQLstr($_GET['rid']) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid`"; +$rr = ocsql_query($rq) or err("Unable to get reviewing info"); +if (ocsql_num_rows($rr) > 0) { + $reviewing .= 'Reviewing:'; + while ($rl = ocsql_fetch_array($rr)) { + $reviewing .= '' . $rl['paperid'] . '. ' . safeHTMLstr($rl['title']) . '
    '; + } + $reviewing .= ''; +} + +if (OCC_CHAIR_PWD_TRUMPS) { + print ' +
    + + +

    +
    + + + + + + +'; +} + +if ($OC_configAR['OC_paperAdvocates']) { + print ''; +} + +oc_showFieldSet($OC_reviewerFieldSetAR, $OC_reviewerFieldAR, $l); + +$extra = ''; +if (oc_hookSet('chair-show_reviewer')) { + foreach ($GLOBALS['OC_hooksAR']['chair-show_reviewer'] as $hook) { + require_once $hook; + } +} + +print $extra . $advocating . $reviewing; + + +print '
    Member ID:' . safeHTMLstr($_GET['rid']) . '
    Username:' . safeHTMLstr($l['username']) . '
    Signed Up:' . safeHTMLstr($l['signupdate']) . '
    Last Signed In:' . safeHTMLstr($l['lastsignin']) . '
    Advocate/PC: ' . (($l['onprogramcommittee'] == 'T') ? 'Yes' : 'No') . '

    '; + +printFooter(); + +?> diff --git a/chair/show_scores.php b/chair/show_scores.php new file mode 100644 index 0000000..3be70ee --- /dev/null +++ b/chair/show_scores.php @@ -0,0 +1,151 @@ +List All Submissions by Score

    +'; + +$pid = $_REQUEST['pid']; + +if (!preg_match("/^\d+$/",$pid)) { + warn("Invalid Submission ID"); +} + +if (isset($_POST['submit']) && !empty($_POST['submit'])) { + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + if ($_POST['submit'] == "Pending") { + $q = "UPDATE `" . OCC_TABLE_PAPER . "` SET `accepted`=NULL WHERE `paperid`='" . $pid . "'"; + ocsql_query($q) or err("Unable to set submission acceptance"); + } elseif (isset($OC_acceptanceColorAR[$_POST['submit']])) { + $q = "UPDATE `" . OCC_TABLE_PAPER . "` SET `accepted`='" . safeSQLstr($_POST['submit']) . "' WHERE `paperid`='" . $pid . "'"; + ocsql_query($q) or err("Unable to set submission acceptance"); + } elseif ($_POST['submit'] == "Submit Notes") { + $q = "UPDATE `" . OCC_TABLE_PAPER . "` SET `pcnotes`='" . safeSQLstr($_POST['pcnotes']) . "' WHERE `paperid`='" . $pid . "'"; + ocsql_query($q) or err("Unable to update notes"); + } +} + +$q2 = "SELECT CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `advocateid`, `adv_recommendation`, `adv_comments` FROM `" . OCC_TABLE_PAPERADVOCATE . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`='" . $pid . "' AND `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; +$r2 = ocsql_query($q2) or err("Unable to get recommendation"); +if (ocsql_num_rows($r2) == 0) { + $l2['adv_recommendation'] = 'No advocate was assigned to this submission

    '; + $l2['advocateid'] = NULL; + $l2['name'] = NULL; + $advcmts = ''; +} else { + $l2=ocsql_fetch_array($r2); + if (empty($l2['adv_recommendation'])) { + $l2['adv_recommendation'] = 'Not yet provided'; + $advcmts = ''; + } else { + $advcmts = safeHTMLstr($l2['adv_comments']); + $advcmts = preg_replace("/\n/","
    \n",$advcmts); + } +} + +$q3 = "SELECT `accepted`, `format`, `title`, `type`, `pcnotes` FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`='" . $pid . "'"; +$r3 = ocsql_query($q3) or err("Unable to get submission info"); +if (ocsql_num_rows($r3) != 1) { + warn("Unable to retrieve submission info"); + exit; +} else { + $l3 = ocsql_fetch_array($r3); + + $q = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.*, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name` FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`='" . $pid . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` ORDER BY `score`, `reviewerid`"; + $r = ocsql_query($q) or err("Unable to get scores"); + + if (oc_hookSet('show_scores')) { + foreach ($OC_hooksAR['show_scores'] as $h) { + require_once $h; + } + } + + print ' +Submission ID: ' . $pid . '
    +Title: ' . safeHTMLstr($l3['title']) . '
    '; + + if (!empty($l3['type'])) { + print 'Type: ' . safeHTMLstr($l3['type']) . '
    '; + } + + print ' +

    + + +
    +
    Decision: ' . (!empty($l3['accepted']) ? $l3['accepted'] : 'Pending') . ' +

    Change to:   +'; + + foreach ($OC_acceptanceValuesAR as $acc) { + if ($l3['accepted'] != $acc['value']) { + print '     '; + } + } + + if (!empty($l3['accepted'])) { + print ''; + } + + print ' +
    +
    +
    ' . OCC_WORD_CHAIR . ' Notes:

    +
    +
    +
    +'; + + if ($OC_configAR['OC_paperAdvocates']) { + print ' +


    +
    +
    Advocate: '. $l2['advocateid'] . ' - ' . safeHTMLstr($l2['name']) . '
    +
    Recommendation: ' . $l2['adv_recommendation'] . '
    +
    Comments:
    +
    '.$advcmts.'
    +
    +'; + } + + require_once OCC_REVIEW_INC_FILE; + + displayReviews($pid, $r, $l3['type']); + + // Additional data? + if (oc_hookSet('show_scores-bottom')) { + foreach ($OC_hooksAR['show_scores-bottom'] as $h) { + require_once $h; + } + } + +} // else show paper info + +printFooter(); + +?> diff --git a/chair/signin.php b/chair/signin.php new file mode 100644 index 0000000..0670552 --- /dev/null +++ b/chair/signin.php @@ -0,0 +1,188 @@ +Incorrect login. Please try again below or contact your OpenConf administrator. +

    + '; + $failedNum++; + if ($OC_configAR['OC_chairFailedSignIn'] != 'skip') { + updateConfigSetting('OC_chairFailedSignIn', $failedNum . ':' . time()); + } + } + elseif (!empty($OC_configAR['OC_chairMFA'])) { // multi-factor enabled + if (preg_match("/^\\\$(OC_pcemail|OC_confirmmail)\$/", $OC_configAR['OC_chairMFA'])) { + $tovar = substr($OC_configAR['OC_chairMFA'], 1); + $to = $OC_configAR[$tovar]; + } elseif (validEmail($OC_configAR['OC_chairMFA'])) { + $to = $OC_configAR['OC_chairMFA']; + } else { + warn('Invalid multi-factor setup', 'Sign In', 3); + exit; + } + $verifier = oc_idGen(32); + if (function_exists('random_int')) { + $code = random_int(100000, 999999); + } else { + $code = mt_rand(100000, 999999); + } + printHeader(OCC_WORD_CHAIR . ' Sign In', 3); + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='" . safeSQLstr(time() . '|' . hash('sha256', $code . $verifier)) . "' WHERE `setting`='OC_chairMFAcode' AND `module`='OC' LIMIT 1") or err('Unable to setup authentication code'); + $subject = $OC_configAR['OC_confName'] . ' Sign In'; + $body = 'Hello, + +The requested code is: + +' . $code . ' + +Please enter it within 15 minutes of requesting the code. +'; + oc_mail($to, $subject, $body) or err('Unable to email authenticate code'); + print ' +

    + +
    +

    Enter the code received via email and click the button within 15 minutes:

    +

    +

    +
    +
    + +'; + printFooter(); + exit; + } + else { // We have a winner! + oc_chairSignIn(); + } +} + +printHeader(OCC_WORD_CHAIR . ' Sign In', 3); + +if (!empty($errmsg)) { + print $errmsg; +} +elseif (isset($_GET['e']) && ($_GET['e'] == "exp")) { print 'Your session has timed out or you did not sign in properly. Please sign in again.

    '; } + +print ' +
    +

    + + + + +
    '; + +if ($OC_configAR['OC_chairUsernameForgot']) { + print ' (forgot username?)'; +} + +print '
    '; + +if ($OC_configAR['OC_chairPasswordForgot']) { + print ' (forgot password?)'; +} + +print '

    +
    +
    + +'; + +if ($OC_configAR['OC_ChairTimeout'] > 0) { + print ' +

    Note: Session times out after ' . $OC_configAR['OC_ChairTimeout'] . ' minutes of inactivity

    +'; +} + +printFooter(); + +?> diff --git a/chair/signout.php b/chair/signout.php new file mode 100644 index 0000000..9da00a7 --- /dev/null +++ b/chair/signout.php @@ -0,0 +1,31 @@ + diff --git a/chair/summary.php b/chair/summary.php new file mode 100644 index 0000000..be9cc75 --- /dev/null +++ b/chair/summary.php @@ -0,0 +1,512 @@ +'); +} else { + oc_addHeader(''); +} + +printHeader("Summary", 1); + +$colorAR = array('#5668E2', '#56AEE2', '#56E2CF', '#56E289', '#68E256', '#AEE256', '#E2CF56', '#E28956', '#E25668', '#E256AE', '#CF56E2', '#8A56E2'); +$statusAR = array( + 0 => '', + 1 => '' +); + +// Get count of papers +$r = ocsql_query("SELECT COUNT(`" . OCC_TABLE_PAPER . "`.`paperid`) AS `papertotal` FROM `" . OCC_TABLE_PAPER . "`") or err("Unable to query submission info"); +$l = ocsql_fetch_assoc($r); +$l1['papertotal'] = $l['papertotal']; + +// Get count of withdrawn submissions +$r = ocsql_query("SELECT COUNT(*) AS `withdrawtotal` FROM `" . OCC_TABLE_WITHDRAWN . "`") or err("Unable to query withdrawn submission info"); +$l = ocsql_fetch_assoc($r); +$l1['withdrawtotal'] = $l['withdrawtotal']; + +// Get count of reviews +$r = ocsql_query("SELECT COUNT(*) AS `reviewstotal` FROM `" . OCC_TABLE_PAPERREVIEWER . "`") or err("Unable to query reviews info"); +$l = ocsql_fetch_assoc($r); +$l1['reviewstotal'] = $l['reviewstotal']; + +// Get # of papers w/reviewers assigned +$r = ocsql_query("SELECT COUNT(DISTINCT(`paperid`)) AS `revassigned` FROM `" . OCC_TABLE_PAPERREVIEWER . "`") or err("Unable to query assigned count"); +$l = ocsql_fetch_assoc($r); +$l1['revassigned'] = $l['revassigned']; + +// Get count of advocate assignments +$r = ocsql_query("SELECT COUNT(*) AS `advocatingtotal` FROM `" . OCC_TABLE_PAPERADVOCATE . "`") or err("Unable to query advocate assignment info"); +$l = ocsql_fetch_assoc($r); +$l1['advocatingtotal'] = $l['advocatingtotal']; + +// Get # of uploads +$r = ocsql_query("SELECT COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` WHERE `format` IS NOT NULL") or err("Unable to query file uploads"); +$l = ocsql_fetch_assoc($r); +$uploadtotal = $l['count']; + +// Get count of signed up reviewers, advocates +$r = ocsql_query("SELECT `" . OCC_TABLE_REVIEWER . "`.`onprogramcommittee`, COUNT(`" . OCC_TABLE_REVIEWER . "`.`reviewerid`) AS `count` FROM `" . OCC_TABLE_REVIEWER . "` GROUP BY `" . OCC_TABLE_REVIEWER . "`.`onprogramcommittee`") or err("Unable to query reviewer info"); +$rcount = array(); +$rcount['T'] = 0; +$rcount['F'] = 0; +while ($l = ocsql_fetch_assoc($r)) { + $rcount[$l['onprogramcommittee']] = $l['count']; +} +// Get count of pc decision +$r = ocsql_query("SELECT `" . OCC_TABLE_PAPER . "`.`accepted`, COUNT(`" . OCC_TABLE_PAPER . "`.`paperid`) AS `count` FROM `" . OCC_TABLE_PAPER . "` GROUP BY `" . OCC_TABLE_PAPER . "`.`accepted`") or err("Unable to query submission info"); +$pcount = array(); +$pcount['T'] = 0; +$pcount['F'] = 0; +while ($l = ocsql_fetch_assoc($r)) { + $pcount[$l['accepted']] = $l['count']; +} +// Get count of completed reviews +$r = ocsql_query("SELECT COUNT(`" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`) FROM `" . OCC_TABLE_PAPERREVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`completed`='T'") or err("Unable to query reviews"); +$l = ocsql_fetch_row($r); +$reviewscompleted = $l[0]; +// Get count of started reviews +$r = ocsql_query("SELECT COUNT(`" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`) FROM `" . OCC_TABLE_PAPERREVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`completed`='F' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`updated` IS NOT NULL") or err("Unable to query started reviews"); +$l = ocsql_fetch_row($r); +$reviewsstarted = $l[0]; +// Get count of advocate recommendations +$r = ocsql_query("SELECT COUNT(`" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`) FROM `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`adv_recommendation` IS NOT NULL") or err("Unable to query recommendations"); +$l = ocsql_fetch_row($r); +$advocaterecommendations = $l[0]; +// Get acceptance type +$r = ocsql_query("SELECT `accepted`, COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` GROUP BY `accepted` ORDER BY `accepted`") or err("Unable to get score count"); +$accCountAR = array(); +while ($l = ocsql_fetch_assoc($r)) { + if (empty($l['accepted'])) { + $accCountAR['Pending'] = $l['count']; + } else { + $accCountAR[$l['accepted']] = $l['count']; + } +} +// Get submission types +$r = ocsql_query("SELECT `type`, COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` GROUP BY `type` ORDER BY `count` DESC, `type`") or err("Unable to get score count"); +$typeCountAR = array(); +$unknown = ''; +while ($l = ocsql_fetch_assoc($r)) { + if ($l['type'] == '') { + $unknown = $l['count']; + continue; + } + $typeCountAR[$l['type']] = $l['count']; +} +if ((count($typeCountAR) > 0) && !empty($unknown)) { + $typeCountAR['unknown'] = $unknown; +} + +$summaryAR = array(); +$SummaryIndex = 0; + +//// Submissions +$summaryAR[$SummaryIndex] = array( + 'header' => 'Submissions', + 'status' => array('( New ' . $statusAR[$OC_statusAR['OC_submissions_open']] . ' | Edit ' . $statusAR[$OC_statusAR['OC_edit_open']] . ' | Upload ' . $statusAR[$OC_statusAR['OC_upload_open']] . ' | View file ' . $statusAR[$OC_statusAR['OC_view_file_open']] . ' | Status ' . $statusAR[$OC_statusAR['OC_view_file_open']] . ' )'), + 'charts' => array() +); + +// Submissions - Submissions +$summaryAR[$SummaryIndex]['charts']['sub'] = array( + 'title' => 'Total', + 'link' => 'list_papers.php', + 'linktitle' => 'view submissions', + 'label' => $l1['papertotal'], + 'sublabel' => 'active', + 'values' => array( + array( + 'value' => $l1['papertotal'], + 'color' => '#99ccff', + 'label' => 'Active' + ), + array( + 'value' => $l1['withdrawtotal'], + 'color' => '#cccccc', + 'label' => 'Withdrawn' + ) + ) +); + +// Submission - Files +$summaryAR[$SummaryIndex]['charts']['files'] = array( + 'title' => OCC_WORD_AUTHOR . ' Files', + 'link' => 'list_papers.php', + 'linktitle' => 'view submissions and files', + 'label' => $uploadtotal, + 'sublabel' => 'uploaded', + 'values' => array( + array( + 'value' => $uploadtotal, + 'color' => '#99CCFF', + 'label' => 'Uploaded' + ), + array( + 'value' => ($l1['papertotal'] - $uploadtotal), + 'color' => '#f0f0f0', + 'label' => 'Pending' + ) + ) +); + +// Submissions - Type +if (count($typeCountAR) > 0) { + $summaryAR[$SummaryIndex]['charts']['type'] = array( + 'title' => 'Type', + 'link' => 'list_papers.php', + 'linktitle' => 'view submissions', + 'values' => array() + ); + $c = 0; + foreach ($typeCountAR as $type => $count) { + if ($type == 'unknown') { + $color = '#f0f0f0'; + } elseif ($c >= 12) { + $color = $colorAR[($c%12+1)]; + } else { + $color = $colorAR[$c]; + } + $summaryAR[$SummaryIndex]['charts']['type']['values'][] = array( + 'value' => $count, + 'color' => $color, + 'label' => $type + ); + $c++; + } +} + +// Submissions - Acceptance +$summaryAR[$SummaryIndex]['charts']['acc'] = array( + 'title' => 'Acceptance', + 'link' => 'list_scores.php', + 'linktitle' => 'view scores & accept/reject', + 'label' => 0, + 'sublabel' => 'accepted', + 'values' => array() +); +foreach ($OC_acceptanceValuesAR as $acc) { + $summaryAR[$SummaryIndex]['charts']['acc']['values'][] = array( + 'value' => (isset($accCountAR[$acc['value']]) ? $accCountAR[$acc['value']] : '0'), + 'color' => '#' . $OC_acceptanceColorAR[$acc['value']], + 'label' => $acc['value'] + ); + if (in_array($acc['value'], $OC_acceptedValuesAR)) { + $summaryAR[$SummaryIndex]['charts']['acc']['label'] += (isset($accCountAR[$acc['value']]) ? $accCountAR[$acc['value']] : '0'); + } +} +$summaryAR[$SummaryIndex]['charts']['acc']['values'][] = array( + 'value' => (isset($accCountAR['Pending']) ? $accCountAR['Pending'] : '0'), + 'color' => '#f0f0f0', + 'label' => 'Pending' +); + + +//// Committees & Assignments +$SummaryIndex++; +$summaryAR[$SummaryIndex] = array( + 'header' => 'Committees & Assignments', + 'status' => array('( Reviewer – Sign Up ' . $statusAR[$OC_statusAR['OC_rev_signup_open']] . ' | Sign In ' . $statusAR[$OC_statusAR['OC_rev_signin_open']] . ' | Reviewing ' . $statusAR[$OC_statusAR['OC_reviewing_open']] . ' )'), + 'charts' => array() +); + +// Committee - Members +$summaryAR[$SummaryIndex]['charts']['cmt'] = array( + 'title' => 'Committee Members', + 'link' => 'list_reviewers.php', + 'linktitle' => 'view committee members', + 'label' => $rcount['F'], + 'sublabel' => 'total', + 'values' => array( + array( + 'value' => $rcount['F'], + 'color' => '#99ccff', + 'label' => 'Review' + ) + ) +); + +// Committee - Review Assignments +$summaryAR[$SummaryIndex]['charts']['rev'] = array( + 'title' => 'Review Assignments', + 'link' => 'list_reviews.php', + 'linktitle' => 'view review assignments', + 'label' => $l1['reviewstotal'], + 'sublabel' => 'total', + 'values' => array( + array( + 'value' => $reviewscompleted, + 'color' => '#68E256', + 'label' => 'Completed' + ), + array( + 'value' => $reviewsstarted, + 'color' => '#AEE256', + 'label' => 'Started' + ), + array( + 'value' => ($l1['reviewstotal'] - $reviewscompleted - $reviewsstarted), + 'color' => '#F0F0F0', + 'label' => 'Pending' + ) + ) +); + +// Advocates? +if ($OC_configAR['OC_paperAdvocates']) { + // Add advocates to Committee - Members + $summaryAR[$SummaryIndex]['charts']['cmt']['label'] += $rcount['T']; + $summaryAR[$SummaryIndex]['status'][] = '( Program – Sign Up ' . $statusAR[$OC_statusAR['OC_pc_signup_open']] . ' | Sign In ' . $statusAR[$OC_statusAR['OC_pc_signin_open']] . ' | Advocating ' . $statusAR[$OC_statusAR['OC_advocating_open']] . ' )'; + $summaryAR[$SummaryIndex]['charts']['cmt']['values'][] = array( + 'value' => $rcount['T'], + 'color' => '#E28956', + 'label' => 'Program' + ); + // Committee - Advocate Assignments + $summaryAR[$SummaryIndex]['charts']['adv'] = array( + 'title' => 'Advocate Assignments', + 'link' => 'list_advocates.php', + 'linktitle' => 'view advocate assignments', + 'label' => $l1['advocatingtotal'], + 'sublabel' => 'total', + 'values' => array( + array( + 'value' => $advocaterecommendations, + 'color' => '#68E256', + 'label' => 'Completed' + ), + array( + 'value' => ($l1['advocatingtotal'] - $advocaterecommendations), + 'color' => '#F0F0F0', + 'label' => 'Pending' + ) + ) + ); + +} + +print ' + +'; + +if (oc_hookSet('chair-summary-pre')) { + foreach ($OC_hooksAR['chair-summary-pre'] as $v) { + include_once $v; + } +} + + +$chartNames = array(); +$chartJS = ''; +$barChartNames = array(); +$barChartJS = ''; +foreach ($summaryAR as $sectionID => $section) { + if ($sectionID > 0) { + print '
    '; + } + print '

    ' . safeHTMLstr($section['header']) . ' '; + foreach ($section['status'] as $status) { + print '' . $status . ' '; + } + print '

    '; + foreach ($section['charts'] as $chartIndex => $chart) { + if (isset($chart['type']) && ($chart['type'] == 'bar')) { + $labels = ''; + $data = ''; + $legend = ''; + foreach ($chart['values'] as $value) { + $labels .= '"' . safeHTMLstr($value['label']) . '",'; + $data .= $value['value'] . ','; + $legend .= safeHTMLstr($value['label'] . ': ' . $value['value']) . '
    '; + } + $labels = rtrim($labels, ','); + $data = rtrim($data, ','); + $barChartJS .= ' +"' . $chartIndex . '": { + labels: [ ' . $labels . ' ], + datasets: [ { + label: "", + backgroundColor: "rgba(153,204,244,0.5)", + borderColor: "rgba(153,204,244,0.8)", + hoverBackgroundColor: "rgba(153,187,204,0.75)", + hoverBorderColor: "rgba(153,204,244,1)", + borderWidth: "2", + data: [' . $data . '] + } ] +}, '; + $barChartNames[] = $chartIndex; + print '
    '; + print '' . $legend . ''; + print '
    '; + + } else { // default to doughnut + + $chartNames[] = $chartIndex; + print ' +
    +

    ' . + ( (isset($chart['link']) && !empty($chart['link']) ) ? + '' . safeHTMLstr($chart['title']) . '' + : + safeHTMLstr($chart['title']) + ) . +'

    +
    +'; + + if (isset($chart['label']) && ($chart['label'] !== '')) { + print '
    ' . safeHTMLstr($chart['label']); + if (isset($chart['sublabel']) && !empty($chart['sublabel'])) { + print '
    ' . safeHTMLstr($chart['sublabel']) . ''; + } + print '
    '; + } + + print ' + +
    +
      '; + // make sure there are no spaces between the
        and
      • tags otherwise activeSegment JS error will result -- OBE as activeSegment no longer in use + $total = 0; + $valuesStr = ''; + $jsStr = ''; + $labels = array(); + $data = array(); + $colors = array(); + foreach ($chart['values'] as $value) { + $total += $value['value']; + $valuesStr .= '
      • ' . safeHTMLstr($value['label']) . ': ' . $value['value'] . '
      • '; + $labels[] = safeHTMLstr($value['label']); + $colors[] = safeHTMLstr($value['color']); + $data[] = $value['value']; + } + $chartJS .= ' "' . $chartIndex . '": { labels: [ "' . implode('","', $labels) . '" ], datasets: [ { data: [' . implode(',', $data) . '], backgroundColor: [ "' . implode('","', $colors) . '" ], hoverBackgroundColor: [ "' . implode('","', $colors) . '" ] }] },' . "\n"; + print $valuesStr . '
      +
    +'; + } + } +} + + +print ' +
    + + +'; + +if (oc_hookSet('chair-summary')) { + foreach ($OC_hooksAR['chair-summary'] as $v) { + include_once $v; + } +} + +printFooter(); + +?> diff --git a/chair/unassign_review.php b/chair/unassign_review.php new file mode 100644 index 0000000..c61fc6f --- /dev/null +++ b/chair/unassign_review.php @@ -0,0 +1,46 @@ + 0))) { + foreach ($_POST['drop'] as $val) { + if (preg_match("/^\d+,\d+$/",$val)) { + list($pid,$rid) = explode(",", $val); + oc_deleteAssignments($pid, $rid); + } else { + print "Unable to process " . safeHTMLstr($val) . ".

    \n"; + } + } + print "

    Reviews have been unassigned.

    \n"; + if (($_POST['src']=="p") || ($_POST['src']=="r")) { + if (($miv = ini_get('max_input_vars')) && (count($_POST['drop']) > ($miv - 10))) { + print '

    The number of reviews selected for unassignment may have been greater than supported by this server. Click the link below as additional passes may be required.

    '; + } + print 'Return to Review Listings

    '; + } +} +else { + print '

    Please return and select the reviews to unassign.

    '; +} + +printFooter(); + +?> diff --git a/chair/upgrade.php b/chair/upgrade.php new file mode 100644 index 0000000..d238ab5 --- /dev/null +++ b/chair/upgrade.php @@ -0,0 +1,90 @@ + 3.10 -- requires a file openconf/upgrade/upgrade-3.0-3.1.inc) +$OC_upgradeAR = array( + '5.31' => '6.00', + '6.00' => '6.01', + '6.01' => '6.10', + '6.10' => '6.20', + '6.20' => '6.30', + '6.30' => '6.40', + '6.40' => '6.50', + '6.50' => '6.60', + '6.60' => '6.70', + '6.70' => '6.71', + '6.71' => '6.80', + '6.80' => '6.81', + '6.81' => '6.90', + '6.90' => '7.00', + '7.00' => '7.10', + '7.10' => '7.20', + '7.20' => 'done' +); + +beginChairSession(); + +printHeader("OpenConf Upgrade", 1); + +if (!isset($OC_upgradeAR[$OC_configAR['OC_version']])) { // valid current version? + warn('Current version unknown or no upgrade available.'); +} elseif ($OC_upgradeAR[$OC_configAR['OC_version']] == 'done') { // done? + print '

    The upgrade process appears to have been previously completed.

    '; +} elseif (isset($_POST['a']) && ($_POST['a'] == 'u')) { // ready to upgrade? + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + // Upgrade + while ($OC_upgradeAR[$OC_configAR['OC_version']] != 'done') { + print '

    Upgrading from ' . $OC_configAR['OC_version'] . ' to ' . $OC_upgradeAR[$OC_configAR['OC_version']] . ' ... '; + $upgradeFile = 'upgrade-' . $OC_configAR['OC_version'] . '-' . $OC_upgradeAR[$OC_configAR['OC_version']] . '.inc'; + if (is_file('../upgrade/' . $upgradeFile)) { + require_once('../upgrade/' . $upgradeFile); + // check installed modules for upgrades + foreach ($OC_modulesAR as $module => $moduleinfo) { + $moduleUpgradeFile = '../modules/' . $module . '/upgrade/' . $upgradeFile; + if (is_file($moduleUpgradeFile)) { + require_once($moduleUpgradeFile); + } + } + print 'Done

    '; + oc_loadConfig($OC_configAR); // update settings in case of dependencies and to update $OC_configAR['OC_version'] + } else { + warn('The upgrade file ' . safeHTMLstr($upgradeFile) . ' appears to be missing'); + } + } + if ($OC_upgradeAR[$OC_configAR['OC_version']] == 'done') { // done? + print ' +

    The upgrade process has completed. You may delete the upgrade directory.

    +

    Proceed to the main ' . safeHTMLstr(OCC_WORD_CHAIR) . ' Page

    +

    OpenConf logo

    +'; + // try to delete upgrade/v so it's not checked for again + unlink('../upgrade/v'); + } +} else { // first script call + print ' +

    This upgrade will take you through updating your OpenConf installation. Click (once) on the Upgrade button below to get started.

    + +
    + + +

    +
    +'; +} + +printFooter(); + +?> diff --git a/data/.htaccess b/data/.htaccess new file mode 100644 index 0000000..8d2f256 --- /dev/null +++ b/data/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/data/index.html b/data/index.html new file mode 100644 index 0000000..e69de29 diff --git a/data/index.php b/data/index.php new file mode 100644 index 0000000..e69de29 diff --git a/data/papers/.htaccess b/data/papers/.htaccess new file mode 100644 index 0000000..8d2f256 --- /dev/null +++ b/data/papers/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/data/zip/.htaccess b/data/zip/.htaccess new file mode 100644 index 0000000..8d2f256 --- /dev/null +++ b/data/zip/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/docs/.htaccess b/docs/.htaccess new file mode 100644 index 0000000..8d2f256 --- /dev/null +++ b/docs/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/docs/CHANGES b/docs/CHANGES new file mode 100644 index 0000000..6ac0a48 --- /dev/null +++ b/docs/CHANGES @@ -0,0 +1,1160 @@ +### OpenConf 7.20 ### + +- Added file formats MP3 (audio/mpeg), MP4 (video/mp4) +- Changed OC_wordForChair to skip use when preceded by Session (i.e., Session Chair) +- Changed Header Image to have max-width of 100% +- Changed SQL files to remove deprecated MySQL *int display attribute - new installs only +- Changed timezone file to locale directories; added include.php:oc_generateSelectTimeZoneOptions(), oc_validateTimeZone() +- Changed use of OC_mailParams in oc_mail() to use constant OCC_MAILPARAMS (undefined by default) and dropped setting +- Removed extraneous global definitions in oc_sendEmail() +- Deprecated lib/zones/zones.php + +Author: + +- Changed Edit Submission menu to View Submission when editing closed but viewing allowed +- Changed Edit Submission to handle View Submission without redirect; renamed view.php to view.inc and revised + +Chair: + +- Changed order of and consolidated some Chair home page menus +- Added settings to change Words for Author and Chair on configuration page (Localization section) +- Changed time zone setting to use new zones file format + +Acceptance: + +- Changed settings color selection to use input type=color + +Custom Forms: + +- Added Chair Only submission form field attribute to limit field editing to Chair only + +Payment: + +- Dropped deprecated UNSIGNED attribute to DECIMAL column +- Changed deprecated PHP in Braintree library + +Proceedings: + +- Removed extraneous word Proceedings from download + +Program: + +- Changed (ICS) calendar file UIDs to support calendar event updates +- Changed (ICS) calendar summary to include event Short Name at start (vs end) +- Changed My Program cookie to remember session selections for 90 days +- Changed My Program page to be bookmarkable +- Added session and submission links to the full program under My Program page and .ics calendar file +- Changed (ICS) calendar file time zone to use general time zone setting if program zone not configured +- Added full program page notice setting (OC_PROGRAM_fullProgramNotice) +- Added hooks: program-myprogram-top, program-myprogram-bottom, program-myprogram-ics-top +- Changed time zone setting to use new zones file format +- Changed time formatting and localization to be handled by PHP instead of MySQL +- Added user selectable time zone to full/glance program and session chair/discussant assignments +- Added time zone and location (room) links to XML program +- Changed session chair and discussant "pick" links to icon on Chair edit session page +- Added location (room) links; use location edit feature to add links +- Changed mobile program to use full program time zone if set +- Changed mobile program to hyperlink session title and location (room) name if links set +- Added session selection and highlight to mobile program integrated with My Program feature +- Added feature for Chair to change session type background colors for full program +- Changed session editing to display year selection with 3 options (current year + 2 more) +- Fixed blank year selection when editing session if session year option too far in future +- Deprecated princeXML integration + + +### OpenConf 7.10a ### + +- Fixed Chair committee member search +- Fixed Chair list submissions and unassign reviews ID count check + + +### OpenConf 7.10 ### + +- Updated plugins CDNs to latest stable releases (Chart.js, CKEditor, jQuery) +- Added skipping display of topics named N/A on submission and committee profile forms +- Changed default privacy policy cookie section, banner message and button text +- Added SameSite session cookie parameter for PHP >= 7.3 +- Removed check.gif and replaced its use with checkmark HTML character entity + +Chair: + +- Added search of submissions and committee members with emailing matches +- Added committee member sign up and last sign in dates to detailed member page +- Changed submission edit to not display email address confirmation message +- Added notice when trying to delete more submissions or unassign more reviews than supported by PHP max_input_vars +- Changed log search results order to sub-sort descending by logid + +CAPTCHA: + +- Added support for hCaptcha + +Custom Forms: + +- Changed message atop field option value editing dialog if data exists + +Copyright-IEEE: + +- Added support for submissions search of IEEE Copyright Type field + +MultiFile: + +- Removed _Photo# from list of displayed file icons + +Program: + +- Added speakers tab to mobile program +- Changed mobile program file viewing to not require full web program be open +- Added discussant email verification +- Added cookie confirmation when creating personalized program +- Changed List Discussants edit link to point at discussants section of session page +- Fixed missing author photo in program + + +### OpenConf 7.00a ### + +- Fixed advocate auto assignment (Auto Assign) +- Added referrer origin meta header (Copyright-IEEE) + + +### OpenConf 7.00 ### + +! Requires PHP 5.6+ with PHP 7.2+ recommended +! Requires MySQL 5.6+ (for earlier versions, may need to change OCC_DB_ENCODING and OCC_DB_COLLATION in include.php) +! Changed default MySQL encoding and collation to utf8mb4 (yay, emojis) and utf8mb4_unicode_520_ci, respectively, now set in include.php +! Dropped upgrade support for versions older than 5.31 (2014) +! Dropped Internet Explorer as a supported browser -- use something modern +- Added hooks: mailsend +- Added support for MySQL SSL connections +- Updated MySQL locale for Bosnian and Serbian +- Added module: ORCID +- Removed module: Publons +- Updated plugins CDNs to latest stable releases (Chart.js, CKEditor, CookieConsent, jQuery/UI) +- Updated time zones +- Added data/.htaccess with deny from all -- previously added to individual directories upon creation +- Added DB author.role, email_queue.reference_id +- Changed DB email address and organization varchar to 150 due to utf8mb4 key limitation (for new installs) +- Changed DB paperreviewer.score to smallint(4) (for new installs) +- Changed DB paperid and reviewerid to int(10) (for new installs) +- Changed DB paper.title to varchar(1000) +- Changed default form input maxlength to match DB.sql definition with utf8mb4 allowance +- Changed OC_mailHeaders X-Mailer to X-OC for new installations +- Changed upgrade to one-click for multi-version updates +- Changed module upgrades to no longer specifying module IDs in main upgrade-#-# files +- Changed oc_mail() to skip sending messages with empty subject or body and return true +- Changed consent form fields to be more translation friendly +- Changed mail From header to be encoded if multibyte +- Changed forms to not display empty fieldsets when all its fields removed (e.g., by a module) +- Changed review scoring to allow score of 0 for custom implementations +- Added support for custom translation of Configuration Notices +- Added support for changing English (en) strings through translation extras.inc feature +- Added include.php:oc_ucfirst() +- Added Reference ID to queued messages (log) with submission and/or reviewer ID if available +- Changed form confirmation messages to strip a/href tags from submitted fields +- Changed config setting update to strip out \r from strings to maintain translation parity +- Changed Chair sub/rev/cmt export to disable translation so data may be re-imported +- Fixed Email Chair feature message field update in case of error on submission +- Fixed review recovery Submit string translation +- Changed oc_createDir umask reset to after htaccess creation +- Removed deprecated creation of $$var for $OC_configAR[$var] and $OC_statusAR[$var] +- Removed deprecated functions: oc_checkField(), oc_checkAuthorField(), fix_magic_gpc() +- Removed deprecated form field attributes: size, maxsize +- Removed deprecated JS function: oc_showProcessing() +- Removed deprecated hook: chair-unassign-review +- Removed deprecated password support and lib/password_compat.php +- Removed deprecated variable/config support for: $OC_requireSubmissionUploadField, $OC_abstractLength +- Removed deprecated variables from review/show_abstract.php: $displayAuthorFields, $displaySubmissionFields + +Chair: + +- Added topic filter on review and advocate manual assignment pages +- Added confirmation dialog when Chair Email setting is changed +- Added reminder notification when software updated but upgrade not yet run +- Added submissions import feature +- Added template download to committee import +- Changed restoring of withdrawn submission to assign new ID to avoid conflict if re-used +- Changed export of multi-value fields (e.g., Topics, checkboxes, picklist) to be separated by newline +- Changed committee import to use newline (vs comma) delimited multi-value fields (e.g., Topics) +- Added encoding selecion and check for non-UTF-8 content to committee import +- Changed email preview to only display To and Subject headers +- Fixed missing message content for Contact Chair feature +- Fixed log search results table headers + +Committee: + +- Addded random string to keycodes during database install +- Added email address confirmation notice above sign up form submit button +- Fixed notification when submission withdrawn for incomplete reviews only + +Author: + +- Added email address confirmation notice above submission form submit button +- Added CRediT Contributor Role author field as option on Plus/Pro submission form +- Fixed edit link when timeout error occurs +- Removed deprecated Google+ URL author field + +Advocate Assign: + +- Added optional advocate notification of review(s) completion + +Custom Forms: + +- Added ability to modify Consent field text +- Added settings option to disable individual Submission Type field options +- Added special notice when removing Topics field from forms +- Fixed untranslated field note text on submission and committee profile forms +- Changed submission form title field to support up to 1000 characters +- Changed DB TEXT table fields to LONGTEXT in support of longer custom forms +- Updated jQuery CDN libraries +- Changed AJAX deprecated sync calls to async + +Docoloc: + +- Added save_file hook when saving reports + +Payment: + +- Updated Braintree library +- Removed Authorize.net DPM and SIM payment methods + +Program: + +- Added Session Types and Location (Room) Names editing feature +- Added option to vertically align concurrent RefereedPapers session presentations +- Added improved Title Case support for left/right quotation marks +- Added Title Case support within submission summary pages, mobile program, XML, and books +- Added consent text and date/time recording +- Fixed settings field hiding when selecting Conc. Session Sort Order value +- Fixed mobile program Talks tab to properly sort when first title character is a number +- Fixed incorrect files hook setup in scd-assignments +- Added List Accounts table row alternating background +- Fixed List Accounts table row display when no assignment present +- Added session type as CSS section class in mobile program +- Added setting (OC_PROGRAM_titleID) to include submission ID with title + +Reviewer Upload: + +- Updated deprecated hook and changed .inc for chair-unassign-review + +Submission Pre-Payment: + +- Changed deprecated oc_checkField() to oc_validateField() +- Added email address confirmation notice above submission form submit button + + +### OpenConf 6.90a ### + +- Added ability to modify Consent field text through Custom Forms module +- Added individual review score to Export Reviews options +- Changed Email Chair feature to send message From Chair address with Reply-To sender +- Fixed email sending when individual recipients selected under PHP>=7.1 +- Fixed error when sending email to individual program discussants or session chairs +- Fixed Payment module Authorize.net Accept.js processing + + +### OpenConf 6.90 ### + +- Chaged lib/config-sample.php define()s to use single-quote instead of double-quote, and updated replaceConstantValue() accordingly +- Changed ocsql_query to reset global DB error variables + +Chair: + +- Added options to select acceptance type and to keep comments when clearing review or advocate recommendation data +- Added email recipient group "Authors - All accepted" for when multiple accepted types are defined +- Added committee member profile update through Chair interface +- Added email feature option to send at most one message per email address +- Fixed erroneous message when manually assigning reviews that included an existing assignment + +Advocate: + +- Added notification when assigned submission withdrawn (template: committee-withdrawnsub) +- Changed table of submissions to advocate so those missing recommendations are shown at the top + +Reviewer: + +- Added notification when assigned submission withdrawn and review not yet completed (template: committee-withdrawnsub) +- Changed table of submissions to review so those not yet completed are shown at the top + +Acceptance: + +- Added "Pending" and "All Submissions" as reserved option labels + +Custom Forms: + +- Changed error message when adding field with invalid ID +- Fixed missing hidden field attributes newsubonly, enabled, donotvalidate + +MultiFile: + +- Added files-publish.inc to retrieve listing of publishable files for submissions + +Proceedings: + +- Added option to include review data on submission summary page (yay, open reviews!) +- Removed biographies variable from submission summary page + +Program: + +- Redeveloped mobile program -- all new! +- Added option to include review data on submission summary page (yay, open reviews!) +- Changed settings page options layout +- Changed matrix program and program book to use natural title sort +- Removed biographies variable from submission summary page + + +### OpenConf 6.81a ### + +- Added who sent Email Chair message to body in case headers obscured +- Added support for hyphenated log Type filter +- Added processing of $hdr parameter if Mail module in use but only for setting Reply To to From +- Fixed payment module hash decryption +- Fixed proceedings module download embedded links to author file +- Added program module SCD assignments hook oc_program-scd-assignments with variable control over whether email links included +- Changed committee profile form submission to skip automatic validation of username and password fields, and only perform manual validation +- Fixed reviewers import + + +### OpenConf 6.81 ### + +- Added Indonesian translation +- Added privacy policy and consent fields +- Added support for commas in Event Short Name +- Added hooks: delete_reviewer +- Added openconf.js:oc_toggleCheckboxes() +- Changed oc_getTemplate to skip translation for templates of type other +- Changed module info page display format +- Replaced deprecated nobr and p/ tags +- Changed GROUP BY queries to support MySQL ONLY_FULL_GROUP_BY +- Updated oc_idGen() to use openssl_random_pseudo_bytes() if available with optional length parameter +- Added fallback attempt when adding file to ZIP archive initially fails +- Added UTF-8 encoding param to mbstring fallback calls in oc_caseConvert() +- Added support for extra translation strings to be read from a file +- Updated idna_convert.class to 0.9.1 +- Changed idn_to_ascii calls to include variant +- Replaced PHP --with-mcrypt requirement with --with-openssl + +Chair: + +- Added multi-factor authentication option for sign in +- Added warning on automated assignments page when selecting not to keep existing assignments or to skip accepted submissions +- Added deletion of withdrawn submissions +- Added log and message queue search and delete +- Changed Chair Email Templates to prevent deletion of built-in templates +- Added option to encrypt exported settings file +- Fixed message preview and variables when selecting individual submission authors + +Reviewer: + +- Fixed translation of review confirmation email +- Changed View Submissions link to always be displayed + +Author: + +- Changed submission Title field default to be editable after new submissions are closed for new installations +- Added option for author to view submission once Edit Submission is closed + +Bidding: + +- Added support for committee member deletion + +CAPTCHA: + +- Removed deprecated reCAPTCHA 1.0 support + +Copyright-ACM: + +- Added author affiliation to ICPS export + +Copyright-IEEE: + +- Added option to display IEEE cookie banner + +Custom Forms: + +- Fixed translation of field option values on review and committee forms + +Discussion: + +- Added support for committee member deletion +- Fixed sort ordering of review scores + +Form Fields: + +- Added committee profile form + +Plagiarism-Docoloc: + +- Added submission deletion support +- Fixed settings FileType error + +Plagiarism-iThenticate: + +- Added support for submission deletion +- Removed deprecated HTTP_RAW_POST_DATA code in IXR_Library +- Changed deprecated mcrypt function calls to use openssl + +Program: + +- Reorganized Chair's Program menus section +- Added listing and export of discussant and session chair accounts +- Added listing with deletion of accounts +- Added consolidated program conflicts view +- Added Location (room) to at-a-glance program +- Added option to include time zone in personal program ICS file +- Added consent field to session chair / discussant (other) account sign up form +- Added full program option to convert names to title case +- Added email all link under each session when session chair viewing assignments +- Changed mobile program map to use Google Maps API -- key now required via module settings +- Changed lat/long update from address in settings to direct async JS call to GMap geocoding API and removed latlong.php +- Renamed Program - Contact Authors email recipient group and template to Program - Authors +- Fixed Program - Authors recipient group program-session email variable when OC_emailAuthorRecipients set to All +- Added book hooks: program-abstract_book-end, program-program_book-end + +Rebuttal: + +- Added support for committee member deletion + +Reviewer Upload: + +- Added file deletion feature for Chair +- Added setting to specify upload file format(s) +- Added support for committee member deletion +- Fixed dangling format when submission deleted + +Submission Payment: + +- Added consent field on submission form if privacy policy in use +- Added submission deletion support +- Fixed module uninstall + + +### OpenConf 6.80 ### + +- Changed document type to HTML5 +- Added Mail module for use of external SMTP server +- Removed support for old IE versions (conditional comments) +- Added hooks: display-review-post, mail, include-bottom, header-top-pre, chair-signout-pre, chair-signout-post, committee-signout-pre, committee-signout-post, committee-signup-pre, committee-update-pre +- Added dropdown and picklist field type support for usekey=false +- Updated CKEdtior CDN to 4.7.2 +- Changed setting default to not display reference links (OC_includeReferenceSearchLinks) for new installations +- Removed Microsoft Academic Search from reference links as it is decommissioned +- Updated time zones and modified to use zone1970.tab as source instead of deprecated zone.tab +- Removed default value for paper.submissiondate DB field in new installs +- Removed deprecated committee guidelines menu + +Chair: + +- Added option on Scores page to switch score sort order by clicking sort arrow +- Added committee member (CSV) import feature +- Added advocate name and email variables to email Author recipient groups +- Added scheduling option to open/close features +- Changed auto assign advocate max subs field size +- Changed email process queue handoff to relative URL to avoid session loss in some browsers +- Added ability to edit message when sending email without selecting recipients and option checked +- Changed configuration page to have fieldsets collapsed by default post-installation, and to display atop page when expanded +- Changed new password to require 10+ characters and differ from username +- Updated Set Conflicts interface + +Advocate: + +- Changed Submissions to Advocate table score to display hyphen (-) if no reviews present +- Added advocate permission option to see acceptance decision on View Submissions page (OC_advocateSeeDecision) +- Changed behavior of OC_advocateSeeOtherReviews so it is only enabled if OC_advocateReadPapers +- Added additional means of recommendation recovery on session timeout + +Reviewer: + +- Added reviewer permission option to display advocate contact info atop review form (OC_reviewerSeeAdvocate) +- Added reviewer permission option to see acceptance decision on View Submissions page (OC_reviewerSeeDecision) +- Changed review.php values for $showEmailCopy and $showCompletedReview to support corresponding field checked value status +- Changed behavior of OC_reviewerSeeOtherReviews so it is only enabled if OC_reviewerReadPapers +- Added additional means of review recovery on session timeout +- Changed use of SQL NOW() to PHP date() + +Author: + +- Added setting to display reviews on Check Status page even if submission decision pending (OC_authorSeePendingSubReviews) +- Added Photo Link author field to submission form + +Advocate Assign: + +- Updated auto notification message + +Copyright-ACM: + +- Fixed extraneous semi-colon in install-db + +Custom Forms: + +- Updated jQuery CDN libraries + +MultiFile: + +- Added full author email variables support for MultiFile Chair email recipient groups +- Added author photo support + +Payment: + +- Added support for Authorize.net Accept.js method +- Fixed settings warning on empty PayPal currency code + +Proceedings: + +- Added author photo support + +Program: + +- Added session data to settings export options +- Changed Title Camel Case feature to handle initial non-letter characters +- Changed mobile program data export to be JSON compliant +- Fixed mobile page edit invalid pageid notice +- Added author photo support +- Added date picker to session edit page + +Reviewer Upload: + +- Added advocate access to review file on submission recommendation page + +Submission Payment: + +- Added support for Authorize.net Accept.js + + +### OpenConf 6.71 ### + +- PHP 5.4+ now required; 5.3.7+ temporarily supported for non-Program module features +- Updated safeHTMLstr() to force UTF-8 and ENT_SUBSTITUTE +- Added hooks: settings-import-pre, settings-export-pre, db-backup-pre, db-reset-pre +- Fixed ZIP archive creation for bulk file download +- Changed browser field validation of char/word limit to use onchange vs onblur events to avoid Safari alert loop, and re-focus on field +- Fixed browser field validation of word limit to calculate empty or space-only string as zero count +- Updated Chart.js CDN version + +Chair: + +- Fixed unassign review/advocate feature +- Fixed notification message content when making manual review assignments to multiple advocates or reviewers +- Fixed auto assignment of reviewers when random assignment option selected and reviewer has no prior assignments + +Advocate Assign: + +- Fixed notification message content when making review assignments to multiple reviewers + +Custom Forms: + +- Added feature to check and repair custom fields in database +- Added feature to recalculate review scores when field Score attribute changes are made after reviews have been submitted +- Fixed JS error for legacy custom modules including empty values attribute in text fields +- Updated jQuery CDN version + +Plagiarism-iThenticate: + +- Updated to use ocGetFile +- Fixed missing report generation due to string/integer comparison + +Plagiarism-Docoloc: + +- Updated to use ocGetFile +- Fixed missing report generation due to string/integer comparison + +Program: + +- Added discussant name and affiliation variables for submission summary template +- Fixed double-encoding of author organization and country when displayed in full program + +Rebuttal: + +- Added support for custom review forms + + +### OpenConf 6.70 ### + +- Changed include.php:oc_strftime() to default to time() if time sent in is empty +- Added $who param to oc_deleteAssignments(), and logging of deleted review/advocate assignments +- Fixed settings import if custom committee member fields in use +- Added conversion of email address mailbox part when sending messages to workaround PHP mail() for utf-8 +- Changed regex character matching to support Unicode letter matching +- Changed include-forms.inc field validation to display a 1 for min word range if field is required and input resulted in error +- Added accessibility improvements +- Updated Chart.js CDN version and removed Chart.HorizontalBar plugin +- Updated CKEditor CDN version + +Chair: + +- Added file deletion under View Uploaded Files +- Added option to toggle emailing all authors or contact only to settings configuration page +- Added config option to allow reviewer to un-assign (own) review (OC_reviewerUnassignReviews) +- Fixed recipient mismatch warning when OC_emailAuthorRecipients=1 and only some addresses for a multi-author submission selected + +Committee Member: + +- Added reviewer un-assign (own) review feature +- Added committee-reviewunassign notification template +- Added support for non-ASCII, UTF-8 usernames + +Author: + +- Added support for emailing all authors per OC_emailAuthorRecipients on submit, edit, withdraw, upload +- Fixed retention of unsaved field changes when re-ordering authors + +Advocate Assign: + +- Added advocate name and email address as email variable options in reviewer notification of assignment messages +- Added review unassignment feature enabled by new Chair setting (OC_ADV_ASSIGN_unassignreview) +- Fixed incorrect reviewer assignment option listing based on OC_ADV_ASSIGN_limitmemberbytopic setting + +Copyright-ACM: + +- Added additional authors' email address column to CSV +- Changed default email address to be First Author + +Custom Forms: + +- Added built-in field deletion confirmation dialog +- Moved jQuery library definitions to init.inc + +Discussion: + +- Fixed last post link under list_threads + +Proceedings: + +- Changed settings page layout +- Added Chair-customizable submission summary (abstract) page template +- Added search feature with Chair-controlled field options +- Deprecated OC_PROCEEDINGS_includeAbstract setting -- use template feature instead + +Program: + +- Added author presentation sessions to session chair / discussant view assignments page +- Added abstract and author country as option in sessions export +- Added check for use of non-required submission fields in session export +- Added topic filter to session edit submission assignment +- Added session chair and discussant organization to full matrix program +- Added Chair-customizable submission summary (abstract) page template +- Deprecated OC_PROGRAM_includeAbstract setting -- use template feature instead +- Changed options for display of author (affiliation) details in full program to include organization, country, or both +- Fixed Chrome bug preventing scrolling under Talks tab +- Changed session Submissions Assigned order number to null for a submission if none yet selected + + +### OpenConf 6.60 ### + +- Changed install to assign unique value to OCC_SESSION_VAR_NAME to avoid multiple installation session collision +- Changed field note for fields with Long Label attribute set to display above instead of below field +- Changed include-forms.inc field validation to display a 1 for min char range if field is required and input resulted in error +- Changed include-forms.inc to just display hidden field and not full fieldset for those containing a single hidden field +- Updated CKEditor CDN library to 4.5.7 full +- Updated countries and time zones lib +- Added hidesubtypes attribute to include-forms.inc fields for designating submission types for which field should not be displayed +- Added optional $subtype param to include.php:oc_displayReviews(),oc_displayReview() in support of hidesubtypes + +Chair: + +- Added alert note pop-up if multiple addresses entered for Chair Email on config page +- Added config setting OC_allowEmailConflict to optionally permit author/reviewer pairing with same email address, with option on List Conflicts page +- Added config setting OC_authorOneContact to Configuration page +- Added config setting OC_emailAuthorRecipients to designate author recipients of Chair emails (0=contact only, 1=all) + +Author: + +- Added author-upload email notification template +- Added config setting OC_authorOneContact to force Author 1 as the contact author and hide the Contact Author field +- Added config setting OC_authorsRequiredData to designate whether the required attribute for author fields applies to all (0), first (1), or contact (2) + +Advocate Assign: + +- Fixed assign_reviews.php to prevent reviewer use + +Custom Forms: + +- Added review form field attribute to specify submission types for which the field should be excluded + +Discussion: + +- Added support for hidesubtypes + +IEEE eCopyright: + +- Updated IEEE test server URL + +MultiFile: + +- Added support for emailing all authors + +Program: + +- Added session chair to discussant view assignments listing +- Added submission topics to abstract and program books +- Added support for emailing all authors + +Rebuttal: + +- Added support for emailing all authors + +Reviewer Upload: + +- Changed session time verification to account for different PHP/MySQL times + + +### OpenConf 6.50 ### + +- DB: added paperrevewer.assigned +- Added Persian translation +- Added hooks: author-submit-postsave, chair-email-variables, chair-email-authors, header-top, footer-bottom, chair-session +- Added modules: Auto Assign, Publons +- Added include.php function: oc_inConflict() +- Addded separate open/close of committee review and advocacy (OC_rev_review_open, OC_pc_advocate_open) +- Updated CKEditor CDN library to 4.5.6 +- Changed include-download.inc action parameter name to daction for module deconfliction +- Fixed include-download.inc memory limit calculation if only numbers reported by PHP +- Changed language sort order to language name based on locale.inc order + +Chair: + +- Changed auto review assignment suggested values to account for whether PC members are assigned as reviewers +- Changed module sort order to case insensitive +- Changed username character limit to 50 +- Fixed summary page notice for undefined acceptance values +- Added review assignment date + +Committee Member: + +- Changed username character limit to 50 +- Changed features with conflict detection to account for review/advocate assignment + +Advocate Assign: + +- Added option to restrict list of reviewer assignees to those with matching topics to the advocate +- Added review assignment date + +Copyright-IEEE: + +- Changed ArtSource setting to allow longer codes + +Custom Forms: + +- Updated jQuery and jQueryUI CDN version + +Payment: + +- Added optional PayPal currency code setting + +Proceedings: + +- Added encoding to downloaded proceedings pages + +Program: + +- Changed program and page detection of HTML tags to be broader +- Fixed missing room info for concurrent sessions under full program matrix view +- Added option to use * for session title -- the title will then be auto-changed to that of a single submission assigned to the session + +Reviewer Upload: + +- Added Chair bulk download of reviewer-uploaded files + + +### OpenConf 6.40 ### + +- DB: added template.type, template.variables, reviewer.orcid +- Added hooks: show_scores, committee-advocate-fields, committee-advocate-extra, committee-advocate-validate, committee-advocate-save, committee-advocate-preinc, committee-advocate-inc, chair-unassign-advocate, chair-unassign-reviewer +- Deprecated hook: chair-unassign-review (use chair-unassign-reviewer instead) +- Changed English country names to use Unicode CLDR. The ISO English names may still be found in lib/locale/en/countries-iso.php +- Added off-screen skip navigation link and other accessibility improvements +- Added output buffer flush before include-download.inc readfile to avoid running out of memory +- Added include.php functions: oc_deleteAssignments(), oc_getTemplate(), oc_replaceVariables() +- Fixed display of topic/session form fields in special cases where they are auto-converted from checkboxes to radio buttons +- Changed auto email notification text from hard-coded to database template table +- Changed dropdown fields to display blank option even if field is required + +Chair: + +- Added optional cell character limit for submissions/reviews export +- Changed summary page format +- Fixed saving OC_topicDisplayAlpha setting when reset to No in set_topics.php +- Added confirmation dialog when submissions deleted/withdrawn +- Changed default email recipient group to none +- Added option on auto review assignment to specify different number of max submissions to be assigned PC members vs reviewers +- Fixed warning on export reviews guide when field does not contain values attribute +- Changed settings export to include version number, and import to check installed version is same or more current +- Added auto email notification editor + +Committee Member: + +- Changed submission assignments displayed on committee member home page to be sorted by ID +- Changed advocate.php to use advocate.inc and include-forms.php +- Added config setting for hiding committee profile form fields (OC_hideCmtFields) + +Author: + +- Added advanced configuration setting for limiting file upload size (OC_fileLimit) + +Advocate Assign: + +- Added support for notification template + +Bidding: + +- Added support for specifying different number of max submissions per PC member vs reviewer on auto review assign +- Changed Chair summary display to match new format + +Custom Forms: + +- Added support for OC_hideCmtFields + +FileType: + +- Added file format identification using PHP Fileinfo + +IEEE Copyright: + +- Removed deprecated ArtDate +- Changed ArtEmail to submit all authors' email addresses +- Added option to record, view and export IEEE-returned copyright type (OC_IEEE_COPYRIGHT_recordCopyright, OC_IEEE_COPYRIGHT_token) +- Fixed use of custom return URL + +MultiFile: + +- Updated file-link2.inc to reflect new assignments view filename +- Changed Chair summary display to match new format +- Changed MF type delete to leave `paper` table format column in place to avoid error in case withdrawn submissions are restored +- Changed uninstall to iterate through matching format column names instead of using registered MF type IDs + +Plagiarism-iThenticate: + +- Added title prefix setting (OC_ITHENTICATE_titlePrefix) + +Program: + +- DB: Changed module_oc_program_scdaccounts.code to .password +- Added base author fields to session export +- Added program-export-session-setup and program-export-session-process hooks to session export +- Added ability to sign in with author or reviewer account for accessing session chair and discussant assignments +- Changed abstract book to use native language +- Fixed missing charset set in program download +- Fixed mobile app map URL parameter when https used +- Fixed program book schedule room display +- Fixed program book date variables +- Added cell char limit option to session export +- Added time format configuration setting (OC_PROGRAM_timeFormat) and changed program feature to use it +- Added .ics export of personalized program +- Added browser cookie to remember personalized program option for 30 days +- Added session topic, if included, to full web program display +- Moved program-mobile.php to mobile/data.php +- Added mobile/cache.php, updating references + + +### OpenConf 6.30 ### + +- Added Hungarian translation +- Added hooks: author-edit-bottom, author-email_papers-bottom, author-paper-bottom, author-upload-bottom, author-reset-bottom, author-status-bottom, author-withdraw-bottom +- Added setting for base OpenConf URL (OC_openconfURL), dynamically generated if not already defined +- Changed header class from p to h1 +- Added $length parameter to generateSelectOptions() for truncating options display length +- Added DB: reviewer.lastupdate, reviewer.lastsignin +- Removed IE8 emulation and openconf-ie.css +- Removed deprecated -[moz|khtml]-border-radius styles +- Changed OCC_CHAIR_PWD_TRUMPS check from individual sign in pages to oc_password_verify() +- Added MySQL locale strings to lib/locale.inc + +Chair: + +- Added submission type filtering to Submission Scores page +- Added submission type and acceptance status filtering to List Submissions, List Reviews, and List Advocates pages +- Changed Create Stub Title field max length +- Fixed submissions export feature when advocate data selected +- Changed list of automatically detected conflicts displayed on Set Conflicts page to account for OC_allowOrgConflict +- Added option to toggle OC_allowOrgConflict on Set Conflicts page +- Added confirmation dialog to automated assignments when overwriting existing ones +- Added option to skip submissions with acceptance decision when making automated review/advocate assignments +- Added option to select submission type for making automated review/advocate assignments +- Added OC_authorsMinDisplay and OC_authorsMax options to Configuration page +- Added option for overriding PC decision if not pending when changing acceptance selection on scores page, and changed default behavior to not override +- Added option for setting acceptance decision to match advocate recommendation on scores page +- Added OpenConf URL to manual review/advocate assignment email notification +- Added [:OC_openconfURL:] email variable + +Author: + +- Changed contact author field to be hidden on submission form if OC_authorsMinDisplay and OC_authorsMax are set to 1 +- Removed country from list of fields checked for authors data in case it is set to required and has value pre-selected + +Bidding: + +- Added support for new Chair automated assignment options for constraining submission assignments + +CAPTCHA: + +- Added support for reCAPTCHA API 2.0 (nocaptcha) + +MultiFile: + +- Added file-link2.inc and support for alternative program files display format + +Plagiarism-iThenticate: + +- Fixed non-reporting for reports with 0% match +- Fixed submission title link + +Proceedings: + +- Fixed download error if table name prefix used or acceptance type with no submissions + +Program: + +- DB: Added tables module_oc_program_booktemplates, module_oc_program_scdaccounts +- Added feature to generate an abstract book +- Added feature to generate a program book +- Removed extraneous code from program-at_a_glance.inc +- Fixed incorrect date display in case of time zone differential between MySQL and PHP +- Changed generation of session chair and discussant titles to program code instead of CSS for i18n and screen reader support +- Added session chair and discussant view assignments feature + +Payment: + +- Changed to use Braintree version 2 library +- Removed OC_payment_braintree_encryptionKey setting +- Added settings export/import support + +Sub. Payment: + +- Added settings export/import support + + +### OpenConf 6.20 ### + +- Added DB template.updated +- Changed DB template.body to default null +- Added use of CKEditor CDN, modifying how CKEditor plugin is used internally +- Added data/zip/ directory for staging ZIP files +- Added "default" topic for new installations + +Chair: + +- Added Presenting Authors email recipient group if submission form presenter field enabled +- Added export support for Excel 2007 (xlsx) format and cleaned up export code +- Added email template editor +- Changed email.php, splitting shared functionality into new email.inc and consolidating $*varAR into $OC_emailVarAR[] +- Changed settings export to include all templates, and import to only those for installed modules +- Added bulk (ZIP) download of author-uploaded files on list submissions and view files pages +- Fixed advanced configuration JavaScript to avoid Chrome notices +- Added review and comment fields variables to email Authors - All and Student recipient groups +- Fixed [:advocate-comment:] email variable name +- Changed recipient group ordering to natcasesort; $recipients array format changed +- Fixed missing advocate data when exporting submissions if advocate field selected but not Committee Notes +- Changed Scores page to display scores of 0 + +Committee Member: + +- Added bulk (ZIP) download of assigned submission files on member home page +- Fixed the display of review data to advocates + +Author: + +- Added logging of make submission, edit submission, and upload file events + +Custom Forms: + +- Added restriction on custom field IDs to end in a letter so as to avoid conflict with numbered author field names + +IEEE Copyright: + +- Added support for IEEE Prohibited Author List (PAL) online search via author export in requisite PAL format +- Updated test URL +- Added submission ID prefix setting (OC_IEEE_COPYRIGHT_idprefix) + +MultiFile: + +- Changed file-links.inc to include preview keycode in file view URL if present +- Changed file-links.inc to use new uploaded file directory structure when exporting proceedings/program +- Updated chair-email-recipient.inc to use new $OC_emailVarAR +- Added support for bulk file download + +Proceedings: + +- Changed download summary page to use new file export data structure + +Program: + +- Added Program - Contact Authors email recipient group +- Added author names to assigned submissions listing when editing a session +- Added conflict detection of names and associated email addresses across overlapping sessions when editing a session +- Added ability to view files when previewing program +- Changed At-a-Glance program permission to allow display if Full program is closed +- Renamed email.inc to chair-email-recipient.inc +- Changed download summary page to use new file export data structure + +Rebuttal: + +- Renamed email.inc to chair-email-recipient.inc +- Updated chair-email-recipient.inc to use new $OC_emailVarAR + + +### OpenConf 6.10 ### + +- Added hooks: author-status, committee-profile-preinc +- Added showauthor review form field attribute to designate fields that may be shown to author (i.e., check status page, acceptance emails) +- Added linking of URL fields displayed in include-forms.inc:showFieldSet() + +Chair: + +- Changed review listing Recommendation legend to display full option text if no colon present +- Added [:review-fields:] variable to author acceptance emails to include all review fields with showauthor attribute set (Pro Edition) +- Changed presenter field check in email.php to support Custom Forms + +Committee Member: + +- Changed committee sign up and update code to latest field definition and validation format +- Fixed incorrect processing of OC_hideRevFields +- Fixed review form phantom sessions field when hidden + +Author: + +- Added all review fields with showauthor attribute set on Check Status page +- Fixed submissions with no topics selected if field is not required + +Custom Forms: + +- Added Show Author attribute to review form field options (excludes sessions field) +- Changed variable tracking custom form use to be type specific +- Added support for customization of committee profile form + +FileType: + +- Added file extension verification of MS Office 2007+ formats + +Proceedings: + +- Added (HTML) Proceedings Download feature + +Program: + +- Added current discussants and session chairs to program building pick lists +- Fixed incorrect back link and file URL on downloaded program session pages +- Changed presenter field check in settings.inc to support Custom Forms +- Changed mobile program XML data file to strip out Unicode control characters + + +### OpenConf 6.01 ### + +- Security Fix + + +### OpenConf 6.00 ### + +- PHP 5.3.7+ now required --with-mcrypt --with-mysqli +- Changed MySQL API from mysql to mysqli +- Added Bosnian translation +- Updated all translations +- Renamed Custom Forms to Form Fields +- Deprecated Sub. Type module (use Custom Forms instead) +- Added modules Custom Forms, Payment, and Sub. Payment +- Added include.php functions: oc_strftime, ocsql_fetch_assoc, ocsql_fetch_array, ocsql_fetch_row, ocsql_insert_id, ocsql_num_rows, ocsql_affected_rows, ocsql_free_result, ocsql_data_seek, ocsql_close, ocsql_error, ocsql_errno +- Added database port to config.php with default of 3306 +- Added DB author.orcid, paperreviewer.score +- Changed DB reviewerid/advocateid to MEDIUMINT(6) for new installations, and paperreviewer.recommendation to TINYINT(3) +- Changed DB author.* varchar to 255 characters +- Added hooks: chair-signin, committee-signin, password-verify, author-submission-preinc, committee-review-preinc +- Changed deprecated preg_replace calls with /e to preg_replace_callback +- Fixed missing fclose() in include.php:oc_createDir() +- Fixed handling of double-quotes in checkbox and radio field option values +- Changed password storage hash, renamed include.php:hashPassword() to oc_password_hash(), and added oc_password_verify(), oc_password_needs_rehash() +- Changed include.php:newPassword() to oc_password_generate() +- Removed SALT_LENGTH constant +- Added new settings for words to use in English (US) locale for Author and Chair (OC_wordForAuthor, OC_wordForChair) +- Added output buffering around main content on home page +- Added field types to include-forms.inc: hidden, dropdown, picklist, email +- Added field options to include-forms.inc: maxchas, minchars, maxwords, minwords, maxselection, minselections, closeedit, longlabel, reviewer, advocate, width, height, placeholder, display +- Deprecated select field type in include-forms.inc (use dropdown or picklist) +- Added include-forms.inc: oc_validateField() +- Deprecated include-forms.inc: oc_checkField() and oc_checkAuthorField() +- Added openconf.js: oc_setupProcessingForm() and oc_processingForm() +- Deprecated openconf.js: oc_showProcessing() +- Added submission confirmation page notice setting (OC_subConfirmNotice), replacing hard-coded notice +- Deprecated make submission confirmation file link (OC_includeSubmissionUploadLink); now specify in OC_subConfirmNotice +- Deprecated submission form file field options (OC_includeSubmissionUploadField, OC_requireSubmissionUploadField, OC_paperFldNote); now set through Custom Forms and MultiFile modules, or directly via submission.inc +- Deprecated abstract length setting (OC_abstractLength); now set through Custom Forms module, or directly via submission.inc +- Removed separate student tracking, including config settings (OC_studentNote, OC_trackStudent); now set through Custom Forms module, or directly via submission.inc +- Removed non-editable submission fields settings (OC_subNonEditFields); now set through Custom Forms module or use closeedit field option +- Added min parameter to openconf.js:check(Word|Char)Num functions +- Changed oc_() and oc_n() to return empty string instead of .po header if string is empty +- Changed score calculation to be based on new paperreviewer.score column instead of recommendation +- Added shortcut links on manual assignment pages to make additional and view assignments + +Chair: + +- Added settings export/import +- Changed Chair home page to consolidate reports +- Changed min number of displayed topics fields to 10 +- Removed $accOptions from chair/index.php +- Renamed list_author_topics.php to list_topics_pcount.php +- Added login session fixation prevention +- Added configuration page field to set starting submission ID if no submissions in system +- Changed email variable advocate-comment to advocate-comments +- Changed Chair interface to be all English + +Committee Member: + +- Added login session fixation prevention +- Changed show_abstract.php to use oc_showFieldSet() and skip fields with empty values +- Updated abstract page reference sites +- Added config option whether to display reference service links on abstract page (OC_includeReferenceSearchLinks) +- Changed review form to use fieldsets +- Changed review form to use include-forms.inc field validation +- Changed review form required fields to be required for form submission, not just for marking review as complete +- Changed sign up keycodes to accept a comma-delimited list of codes + +Author: + +- Added new setting to restrict Edit Submission to accepted authors only (OC_editAcceptedOnly) +- Fixed update of Contact Author field options when deleting authors in Edit Submission +- Changed submission form to better support single author events +- Changed student field to normal field (NOTE: if upgrading, student field note must be manually updated) +- Dropped otherauthors field support + +Multiple Modules: + +- Added settings import/export +- Changed deprecated preg_replace calls with /e to preg_replace_callback +- Changed password verification to use oc_password_verify() +- Added support for custom Author/Chair name + +Adv. Assign: + +- Added optional display of submissions and reviewers by topic to advocates (OC_ADV_ASSIGN_viewtopics) + +Bidding: + +- Changed Chair home page links + +Discussion: + +- Fixed dates for non-English display + +FileType: + +- Changed to be installed and activated upon OpenConf installation +- Added alternative file extensions for jpg and mpg + +IEEE Copyright: + +- Updated test URL + +MultiFile: + +- Added note to Format(s) header on config page +- Changed links in file-links.inc to include file path for program download + +Program: + +- Added sub-pages to full program preview +- Added Program Download feature +- Fixed dates for non-English display +- Changed mobile settings geolocation API to Google +- Changed automatic room sort order to also handle numberic values +- Changed sort order of entries in Assign Accepted Submissions list on session edit page +- Updated mobile program app to latest HTML5 standards +- Fixed chair email preview for discussant and session chairs +- Added presentation title in chair email to discussant recipient group + +#OC# Ala Viva #OC# ΦΚΨ #OC# diff --git a/docs/INSTALL.txt b/docs/INSTALL.txt new file mode 100644 index 0000000..f8e327c --- /dev/null +++ b/docs/INSTALL.txt @@ -0,0 +1,68 @@ +============== + REQUIREMENTS +============== + +- HTTP Server* (TLS/SSL highly recommended) +- PHP 5.6+ with modules: curl, intl, json, mbstring, mysqli, openssl, xml, zip +- MySQL 5.6+ or MariaDB 10+ + +* OpenConf was developed using Apache and makes use of .htaccess files to help + protect sensitive files and directories. Make sure to update your HTTP server + configuration to support .htaccess files or change the config accordingly. + + +========= + INSTALL +========= + +1. Download the OpenConf software archive and extract (unzip) files + into the Web server document root directory, maintaining the + OpenConf sub-directory structure. + +2. Ensure Web server can create or write to: + openconf/config.php + openconf/data/ (and sub-directories) + +3. Browse to https://[HOST]/openconf/ and follow web instructions. + +See https://www.OpenConf.com/support/ for additional documentation. + + +========= + UPGRADE +========= + +1. Backup your current OpenConf database and files. + +2. Extract (unzip) new OpenConf archive over top of current directory; + your settings and custom modules will remain intact, however code + customizations will be overwritten. + +3. Sign in as Chair and browse to: + https://[HOST]/openconf/chair/upgrade.php + Follow the instructions provided. + + +============================ + ETCETERA / TROUBLESHOOTING +============================ + +- For email issues, see our troubleshooting guide: + https://www.OpenConf.com/documentation/email.php#troubleshooting + +- OpenConf does not limit the size of files that may be uploaded; + PHP however does. You will need to modify PHP's max file and form upload + settings if you want to support larger files being uploaded; do not forget + to restart the HTTP server when you update PHP settings. + +- If you are uncomfortable having a file (config.php) with the database + password inside the Web document space, you can move it elsewhere + and simply modify the OCC_CONFIG_FILE define in include.php. + +- In order to use OpenConf's multilingual capability, PHP must be compiled + with gettext, and the system have the proper locale(s) installed. + See lib/locale/locale.inc for appropriate locales. + +- If you are running multiple instances of OpenConf, you must ensure the + value of OCC_SESSION_VAR_NAME in config.php is different for each in order + to prevent cross-instance access. diff --git a/docs/LICENSE b/docs/LICENSE new file mode 100644 index 0000000..93ce5e2 --- /dev/null +++ b/docs/LICENSE @@ -0,0 +1,47 @@ +This license is a legal Agreement between you and Zakon Group LLC for use of the OpenConf Software (the "Software"). By downloading or installing OpenConf or any OpenConf modules you agree to be bound by the terms and conditions of this license. Zakon Group LLC reserves the right to alter this agreement at any time, for any reason, without notice. + +PERMITTED USE + +- Community License: The Community License permits installation of the Software on your own web site and if no payment is made or received in connection with the Software or related services. No support is included. If you need assistance from Zakon Group LLC or a third party to install, host, customize, or administer the Software, or you wish to provide such services to others, an OpenConf License must first be purchased for each installation. + +- Plus and Professional Licenses: Upon payment of the license fee to and issuance of the license by Zakon Group LLC, a single installation of the licensed Software with embedded license key may be made by the licensee or its designated agent. One license grants the right to perform one installation of the Software to be used for the entity the license was purchased for. Each additional installation of the Software requires an additional purchased license. An entity is defined as constituting a single submission cycle such as for one event date or journal volume. Recurring entities, such as annual events or journals, or ones with parallel submissions, such as separately-managed event tracks or journal volumes, require a license for each instance. Components of the Plus and Professional Edition Software may not be copied to other installations, whether they are licensed or not. New submissions may not be accepted after a license has expired. + +RESTRICTIONS + +Unless you have been granted prior, written consent from Zakon Group LLC, you may not: + +- Sublicense, resell, rent, lease, distribute, market, commercialize or otherwise transfer rights or usage to: (a) the Software, (b) any modified version or derivative work of the Software, (c) any software, either modified or not, licensed under an OpenConf License, for any purpose, or (d) any translation of the Software or its components; + +- Remove or alter any copyright, trademark or proprietary notice in the Software; + +- Change, disable, or circumvent any part of the Software marked as not to be modified. + +DISPLAY OF LOGOS AND TRADEMARKS + +By using the Software, you grant Zakon Group LLC the non-exclusive right to display your organization's logos, trademarks, and trade names so that Zakon Group LLC may refer to your organization as a user of the Software should Zakon Group LLC desire, such as on Zakon Group LLC and OpenConf websites and marketing materials. + +EXPORT CONTROL + +The export and re-export of Zakon Group software products are controlled by the United States Export Administration Regulations and such software may not be exported or re-exported to Cuba, Iran, North Korea, Sudan, Syria, or any country to which the United States embargoes goods. In addition, Zakon Group software may not be distributed to persons on the Table of Denial Orders, the Entity List, or the List of Specially Designated Nationals. By downloading or using a Zakon Group software product you are certifying that you are in compliance with these policies. + +INDEMNITY + +You agree to indemnify and hold harmless Zakon Group LLC for any third-party claims, actions or suits, as well as any related expenses, liabilities, damages, settlements or fees arising from your use or misuse of the Software, or a violation of any terms of this license. + +TERMINATION + +Zakon Group LLC may at its discretion terminate this Agreement or access to the Software licensed under this Agreement immediately and without notice if you fail to comply with any term or condition of the License or this Agreement. Upon such termination, you must immediately cease using the Software, and destroy all complete and partial copies of the Software. + +DISCLAIMER OF WARRANTY + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. FURTHER, ZAKON GROUP LLC DOES NOT WARRANT THAT THE SOFTWARE OR ANY RELATED SERVICE WILL ALWAYS BE AVAILABLE. + +LIMITATIONS OF LIABILITY + +YOU ASSUME ALL RISK ASSOCIATED WITH THE INSTALLATION AND USE OF THE SOFTWARE. IN NO EVENT SHALL ZAKON GROUP LLC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +GENERAL + +If you use the Software from outside the United States, you are entirely responsible for compliance with applicable local laws, including but not limited to the export and import regulations of other countries. This Agreement will be governed by New Hampshire law and controlling United States federal law, without regard to the choice or conflicts of law provisions of any jurisdiction. The parties agree that the United Nations Convention on Contracts for the International Sale of Goods (1980) is specifically excluded from application to this Agreement. You shall bring all disputes, actions, claims, or causes of action related to these terms or in connection with this Software only in the federal and state courts located in Carroll County, New Hampshire. If any provision of this Agreement is held by a court of competent jurisdiction to be contrary to law, then such provision(s) shall be construed, as nearly as possible, to reflect the intentions of the parties, with all other provisions remaining in full force and effect. The failure of Zakon Group LLC to enforce any right or provision in these terms shall not constitute a waiver of such right or provision unless acknowledged and agreed to by Zakon Group LLC in writing. + +Revised on: 20 November 2019 diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.php b/docs/index.php new file mode 100644 index 0000000..e69de29 diff --git a/footer.php b/footer.php new file mode 100644 index 0000000..308b1d0 --- /dev/null +++ b/footer.php @@ -0,0 +1,2 @@ + + diff --git a/header.php b/header.php new file mode 100644 index 0000000..a08a9a0 --- /dev/null +++ b/header.php @@ -0,0 +1,43 @@ + +> + + +<?php echo (isset($GLOBALS['OC_configAR']['OC_confName']) ? (safeHTMLstr($GLOBALS['OC_configAR']['OC_confName']) . ' - ') : '') . safeHTMLstr(sprintf(oc_('%s Abstract Submission, Peer Review, and Event Management System'), 'OpenConf')); ?> + + +'."\n"; +} +foreach ($GLOBALS['OC_cssAR'] as $file) { + echo ''."\n"; +} +foreach ($GLOBALS['OC_jsAR'] as $file) { + echo ''."\n"; +} +if (isset($GLOBALS['OC_configAR']['OC_privacy_banner_options']) && preg_match('/"display":"?1/', $GLOBALS['OC_configAR']['OC_privacy_banner_options'])) { + require_once OCC_PLUGINS_DIR . 'privacy_banner.inc'; +} +echo implode("\n", $GLOBALS['OC_extraHeaderAR']); +?> + + + +
    '; +} else { + $confHeader = safeHTMLstr((isset($GLOBALS['OC_configAR']['OC_confNameFull']) ? $GLOBALS['OC_configAR']['OC_confNameFull'] : $GLOBALS['OC_confNameFull'])); +} +if (isset($GLOBALS['OC_configAR']['OC_confURL']) && !empty($GLOBALS['OC_configAR']['OC_confURL'])) { + echo '' . $confHeader . ''; +} else { + echo $confHeader; +} +?>
    diff --git a/images/calendar.png b/images/calendar.png new file mode 100644 index 0000000..a8973bd Binary files /dev/null and b/images/calendar.png differ diff --git a/images/circlex.png b/images/circlex.png new file mode 100644 index 0000000..984bb16 Binary files /dev/null and b/images/circlex.png differ diff --git a/images/document-sm.gif b/images/document-sm.gif new file mode 100644 index 0000000..0062991 Binary files /dev/null and b/images/document-sm.gif differ diff --git a/images/document.gif b/images/document.gif new file mode 100644 index 0000000..da8c847 Binary files /dev/null and b/images/document.gif differ diff --git a/images/documentless-sm.gif b/images/documentless-sm.gif new file mode 100644 index 0000000..0acd81c Binary files /dev/null and b/images/documentless-sm.gif differ diff --git a/images/documentmulti-sm.gif b/images/documentmulti-sm.gif new file mode 100644 index 0000000..3c9b25a Binary files /dev/null and b/images/documentmulti-sm.gif differ diff --git a/images/facebook.png b/images/facebook.png new file mode 100644 index 0000000..d7b84ba Binary files /dev/null and b/images/facebook.png differ diff --git a/images/globe.png b/images/globe.png new file mode 100644 index 0000000..6243963 Binary files /dev/null and b/images/globe.png differ diff --git a/images/index.html b/images/index.html new file mode 100644 index 0000000..e69de29 diff --git a/images/index.php b/images/index.php new file mode 100644 index 0000000..e69de29 diff --git a/images/linkedin.png b/images/linkedin.png new file mode 100644 index 0000000..69f7db4 Binary files /dev/null and b/images/linkedin.png differ diff --git a/images/social-icons b/images/social-icons new file mode 100644 index 0000000..d67378e --- /dev/null +++ b/images/social-icons @@ -0,0 +1 @@ +Social icons by http://paulrobertlloyd.com/2009/06/social_media_icons/, CC BY-SA 2 \ No newline at end of file diff --git a/images/sort.gif b/images/sort.gif new file mode 100644 index 0000000..1bae5f0 Binary files /dev/null and b/images/sort.gif differ diff --git a/images/sortasc.gif b/images/sortasc.gif new file mode 100644 index 0000000..c035e86 Binary files /dev/null and b/images/sortasc.gif differ diff --git a/images/sortdesc.gif b/images/sortdesc.gif new file mode 100644 index 0000000..1bae5f0 Binary files /dev/null and b/images/sortdesc.gif differ diff --git a/images/twitter.png b/images/twitter.png new file mode 100644 index 0000000..c569222 Binary files /dev/null and b/images/twitter.png differ diff --git a/images/url.png b/images/url.png new file mode 100644 index 0000000..42e1e67 Binary files /dev/null and b/images/url.png differ diff --git a/images/web.png b/images/web.png new file mode 100644 index 0000000..42e1e67 Binary files /dev/null and b/images/web.png differ diff --git a/include-download.inc b/include-download.inc new file mode 100644 index 0000000..c57084e --- /dev/null +++ b/include-download.inc @@ -0,0 +1,229 @@ +' . oc_('We are generating a ZIP archive of the files. Please do not close this page. Once the ZIP archive is created, you will be prompted to save the file.') . '

    '; + print '

    '; +} + +// Action to execute +if (!isset($_GET['daction']) || empty($_GET['daction'])) { + // redirect when starting out in case of double-click and so user knows what is going on + printHeader($hdr, $hdrfn); + displayZipNotice(10, 100); +print ' + +'; + printFooter(); + flush(); + print ' + +'; + exit; +} elseif ($_GET['daction'] == 'download') { + // send out archive + header("Content-Type: application/zip"); + header("Content-Disposition: attachment; filename=files-" . $_GET['t'] . ".zip"); + header("Content-Length: " . filesize($zipFileName)); + header("Cache-control: private"); + header("Pragma: public"); // IE issue work around + ob_end_flush(); + readfile($zipFileName) or err('Unable to read ZIP file', $hdr, $hdrfn); + // delete archive + unlink($zipFileName); + // clean up old ZIP files still around + if ($dh = opendir($zipDir)) { + $fourHoursAgo = time() - (60 * 60 * 4); + while (($file = readdir($dh)) !== false) { + if (preg_match("/\.zip$/", $file) && ($mtime = filemtime($zipDir . $file)) && ($mtime < $fourHoursAgo)) { + unlink($zipDir . $file); + } + } + } + exit; +} elseif ($_GET['daction'] == 'complete') { + printHeader($hdr, $hdrfn); + if (is_file($zipFileName) && (filesize($zipFileName) > 0)) { + displayZipNotice(1, 1); + print '

    ' . oc_('The ZIP archive has been created, and the download should begin shortly.') . '

    '; + if (isset($_GET['skipped']) && ($_GET['skipped'] == 1)) { + print '

    ' . oc_('One or more files were not found or too large to include in the ZIP archive.') . '

    '; + } + print ' + +'; + printFooter(); + flush(); + print ' + +'; + } else { + warn('Failed creating ZIP archive (4)'); + } + exit; +} else { // daction == start + + // let user know what's going on + printHeader($hdr, $hdrfn); + + // Retrieve assigned submissions + $r = ocsql_query($q) or err('Unable to retrieve file data'); + $fileAR = array(); + while ($l = ocsql_fetch_assoc($r)) { + if (!empty($l[$formatDBFldName])) { + $fileAR[$l['paperid']] = $l['paperid'] . '.' . $l[$formatDBFldName]; + } + } + ocsql_free_result($r); // free up memory as ZIP could use up a bit + $fileARcount = count($fileAR); + if ($fileARcount == 0) { + warn(oc_('There are no files available')); + } + + // Open ZIP archive + $zip = new ZipArchive(); + $res = $zip->open($zipFileName, (($_GET['daction']=='start') ? (ZipArchive::OVERWRITE | ZipArchive::CREATE) : ZipArchive::CREATE)) or err('Failed creating ZIP archive (1)'); + if (($zip->numFiles > 0) && preg_match("/^\d+$/", $zip->getArchiveComment())) { + $stoppedAt = $zip->getArchiveComment(); + } else { + $stoppedAt = 0; + } + // display progress + displayZipNotice((($zip->numFiles > 0) ? $zip->numFiles : ceil($fileARcount * 0.1)), $fileARcount); + // add files + $files = 0; // count of files added per zip->open + if (isset($_GET['skipped']) && ($_GET['skipped'] == 1)) { // track whether we had to skip files + $skippedFiles = true; + } else { + $skippedFiles = false; + } + foreach ($fileAR as $pid => $fname) { + // skip previously processed files + if ($pid <= $stoppedAt) { continue; } + + // reload page in case limit(s) being reached + if ( + oc_checkTimeout() // processing time reaching timeout + || ($files++ >= $zipFileCount) // too many files open + || ( ($fileSize = oc_fileSize($dir . $fname)) === false ) // file does not exist + || ((memory_get_usage() + ( 2 * $fileSize )) > $memoryLimit) // memory usage will be over limit if file added - 2x factor used (w/memoryLimit @ 95%) + ) { + if ($files == 1) { + $zip->setArchiveComment($pid); // skip file because it's too large + $skippedFiles = true; + } else { + $zip->setArchiveComment($pid - 1); // record 1 less than current file ID so it starts w/current file again + } + $zip->close(); + print ' + + '; + printFooter(); + flush(); + print ' + + '; + exit; + } + + // add file + if (oc_hookSet('zip_add_file')) { + call_user_func($GLOBALS['OC_hooksAR']['zip_add_file'][0], $zip, $dir . $fname, $savePath . $fname); + } elseif (is_readable($dir . $fname)) { + if ( ! $zip->addFile($dir . $fname, $savePath . $fname) ) { + $zcontent = ocGetFile($dir . $fname) or err('Failed creating ZIP archive (3a)'); + $zip->addFromString($savePath . $fname, $zcontent) or err('Failed creating ZIP archive (3b)'); + } + } + } + $zip->close(); + + // done - redirect user + print ' + + '; + + printFooter(); + flush(); + + print ' + + '; +} + +exit; + +?> diff --git a/include-forms.inc b/include-forms.inc new file mode 100644 index 0000000..571de4d --- /dev/null +++ b/include-forms.inc @@ -0,0 +1,847 @@ +'; +$oc_defaultFieldWidth = '60'; +$oc_defaultFieldHeight = '5'; + +$oc_jsValidateEvent = 'change'; // event type to use for triggering JavaScript char or word number validation -- "change" used instead of "blur" to prevent Safari alert() loop + +$formDisplayAR = array( + 'sameline' => '   ', + 'newline' => '
    ' +); + +if (!isset($GLOBALS['oc_authorNum'])) { + $GLOBALS['oc_authorNum'] = $GLOBALS['OC_configAR']['OC_authorsMax']; +} + +function oc_fieldEnabled($fieldID, &$fieldsAR) { + if (!isset($fieldsAR[$fieldID]['enabled']) || $fieldsAR[$fieldID]['enabled']) { + return(TRUE); + } else { + return(FALSE); + } +} + +function oc_genField(&$fid, &$fAR, &$fVals, $fidxtra='') { + $usefid = $fid . $fidxtra; + + $field = ''; + + $field .= '
    '; + + if (isset($fAR['enabled']) && !$fAR['enabled']) { + $disabled = 'disabled '; + } else { + $disabled = ''; + } + + if (isset($fAR['required']) && $fAR['required']) { + $required = $GLOBALS['OC_configAR']['OC_requiredField']; + } else { + $required = ''; + } + + if (!empty($fAR['note']) && ($fAR['type'] != 'plain') && ($fAR['type'] != 'hidden')) { + $fieldnote = '
    ' . $fAR['note'] . '
    '; + } else { + $fieldnote = ''; + } + + if (isset($fAR['longlabel']) && $fAR['longlabel']) { + $longlabel = $fieldnote . ''; + $longlabelclass = ' class="plain"'; + $fieldnote = ''; + } else { + $longlabel = ''; + $longlabelclass = ''; + } + + switch ($fAR['type']) { + + case 'plain': + $field .= '' . $fAR['values']; + break; + + case 'hidden': + $field .= ''; + break; + + case 'text': + if (isset($fAR['width'])) { + $width = $fAR['width']; + } else { + $width = $GLOBALS['oc_defaultFieldWidth']; + } + if (isset($fAR['maxchars'])) { + $maxchars = $fAR['maxchars']; + } else { + $maxchars = '255'; // should match default used in DB VARCHAR fields + } + $field .= '' . $longlabel . ''; + if ( (isset($fAR['maxwords']) && ($fAR['maxwords'] > 0)) || (isset($fAR['minwords']) && ($fAR['minwords'] > 0)) ) { // word limit + $field .= ' + +'; + } + if ( ($maxchars > 0) || (isset($fAR['minchars']) && ($fAR['minchars'] > 0)) ) { // character limit + $field .= ' + +'; + } + break; + + case 'email': + $field .= '' . $longlabel . ''; + break; + + case 'textarea': + if (isset($fAR['height'])) { + $height = $fAR['height']; + } else { + $height = $GLOBALS['oc_defaultFieldHeight']; + } + $field .= '' . $longlabel . ''; + if (isset($fAR['maxwords'])) { + $maxwords = $fAR['maxwords']; + } else { + $maxwords = 0; + } + if ( ($maxwords > 0) || (isset($fAR['minwords']) && ($fAR['minwords'] > 0)) ) { // word limit + $field .= ' + +'; + } + if ( (isset($fAR['maxchars']) && ($fAR['maxchars'] > 0)) || (isset($fAR['minchars']) && ($fAR['minchars'] > 0)) ) { // character limit + $field .= ' + +'; + } + break; + + case 'dropdown': + $field .= '' . $longlabel . ''; + break; + + case 'picklist': + if (!isset($fAR['multiple']) || $fAR['multiple']) { // default to multiple for picklist + $multiple = true; + } else { + $multiple = false; + } + if ($multiple && isset($fVals[$usefid]) && !is_array($fVals[$usefid])) { + $vals = explode(',', $fVals[$usefid]); + } else { + $vals = varValue($usefid, $fVals); + } + $field .= '' . $longlabel . ''; + break; + + case 'radio': + if (isset($fAR['display']) && isset($GLOBALS['formDisplayAR'][$fAR['display']])) { + $delimiter = $GLOBALS['formDisplayAR'][$fAR['display']]; + } elseif (isset($fAR['delimiter'])) { + $delimiter = $fAR['delimiter']; + } else { + $delimiter = $GLOBALS['oc_defaultDelimiter']; + } + $field .= '' . $fAR['name'] . ':' . $required . '' . $longlabel . '
    '; + $field .= generateRadioOptions($usefid, $fAR['values'], varValue($usefid, $fVals), ((!isset($fAR['usekey']) || $fAR['usekey']) ? true : false), $disabled, $delimiter); + $field .= '
    '; + break; + + case 'checkbox': + if (isset($fAR['display']) && isset($GLOBALS['formDisplayAR'][$fAR['display']])) { + $delimiter = $GLOBALS['formDisplayAR'][$fAR['display']]; + } elseif (isset($fAR['delimiter'])) { + $delimiter = $fAR['delimiter']; + } else { + $delimiter = $GLOBALS['oc_defaultDelimiter']; + } + $field .= '' . $fAR['name'] . ':' . $required . '' . $longlabel . '
    '; + if (isset($fVals[$usefid])) { + if (!is_array($fVals[$usefid])) { + $vals = explode(',', $fVals[$usefid]); + } else { + $vals = $fVals[$usefid]; + } + } else { + $vals = array(); + } + $field .= generateCheckboxOptions($usefid, $fAR['values'], $vals, ((!isset($fAR['usekey']) || $fAR['usekey']) ? true : false), $disabled, $delimiter); + $field .= '
    '; + break; + + case 'password': + $field .= '' . $longlabel . ''; + break; + + case 'file': + $field .= '
    ' . $longlabel . '   ' . oc_('Format') . ':' . $required . ' '; + if (count($GLOBALS['extAR']) == 1) { // Only accept one format? + $field .= $GLOBALS['OC_formatAR'][$GLOBALS['extAR'][0]] . ' '; + } else { + $formatOptions = array(); + foreach ($GLOBALS['extAR'] as $formatVal) { + $formatOptions[$formatVal] = $GLOBALS['OC_formatAR'][$formatVal]; + } + $field .= ''; + } + break; + + default: + err('There is an error with field ID ' . $usefid); + } + + if (!empty($fieldnote)) { + $field .= $fieldnote; + } + + $field .= '
    '."\n"; + + return($field); + +} + +function oc_displayFields(&$fieldsAR, &$fVals=array()) { + foreach ($fieldsAR as $fieldID => $fieldAR) { + print '
    ' . oc_genField($fieldID, $fieldAR, $fVals) . '
    '; + } +} + +function oc_displayFieldSet(&$fsAR, &$fieldsAR, &$fVals=array()) { + // Include field validation translation strings + print ' + +'; + + // Iterate through fieldsets and fields + foreach ($fsAR as $fieldset => $fieldsetAR) { + // skip fieldset if no fields included -- e.g., review fields removed because of sub type + $fcount = 0; + foreach ($fieldsetAR['fields'] as $f) { + if (isset($fieldsAR[$f])) { + $fcount++; + } + } + if ($fcount == 0) { + continue; + } + + if ((count($fieldsetAR['fields']) == 1) && ($fieldsAR[$fieldsetAR['fields'][0]]['type'] == 'hidden')) { // handle special case of single hidden field + print oc_genField($fieldsetAR['fields'][0], $fieldsAR[$fieldsetAR['fields'][0]], $fVals); + continue; + } + + print '
    ' . safeHTMLstr($fieldsetAR['fieldset']) . ''; + if (!empty($fieldsetAR['note'])) { + print '
    ' . $fieldsetAR['note'] . '
    '; + } + + if ($fieldset == 'fs_authors') { + // setup dynamic add authors + if (($GLOBALS['oc_authorNum'] == 1) && ($GLOBALS['OC_configAR']['OC_authorsMax'] == 1)) { + $singleAuthor = true; + } else { + $singleAuthor = false; + $blankAR = array(); + $authorFields = '' . oc_('Author') . ' [:authornum:]'; + foreach ($fieldsetAR['fields'] as $fieldID) { + if (!isset($fieldsAR[$fieldID])) { continue; } + $authorFields .= oc_genField($fieldID, $fieldsAR[$fieldID], $blankAR, '[:authornum:]'); + } + if (preg_match("/edit\.p/", $_SERVER['PHP_SELF'])) { + //T: Single quotes (') must be written as \\' for translation of string "X = Delete Author ..." + $authorFields .= '
    ?X+
    '; + } + print ' + +'; + } + + // display author fieldsets + print '
    '; + for ($i=1; $i<=$GLOBALS['oc_authorNum']; $i++) { + print '
    ' . ($singleAuthor ? '' : ('' . oc_('Author') . ' ' . $i . '')); + foreach ($fieldsetAR['fields'] as $fieldID) { + if (!isset($fieldsAR[$fieldID])) { continue; } + print oc_genField($fieldID, $fieldsAR[$fieldID], $fVals, $i); + } + if (preg_match("/edit\.p/", $_SERVER['PHP_SELF']) && !$singleAuthor) { + //T: Single quotes (') must be written as \\' for translation of string "X = Delete Author ..." + print '
    ?X+
    '; + } + print '
    '; + } + + // display extra author link + if ($i <= $GLOBALS['OC_configAR']['OC_authorsMax']) { + print ' + + +'; + } + print '
    '; + } else { // not authors fieldset + foreach ($fieldsetAR['fields'] as $fieldID) { + if (!isset($fieldsAR[$fieldID])) { continue; } + print oc_genField($fieldID, $fieldsAR[$fieldID], $fVals); + } + } + print '
    '."\n"; + } +} + +function oc_getFieldValue(&$fieldsAR, &$fVals, $fieldID, $valID='', $charLimit=0, $prefixMultiValues=true) { + if (empty($valID)) { + $valID = $fieldID; + } + + if (!isset($fVals[$valID])) { + return(''); + } else { + $retval = ''; // return value + if (isset($fieldsAR[$fieldID]) + && ( + ($fieldsAR[$fieldID]['type'] == 'checkbox') + || ($fieldsAR[$fieldID]['type'] == 'picklist') + ) + && !is_array($fVals[$valID]) + && ($fieldID != 'consent') // skip consent in case it has a comma in text as it is set for usekey:false + ) { + $vals = explode(',', $fVals[$valID]); + } else { + $vals = $fVals[$valID]; + } + if (is_array($vals)) { + if (count($vals) == 1) { + if (is_array($fieldsAR[$fieldID]['values']) && (!isset($fieldsAR[$fieldID]['usekey']) || $fieldsAR[$fieldID]['usekey'])) { + $retval = $fieldsAR[$fieldID]['values'][$vals[0]]; + } else { + $retval = $vals[0]; + } + } else { + if ($prefixMultiValues) { + $fret = "\n"; + $prefix = ' - '; + } else { + $fret = ''; + $prefix = ''; + } + foreach ($vals as $f) { + if (is_array($fieldsAR[$fieldID]['values']) && (!isset($fieldsAR[$fieldID]['usekey']) || $fieldsAR[$fieldID]['usekey'])) { + $fret .= $prefix . $fieldsAR[$fieldID]['values'][$f] . "\n"; + } else { + $fret .= $prefix . $f . "\n"; + } + } + $retval = rtrim($fret, "\n"); + } + } elseif (isset($fieldsAR[$fieldID]['values']) && is_array($fieldsAR[$fieldID]['values']) + && (!isset($fieldsAR[$fieldID]['usekey']) || $fieldsAR[$fieldID]['usekey']) + && ($vals != '') + && isset($fieldsAR[$fieldID]['values'][$vals]) + ) { + $retval = $fieldsAR[$fieldID]['values'][$vals]; + } else { + $retval = varValue($valID, $fVals); + } + + if (($charLimit > 0) && (oc_strlen($retval) > $charLimit)) { + return(utf8_encode(substr(utf8_decode($retval), 0, $charLimit))); + } else { + return($retval); + } + } +} + +function oc_stripHREF($s) { + $from = array( + '/]+>/', + '/<\/a>/' + ); + $to = array( + '', + '' + ); + return(preg_replace($from, $to, $s)); +} + +function oc_genFieldMessage(&$fsAR, &$fieldsAR, &$fVals=array()) { + $fmsg = ''; + foreach ($fsAR as $fieldset => $fieldsetAR) { + if ($fieldset == 'fs_authors') { + for ($i=1; $i<=$GLOBALS['oc_authorNum']; $i++) { + if (empty($fVals['name_last' . $i])) { continue; } + $fmsg .= oc_('Author') . ' ' . $i . ":\n"; + foreach ($fieldsetAR['fields'] as $fieldID) { + if (!oc_fieldEnabled($fieldID, $fieldsAR)) { continue; } + $fmsg .= ' ' . $fieldsAR[$fieldID]['short'] . ": " . oc_stripHREF(oc_getFieldValue($fieldsAR, $fVals, $fieldID, $fieldID . $i)) . "\n"; + } + $fmsg .= "\n\n"; + } + } else { + foreach ($fieldsetAR['fields'] as $fieldID) { + if (preg_match("/^password/i", $fieldID) + || ($fieldID == 'file') + || empty($fieldsAR[$fieldID]['name']) + || (!oc_fieldEnabled($fieldID, $fieldsAR)) + ) { + continue; + } + $fmsg .= $fieldsAR[$fieldID]['short'] . ': ' . oc_stripHREF(oc_getFieldValue($fieldsAR, $fVals, $fieldID)) . "\n\n"; + } + } + } + return($fmsg); +} + +function oc_showFieldSet(&$fsAR, &$fieldsAR, &$fVals, $blind=false, $committee=false, $references=false) { + foreach ($fsAR as $fieldset => $fieldsetAR) { + if (count($fieldsetAR['fields']) == 0) { continue; } // skip fieldset if no fields included + if (preg_match("/^fs_passwords$/i", $fieldset)) { continue; } // skip password fs + if ($fieldset == 'fs_authors') { // display author fields + if (!$blind) { + for ($i=1; $i<=$GLOBALS['oc_authorNum']; $i++) { + if (!isset($fVals['name_last' . $i])) { continue; } + print '' . oc_('Author') . ' ' . $i . ':'; + if ($references) { + print '[ CiteSeer | Google Scholar | ScienceDirect ]

    '; + } + print ''; + foreach ($fieldsetAR['fields'] as $fieldID) { + if (!isset($fieldsAR[$fieldID]) || preg_match("/^password/", $fieldID) || ($committee && empty($fVals[$fieldID.$i]))) { continue; } + if ($committee && isset($_SESSION[OCC_SESSION_VAR_NAME]['acpc']) && preg_match("/\/review\//", $_SERVER['PHP_SELF'])) { + if ( + (($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] == "T") && (!isset($fieldsAR[$fieldID]['advocate']) || !$fieldsAR[$fieldID]['advocate'])) + || + (($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] != "T") && (!isset($fieldsAR[$fieldID]['reviewer']) || !$fieldsAR[$fieldID]['reviewer'])) + ) { + continue; + } + } + print '\n"; + } + print "
    ' . safeHTMLstr(($committee ? oc_($fieldsAR[$fieldID]['short']) : $fieldsAR[$fieldID]['short'])) . ':'; + $fieldVal = oc_getFieldValue($fieldsAR, $fVals, $fieldID, $fieldID . $i); + if (($fieldID == 'email') && validEmail($fieldVal)) { // email + print '' . safeHTMLstr($fieldVal) . ''; + } elseif (preg_match("/^https?\:\/\//", $fieldVal) && !preg_match("/[\r\n]/", $fieldVal)) { // url + print '' . safeHTMLstr($fieldVal) . ''; + } else { // other + print nl2br(safeHTMLstr(oc_getFieldValue($fieldsAR, $fVals, $fieldID, $fieldID . $i))); + } + print "
    \n"; + } + } + } else { // not authors fieldset + foreach ($fieldsetAR['fields'] as $fieldID) { + if (!isset($fieldsAR[$fieldID]) || preg_match("/^password/", $fieldID) || ($committee && empty($fVals[$fieldID]))) { continue; } + if ($committee && isset($_SESSION[OCC_SESSION_VAR_NAME]['acpc']) && preg_match("/\/review\//", $_SERVER['PHP_SELF'])) { + if ( + (($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] == "T") && (!isset($fieldsAR[$fieldID]['advocate']) || !$fieldsAR[$fieldID]['advocate'])) + || + (($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] != "T") && (!isset($fieldsAR[$fieldID]['reviewer']) || !$fieldsAR[$fieldID]['reviewer'])) + ) { + continue; + } + } + if (preg_match("/^(?:file|format)/", $fieldID)) { continue; } // skip file/format fields + print '' . safeHTMLstr(($committee ? oc_($fieldsAR[$fieldID]['short']) : $fieldsAR[$fieldID]['short'])) . ':' . nl2br(safeHTMLstr(trim(oc_getFieldValue($fieldsAR, $fVals, $fieldID)))); + if (($fieldID == 'title') && $references) { + print '     [ CiteSeer | Google Scholar | ScienceDirect ]'; + } + print "\n"; + } + } + } +} + +function oc_limitString($min, $max, $required=false) { + $limit = ''; + if ($min > 0) { + $limit = $min; + } elseif ($required) { + $limit = 1; + } else { + $limit = 0; + } + if ($max > 0) { + if (empty($limit) || ($min == $max)) { + $limit = $max; + } else { + $limit .= '-' . $max; + } + } else { + $limit .= '+'; + } + return($limit); +} + +function oc_validateField($fieldID, &$fieldsAR, &$saveFieldAR, &$err, $authorID=0, $requiredOverride=false) { + if (!isset($fieldsAR[$fieldID])) { + return(false); // field not defined + } + + if (oc_fieldEnabled($fieldID, $fieldsAR) + && (!isset($fieldsAR[$fieldID]['donotvalidate']) || !$fieldsAR[$fieldID]['donotvalidate']) + ) { + // Author field? Add author ID + if ($authorID > 0) { + $postFieldID = $fieldID . $authorID; + } else { + $postFieldID = $fieldID; + } + // Validate if field is set and has a value + if (isset($_POST[$postFieldID]) && ((is_array($_POST[$postFieldID]) && (count($_POST[$postFieldID]) > 0)) || ($_POST[$postFieldID] != ''))) { + // Check fields with values array set + if (isset($fieldsAR[$fieldID]['values']) && is_array($fieldsAR[$fieldID]['values'])) { + $values = array(); + // handle both single and multi-selection fields + if (is_array($_POST[$postFieldID])) { + $checkAR = $_POST[$postFieldID]; + } else { + $checkAR = array($_POST[$postFieldID]); + } + // validate values + foreach ($checkAR as $val) { + if ( + ((!isset($fieldsAR[$fieldID]['usekey']) || $fieldsAR[$fieldID]['usekey']) && isset($fieldsAR[$fieldID]['values'][$val])) + || + (isset($fieldsAR[$fieldID]['usekey']) && ( ! $fieldsAR[$fieldID]['usekey']) && in_array($val, $fieldsAR[$fieldID]['values'])) // backward compatibilty for sub. type & old custom fields + ) { + $values[] = $val; + } else { + if ($authorID > 0) { + //T: %1$d = author number, %2$s = topic field short name; %3$s = invalid field value + $err .= '
  • ' . sprintf(oc_('Author %1$d %2$s field value is invalid: %3$s'), $authorID, $fieldsAR[$fieldID]['short'], safeHTMLstr($val)) . '
  • '; + } else { + //T: %1$s = topic field short name; %2$s = invalid field value + $err .= '
  • ' . sprintf(oc_('%1$s field value is invalid: %2$s'), $fieldsAR[$fieldID]['short'], safeHTMLstr($val)) . '
  • '; + } + } + } + + // check picklist and checkbox selection count + $count = count($values); + if (($fieldsAR[$fieldID]['type'] == 'picklist') || ($fieldsAR[$fieldID]['type'] == 'checkbox')) { + $min = (isset($fieldsAR[$fieldID]['minselections']) ? $fieldsAR[$fieldID]['minselections'] : 0); + $max = (isset($fieldsAR[$fieldID]['maxselections']) ? $fieldsAR[$fieldID]['maxselections'] : 0); + if ((($min > 0) && ($count < $min)) + || (($max > 0) && ($count > $max)) + ) { + $limit = oc_limitString($min, $max, varValue('required', $fieldsAR[$fieldID], false)); + if ($authorID > 0) { + // %1$d = author number, %2$s = field name, $3$d = number; %4$s = number or number range (e.g., 4 or 1-3) + $err .= '
  • ' . sprintf(oc_('Author %1$d %2$s field contains %3$d selection(s); limit is %4$s selection(s)'), $authorID, oc_($fieldsAR[$fieldID]['short']), $count, $limit) . '
  • '; + } else { + // %1$s = field name, $2$d = number; %3$s = number or number range (e.g., 1-3) + $err .= '
  • ' . sprintf(oc_('%1$s field contains %2$d selection(s); limit is %3$s selection(s)'), oc_($fieldsAR[$fieldID]['short']), $count, $limit) . '
  • '; + } + } + } + // store value(s) + if (empty($limit) && ($count > 0)) { + $saveFieldAR[$fieldID] = "'" . safeSQLstr(implode(',', $values)) . "'"; + } else { + $saveFieldAR[$fieldID] = "NULL"; + } + + } else { // regular field w/no values + $wlimit = ''; + $climit = ''; + // Check text and textarea input lengths + if (($fieldsAR[$fieldID]['type'] == 'text') || ($fieldsAR[$fieldID]['type'] == 'textarea')) { + // check words + $min = (isset($fieldsAR[$fieldID]['minwords']) ? + $fieldsAR[$fieldID]['minwords'] + : + ((isset($fieldsAR[$fieldID]['required']) && $fieldsAR[$fieldID]['required']) ? 1 : 0) + ); + $max = (isset($fieldsAR[$fieldID]['maxwords']) ? $fieldsAR[$fieldID]['maxwords'] : 0); + $count = count(explode(' ', preg_replace("/\s+/", " ", trim($_POST[$postFieldID])))); // We're not using str_word_count as numbers are not counted + if ((($min > 0) && ($count < $min)) + || (($max > 0) && ($count > $max)) + ) { + $wlimit = oc_limitString($min, $max, varValue('required', $fieldsAR[$fieldID], false)); + if ($authorID > 0) { + // %1$d = author number, %2$s = field name, $3$d = number; %4$s = number or number range (e.g., 4 or 1-3) + $err .= '
  • ' . sprintf(oc_('Author %1$d %2$s field contains %3$d words; limit is %4$s words.'), $authorID, oc_($fieldsAR[$fieldID]['short']), $count, $wlimit) . '
  • '; + } else { + // %1$s = field name, $2$d = number; %3$s = number or number range (e.g., 1-3) + $err .= '
  • ' . sprintf(oc_('%1$s field contains %2$d words; limit is %3$s words.'), oc_($fieldsAR[$fieldID]['short']), $count, $wlimit) . '
  • '; + } + } + + // check chars + $min = (isset($fieldsAR[$fieldID]['minchars']) ? + $fieldsAR[$fieldID]['minchars'] + : + ((isset($fieldsAR[$fieldID]['required']) && $fieldsAR[$fieldID]['required']) ? 1 : 0) + ); + $max = (isset($fieldsAR[$fieldID]['maxchars']) ? $fieldsAR[$fieldID]['maxchars'] : 0); + $count = oc_strlen(preg_replace("/\s+/", " ", trim($_POST[$postFieldID]))); + if ((($min > 0) && ($count < $min)) + || (($max > 0) && ($count > $max)) + ) { + $climit = oc_limitString($min, $max, varValue('required', $fieldsAR[$fieldID], false)); + if ($authorID > 0) { + // %1$d = author number, %2$s = field name, $3$d = number; %4$s = number or number range (e.g., 4 or 1-3) + $err .= '
  • ' . sprintf(oc_('Author %1$d %2$s field contains %3$d characters; limit is %4$s characters.'), $authorID, oc_($fieldsAR[$fieldID]['short']), $count, $climit) . '
  • '; + } else { + // %1$s = field name, $2$d = number; %3$s = number or number range (e.g., 1-3) + $err .= '
  • ' . sprintf(oc_('%1$s field contains %2$d characters; limit is %3$s characters.'), oc_($fieldsAR[$fieldID]['short']), $count, $climit) . '
  • '; + } + } + + } elseif (($fieldsAR[$fieldID]['type'] == 'email') && !validEmail($_POST[$postFieldID])) { + if ($authorID > 0) { + //T: %1$d = author number, %2$s = field name, %3$s = field value + $err .= '
  • ' . sprintf(oc_('Author %1$d %2$s field value is invalid: %3$s'), $authorID, oc_($fieldsAR[$fieldID]['short']), safeHTMLstr($_POST[$postFieldID])) . '
  • '; + } else { + //T: %1$s = field name, %2$s = field value + $err .= '
  • ' . sprintf(oc_('%1$s field value is invalid: %2$s'), oc_($fieldsAR[$fieldID]['short']), safeHTMLstr($_POST[$postFieldID])) . '
  • '; + } + } + + // store value + if (empty($wlimit) && empty($climit)) { + $saveFieldAR[$fieldID] = "'" . safeSQLstr(trim($_POST[$postFieldID])) . "'"; + } else { + $saveFieldAR[$fieldID] = "NULL"; + } + } + } + + if (!isset($saveFieldAR[$fieldID])) { + if ( isset($fieldsAR[$fieldID]['required']) && $fieldsAR[$fieldID]['required'] && ! $requiredOverride) { + if ($authorID > 0) { + //T: %1$d = author number, %2$s = field name + $err .= '
  • ' . sprintf(oc_('Author %1$d %2$s field is required'), $authorID, oc_($fieldsAR[$fieldID]['short'])) . '
  • '; + } else { + //T: %s = field name + $err .= '
  • ' . sprintf(oc_('%s field is required'), oc_($fieldsAR[$fieldID]['short'])) . '
  • '; + } + } else { + $saveFieldAR[$fieldID] = "NULL"; + } + } + } +} diff --git a/include-submissions.inc b/include-submissions.inc new file mode 100644 index 0000000..e1515b6 --- /dev/null +++ b/include-submissions.inc @@ -0,0 +1,220 @@ + 0) { + $assignNewID = true; + } else { + $assignNewID = false; + } + $q = "SELECT * FROM `" . OCC_TABLE_WITHDRAWN . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"; + $r = ocsql_query($q) or err('Unable to retrieve submission information'); + if (ocsql_num_rows($r) == 1) { + // paper + $l = ocsql_fetch_assoc($r); + if ($assignNewID) { + $l['papersql'] = preg_replace("/`paperid`='" . $paperid . "',/", "", $l['papersql']); + } + ocsql_query($l['papersql']) or err('Unable to restore paper'); + if ($assignNewID) { + $newID = ocsql_insert_id() or err('Unable to get new submission ID'); + } else { + $newid = null; + } + if (!empty($l['authorsql'])) { + if ($assignNewID) { + $l['authorsql'] = preg_replace("/\('" . $paperid . "',/", "('" . $newID . "',", $l['authorsql']); + } + ocsql_query($l['authorsql']) or err('Unable to restore ' . oc_strtolower(OCC_WORD_AUTHOR) . ' information'); + } + if (!empty($l['topicsql'])) { + if ($assignNewID) { + $l['topicsql'] = preg_replace("/\(" . $paperid . ",/", "('" . $newID . "',", $l['topicsql']); + } + ocsql_query($l['topicsql']) or err('Unable to restore topic information'); + } + ocsql_query("DELETE FROM `" . OCC_TABLE_WITHDRAWN . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'") or err('Unable to update withdrawn submission status'); + // restore + if (oc_hookSet('restore_paper')) { + foreach ($GLOBALS['OC_hooksAR']['restore_paper'] as $inc) { + include $inc; + } + } + + // log + oc_logit('submission', 'Submission ID ' . $paperid . ' restored' . ($assignNewID ? (' and assigned new ID ' . $newID) : '')); + + if ($assignNewID) { + return($newID); + } else { + return($paperid); + } + } else { + return(null); + } +} + +// Withdraws submission +function withdrawPaper($paperid, $by) { + $q = "SELECT * FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"; + $r = ocsql_query($q) or err('Unable to retrieve submission information'); + if (ocsql_num_rows($r) == 1) { + // paper + $l = ocsql_fetch_assoc($r); + $papervalues = ''; + foreach ($l as $fld => $val) { + $papervalues .= "`$fld`="; + if (($val === NULL) || ($fld == 'format')) { + $papervalues .= "NULL,"; + } else { + $papervalues .= "'" . safeSQLstr($val) . "',"; + } + } + if (!empty($papervalues)) { + $paperq = "INSERT INTO `" . OCC_TABLE_PAPER . "` SET " . rtrim($papervalues, ','); + } else { + $paperq = ''; + } + $title = $l['title']; + $contactid = $l['contactid']; + $contact_author = ''; + $contact_email = ''; + // authors + $q = "SELECT * FROM `" . OCC_TABLE_AUTHOR . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"; + $r = ocsql_query($q) or err('Unable to retrieve ' . oc_strtolower(OCC_WORD_AUTHOR) . ' information'); + $authorvalues = ""; + $fields = ''; + while ($l = ocsql_fetch_assoc($r)) { + if (empty($fields)) { + $fields = "`" . implode('`,`', array_keys($l)) . "`"; + } + $authorvalues .= "("; + foreach ($l as $val) { + if ($val === NULL) { + $authorvalues .= "NULL,"; + } else { + $authorvalues .= "'" . safeSQLstr($val) . "',"; + } + } + $authorvalues = rtrim($authorvalues, ',') . "),"; + // contact author? + if ($l['position'] == $contactid) { + $contact_author = $l['name_first'] . ' ' . $l['name_last']; + $contact_email = $l['email']; + } + } + if (!empty($authorvalues)) { + $authorq = "INSERT INTO `" . OCC_TABLE_AUTHOR . "` ($fields) VALUES " . rtrim($authorvalues, ','); + } else { + $authorq = ''; + } + //topics + $q = "SELECT * FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"; + $r = ocsql_query($q) or err('Unable to retrieve topics'); + $topicValues = ''; + while ($l = ocsql_fetch_assoc($r)) { + $topicValues .= '(' . $l['paperid'] . ', ' . $l['topicid'] . '),'; + } + if (!empty($topicValues)) { + $topicq = "INSERT INTO `" . OCC_TABLE_PAPERTOPIC . "` (`paperid`, `topicid`) VALUES " . rtrim($topicValues, ','); + } else { + $topicq = ''; + } + + // get committee notification template - before hook to allow custom mod + list($mailsubject, $mailbody) = oc_getTemplate('committee-withdrawnsub'); + + // hook + if (oc_hookSet('withdraw_paper-preprocess')) { + foreach ($GLOBALS['OC_hooksAR']['withdraw_paper-preprocess'] as $inc) { + include $inc; + } + } + + $q = "INSERT INTO `" . OCC_TABLE_WITHDRAWN . "` SET `paperid`='" . safeSQLstr($paperid) . "', `title`='" . safeSQLstr($title) . "', `contact_author`='" . safeSQLstr($contact_author) . "', `contact_email`='" . safeSQLstr($contact_email) . "', `papersql`='" . safeSQLstr($paperq) . "', `authorsql`='" . safeSQLstr($authorq) . "', `topicsql`='" . safeSQLstr($topicq) . "', `withdraw_date`='" . date('Y-m-d H:i:s') . "', `withdrawn_by`='" . safeSQLstr($by) . "'"; + ocsql_query($q) or err('Unable to save info'); + if (oc_hookSet('withdraw_paper')) { + foreach ($GLOBALS['OC_hooksAR']['withdraw_paper'] as $inc) { + include $inc; + } + } + + // log + oc_logit('submission', 'Submission ID ' . $paperid . ' withdrawn by ' . $by . '. Title: ' . $title); + + // notify committee members + if (!empty($mailsubject) && !empty($mailbody)) { + // ocIgnore included so poEdit picks up (DB) template translation + //T: [:sid:] is the numeric submission ID + $ocIgnoreSubject = oc_('Submission [:sid:] Withdrawn'); + //T: [:OC_confName:] is the event name; [:sid:] is the numeric submission ID + $ocIgnoreBody = oc_('The submission below has been withdrawn and is no longer assigned to you. + + [:sid:]. [:title:]'); + + // notify assigned reviewers with review incomplete + $reviewersNotifiedAR = array(); + $q = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid` AS `sid`, `" . OCC_TABLE_REVIEWER . "`.`reviewerid` AS `memberid`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `" . OCC_TABLE_REVIEWER . "`.`username`, `" . OCC_TABLE_REVIEWER . "`.`email` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERREVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`='" . safeSQLstr($paperid) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`completed`!='T' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + if ($r = ocsql_query($q)) { + while ($l = ocsql_fetch_assoc($r)) { + $l['title'] = $title; + $tmpsubject = oc_replaceVariables($mailsubject, $l); + $tmpbody = oc_replaceVariables($mailbody, $l); + sendEmail($l['email'], $tmpsubject, $tmpbody); + $reviewersNotifiedAR[] = $l['email']; + } + } + + // notify advocate if not yet notified as a reviewer + $q = "SELECT `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid` AS `sid`, `" . OCC_TABLE_REVIEWER . "`.`reviewerid` AS `memberid`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name`, `" . OCC_TABLE_REVIEWER . "`.`username`, `" . OCC_TABLE_REVIEWER . "`.`email` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`='" . safeSQLstr($paperid) . "' AND `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + if (($r = ocsql_query($q)) && ($l = ocsql_fetch_assoc($r)) && !in_array($l['email'], $reviewersNotifiedAR)) { + $l['title'] = $title; + $tmpsubject = oc_replaceVariables($mailsubject, $l); + $tmpbody = oc_replaceVariables($mailbody, $l); + sendEmail($l['email'], $tmpsubject, $tmpbody); + } + } + } else { + return(false); + } + return(true); +} + +// Deletes submission +function deletePaper($paperid, $log=true) { + $q = "SELECT * FROM `" . OCC_TABLE_PAPER . "` WHERE paperid='" . safeSQLstr($paperid) . "'"; + $r = ocsql_query($q) or err("Unable to retrieve submission format"); + $l = ocsql_fetch_assoc($r); + issueSQL("DELETE FROM `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"); + issueSQL("DELETE FROM `" . OCC_TABLE_PAPERREVIEWER . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"); + issueSQL("DELETE FROM `" . OCC_TABLE_PAPERSESSION . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"); + issueSQL("DELETE FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"); + issueSQL("DELETE FROM `" . OCC_TABLE_AUTHOR . "` WHERE `paperid`='" . safeSQLstr($paperid) . "'"); + issueSQL("DELETE FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`='" .safeSQLstr($paperid) . "'"); + if ($l['format'] && oc_isFile(($pfile = $GLOBALS['OC_configAR']['OC_paperDir'] . $paperid . '.' . $l['format']))) { + if (!oc_deleteFile($pfile)) { + print "       Unable to delete the file for submission " . safeHTMLstr($paperid) . "

    \n"; + } + } + if (oc_hookSet('delete_paper')) { + foreach ($GLOBALS['OC_hooksAR']['delete_paper'] as $inc) { + include $inc; + } + } + + // log + if ($log) { + oc_logit('submission', 'Submission ID ' . $paperid . ' deleted. Title: ' . $l['title']); + } + +} diff --git a/include.php b/include.php new file mode 100644 index 0000000..8280512 --- /dev/null +++ b/include.php @@ -0,0 +1,1964 @@ +'; +$OC_sortImgAsc = 'current sort selection'; +$OC_translate = true; +$OC_translationExtrasAR = array(); +$OC_db = NULL; +$OC_db_error = NULL; +$OC_db_errno = NULL; + +// Init arrays +$OC_hooksAR = array(); +$OC_cssAR = array(); +$OC_jsAR = array(); +$OC_extraHeaderAR = array(); +$OC_onloadAR = array(); +$OC_configAR = array(); +$OC_statusAR = array(); +$OC_modulesAR = array(); +$OC_activeModulesAR = array(); +$OC_languageAR = array(); +$OC_httpHeaders = array('Content-type: text/html; charset=utf-8'); + +// Sanitize PHP_SELF +$_SERVER['PHP_SELF'] = htmlspecialchars($_SERVER['PHP_SELF']); + +// Baseline version - set for install, updated from db below once installed +$GLOBALS['OC_configAR']['OC_version'] = '7.x'; ### + +// Check whether it's home page or a subdir we're in +if (preg_match("/(?:privacy_policy|openconf)\.php/", basename($_SERVER['PHP_SELF']))) { + $pfx = ""; + $OC_basepath = dirname($_SERVER['PHP_SELF']); +} else { + $pfx = "../"; + $OC_basepath = dirname(dirname($_SERVER['PHP_SELF'])); +} + +// Define constants +define('OCC_DB_ENCODING', 'utf8mb4'); // Database encoding +define('OCC_DB_COLLATION', 'utf8mb4_unicode_520_ci'); // Database collation + +define('OCC_BASE_URL', 'http' . ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) ? 's' : '') . '://' . safeHTMLstr($_SERVER['SERVER_NAME']) . (ctype_digit($_SERVER['SERVER_PORT']) && (($_SERVER['SERVER_PORT'] != '80')) ? (':' . $_SERVER['SERVER_PORT']) : '') . $OC_basepath . '/'); + +define('OCC_LIB_DIR', $pfx . 'lib/'); // lib dir + +define('OCC_PLUGINS_DIR', $pfx . 'plugins/'); // plugins dir + +define('OCC_CONFIG_FILE', $pfx . 'config.php'); // config file location + +define('OCC_FORM_INC_FILE', $pfx . 'include-forms.inc'); // forms include file location + +define('OCC_SUBMISSION_INC_FILE', $pfx . 'author/submission.inc'); // submission include file + +define('OCC_ADVOCATE_INC_FILE', $pfx . 'review/advocate.inc'); // advocate include file + +define('OCC_REVIEW_INC_FILE', $pfx . 'review/review.inc'); // review include file + +define('OCC_COMMITTEE_INC_FILE', $pfx . 'review/committee.inc'); // review include file + +define('OCC_MIME_FILE', OCC_LIB_DIR . 'mime.php'); // mime types file location + +define('OCC_ZONE_FILE_EN', OCC_LIB_DIR . 'locale/en/zones.php'); + +define('OCC_UTF8CASECONV_FILE', OCC_LIB_DIR . 'UTF8CaseConv.php'); // UTF8CaseConv file location + +/* DO NOT MODIFY THIS LINE OR OTHERWISE FALSELY DEFINE OR MAKE UP OCC_LICENSE */ (file_exists($pfx . 'license.php') ? require_once($pfx . 'license.php') : define('OCC_LICENSE', 'Public')); // License type /* DO NOT MODIFY THIS LINE */ + +define('OCC_JQUERY_VERSION', '3.5.0'); // jQuery version +define('OCC_JQUERYUI_VERSION', '1.12.1'); // jQueryUI version - also update oc_customforms.js + + +// Set OC_formatAR with mime types - moved to OCC_MIME_FILE in 4.00 +require_once OCC_MIME_FILE; + +// Row Array - used for toggling row style +$rowAR = array(); +$rowAR[1] = 2; +$rowAR[2] = 1; + +// Yes/No Array +$yesNoAR = array( + 1 => 'Yes', + 0 => 'No' +); + +// Status Array +$OC_statusValueAR = array( + 1 => 'Open', + 0 => 'Closed', +); + +// Context +$OC_context = stream_context_create(array('http'=>array('timeout'=>20))); + +// i18n routines +// params: s|ource, d|omain, override-translate even if Chair (i.e.,OC_translate=false) +function oc_($s, $d='', $override=false) { + if ($s == '') { + return(''); + } + if (($GLOBALS['OC_locale'] == 'en') || (!$GLOBALS['OC_translate'] && !$override)) { + if (isset($GLOBALS['OC_translationExtrasAR'][$GLOBALS['OC_locale']][$s])) { + return ($GLOBALS['OC_translationExtrasAR'][$GLOBALS['OC_locale']][$s]); + } else { + if ( defined('OCC_WORD_AUTHOR') && (OCC_WORD_AUTHOR != 'Author')) { + $from = array('/Author/', '/author/'); + $to = array(OCC_WORD_AUTHOR, oc_strtolower(OCC_WORD_AUTHOR)); + } else { + $from = array(); + $to = array(); + } + if ( defined('OCC_WORD_CHAIR') && (OCC_WORD_CHAIR != 'Chair') ) { + $from[] = '/(? 0) { + return(preg_replace($from, $to, $s)); + } else { + return($s); + } + } + } elseif (isset($GLOBALS['OC_translationExtrasAR'][$GLOBALS['OC_locale']][$s])) { + return ($GLOBALS['OC_translationExtrasAR'][$GLOBALS['OC_locale']][$s]); + } elseif ( ( $shash = hash("md5", $s) ) && isset($GLOBALS['OC_translationExtrasAR'][$GLOBALS['OC_locale']][$shash])) { + return ($GLOBALS['OC_translationExtrasAR'][$GLOBALS['OC_locale']][$shash]); + } elseif (function_exists('gettext')) { + if (!empty($d)) { + return(dgettext($d, $s)); + } else { + return(_($s)); + } + } + else { return($s); } + /* + elseif (empty($t)) { + return(T_($s)); + } else { + return(T_dgettext($domain, $s)); + } + */ +} +function oc_n($s, $p, $c, $d='') { // s|ource p|lural c|ount d|omain + if ($s == '') { + return(''); + } + if (function_exists('ngettext')) { + if (!empty($d)) { + return(dngettext($d, $s, $p, $c)); + } else { + return(ngettext($s, $p, $c)); + } + } + elseif ($c > 1) { return $p; } + else { return $s; } + /* + elseif (empty($d)) { + return(T_ngettext($s, $p, $c)); + } else { + return(T_dngettext($d, $s, $p, $c)); + } + */ +} + +// Returns a string with double-quotes (only) slashes +function slashQuote($s) { + return(preg_replace('/"/','\\"',$s)); +} + +// Checks whether the script is close to timing out +function oc_checkTimeout() { + if (($GLOBALS['OC_timeStamp'] > 0) + && ((time() - $GLOBALS['OC_timeStamp']) > ($GLOBALS['OC_maxRunTime'] - 5)) // timeout if within 5 seconds + ) { + return TRUE; + } + return FALSE; +} + +// Returns a string containing define statements with an updated constant value +function replaceConstantValue($constName, $newValue, &$string) { + $newValue = str_replace("'", "\\'", $newValue); + $string = preg_replace("/(define\('" . $constName . "',\s?'?).*?('?\);)/", '${1}' . $newValue . '${2}', $string); +} + +// Returns true/false on whether a named hook is set +function oc_hookSet($hook) { + if (isset($GLOBALS['OC_hooksAR'][$hook]) && !empty($GLOBALS['OC_hooksAR'][$hook])) { + return true; + } else { + return false; + } +} + +// Adds a hook for additional functionality; typically used with modules +function oc_addHook($name, $value) { + if (!isset($GLOBALS['OC_hooksAR'][$name])) { // init if first hook for name + $GLOBALS['OC_hooksAR'][$name] = array($value); + } elseif (!in_array($value, $GLOBALS['OC_hooksAR'][$name])) { // add only if not duplicate + $GLOBALS['OC_hooksAR'][$name][] = $value; + } +} + +// Add CSS file to be read in by header +function oc_addCSS($file,$moduleId='') { + if (!empty($moduleId)) { + $GLOBALS['OC_cssAR'][] = 'modules/' . $moduleId . '/' . $file; + } else { + $GLOBALS['OC_cssAR'][] = $file; + } +} + +// Add JS file to be read in by header +function oc_addJS($file,$moduleId='') { + if (!empty($moduleId)) { + $GLOBALS['OC_jsAR'][] = 'modules/' . $moduleId . '/' . $file; + } else { + $GLOBALS['OC_jsAR'][] = $file; + } +} + +// Add body onLoad to be included in header +function oc_addOnLoad($js) { + $GLOBALS['OC_onloadAR'][] = $js; +} + +// Add extra headers +function oc_addHeader($hdr) { + $GLOBALS['OC_extraHeaderAR'][] = $hdr; +} + +// Returns an array of database tables +function getTables() { + $constAR = get_defined_constants(); + preg_match_all("/(OCC_TABLE_\w+)/",implode('\0',array_keys($constAR)),$tAR); + foreach ($tAR[0] as $t) { $tableAR[] = constant($t); } + return($tableAR); +} + +// oc_encrypt - encrypts string +function oc_encrypt($s, $key='') { + $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC')); + if (empty($key)) { + $key = ((defined('OCC_ENC_KEY') && (OCC_ENC_KEY != '')) ? OCC_ENC_KEY : pack('H*', md5(OCC_LICENSE))); // fallback for upgrade error + } + return(base64_encode($iv) . '|' . base64_encode(openssl_encrypt($s, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv))); +} + +// oc_decrypt - decrypts encrypted string +function oc_decrypt($e, $key='') { + if (empty($key)) { + $key = ((defined('OCC_ENC_KEY') && (OCC_ENC_KEY != '')) ? OCC_ENC_KEY : pack('H*', md5(OCC_LICENSE))); // fallback for upgrade error + } + list($e1, $e2) = explode('|', $e); + return(trim(openssl_decrypt(base64_decode($e2), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, base64_decode($e1)))); +} + +// oc_password_hash - hashes password +function oc_password_hash($pw) { + return(password_hash($pw, PASSWORD_DEFAULT)); +} + +// oc_password_needs_rehash - checks whether password hash is outdated & new format available +function oc_password_needs_rehash($hash) { + return(password_needs_rehash($hash, PASSWORD_DEFAULT)); +} + +// oc_password_verify - verifies password and updates hash if needed +function oc_password_verify($pw, $hash, $type=null, $id=null) { + $verified = false; + if (oc_hookSet('password-verify')) { + foreach ($GLOBALS['OC_hooksAR']['password-verify'] as $hook) { + require_once $hook; + } + } else { + // verify hash + if (preg_match("/^\\$/", $hash)) { // new school + if (password_verify($pw, $hash)) { + $verified = true; + } + } else { // old school + $salt = substr($hash, 0, 10); + if ($hash == ($salt . sha1($salt . $pw))) { + $verified = true; + } + } + // update hash? + if ($verified && preg_match("/^\w+$/", $type) && oc_password_needs_rehash($hash)) { + if (($type == 'submission') && preg_match("/^\d+$/", $id)) { + ocsql_query("UPDATE `" . OCC_TABLE_PAPER . "` SET `password`='" . safeSQLstr(oc_password_hash($pw)) . "' WHERE `paperid`='" . safeSQLstr($id) . "'"); + } elseif (($type == 'committee') && preg_match("/^\d+$/", $id)) { + ocsql_query("UPDATE `" . OCC_TABLE_REVIEWER . "` SET `password`='" . safeSQLstr(oc_password_hash($pw)) . "' WHERE `reviewerid`='" . safeSQLstr($id) . "'"); + } elseif ($type == 'chair') { + updateConfigSetting('OC_chair_pwd', oc_password_hash($pw)); + } + } + // check for chair pwd if not verified + if (!$verified && ($type != 'chair') && ($type != 'trump') && OCC_CHAIR_PWD_TRUMPS && oc_password_verify($pw, $GLOBALS['OC_configAR']['OC_chair_pwd'], 'trump')) { + $verified=true; + } + } + + return($verified); +} + +// oc_password_generate - creates and returns a new random password +function oc_password_generate() { + $validChars = 'bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ2346789'; // available chars for pwd + $cmax = strlen($validChars); + $ctot = rand(10, 14); // pwd length + $p = ''; // pwd + $c = 0; // number of chars in pwd + while ($c < $ctot) { + $p .= substr($validChars, mt_rand(0, ($cmax - 1)), 1); + $c++; + } + return($p); +} + +// Format number +// $n = number of bytes +function oc_formatNumber($n) { + if ($n > 1048576) { // > 1 MB + return(number_format(($n/1048576),1) . "MB"); + } else { + return(number_format(($n/1024),0) . "KB"); + } +} + +// Convert units +function toMB($n) { + if (preg_match("/^(\d+)(\w?)[bB]?$/",$n,$matches)) { + switch (strtoupper($matches[2])) { + case '': + case 'B': return((($matches[1] >= 105000) ? (number_format(($matches[1]/1048576),1) . "MB") : (number_format(($matches[1]/1024),1) . "KB"))); break; + case 'K': return((($matches[1] >= 103) ? (number_format(($matches[1]/1024),1) . "MB") : (number_format($matches[1],1) . "KB"))); break; + case 'M': return($matches[1] . "MB"); break; + } + } + return($n); +} + +// Returns the value of a var if it exists in the specified array, or a default value +// if safe=true and array value exists, it's returned safeHTMLstr() +function varValue($varName, &$ar, $default='', $safe=false) { + if (isset($ar[$varName])) { + if ($safe) { + return(safeHTMLstr($ar[$varName])); + } else { + return($ar[$varName]); + } + } + return($default); +} + +// Displays page header +function printHeader($what, $function="0") { + global $pfx; + + // CHANGES TO MENU ITEMS MAY REQUIRE UPDATE TO PLACEMENT OF PRIVACY POLICY BELOW + $menusAR = array( + 0 => array( // none of the below + safeHTMLstr(sprintf(oc_('%s Home'), 'OpenConf')), + '' . safeHTMLstr(oc_('Email Chair')) . '', + ), + 1 => array( // chair + '' . safeHTMLstr(sprintf(oc_('%s Home'), (defined('OCC_WORD_CHAIR') ? OCC_WORD_CHAIR : 'Chair'))) . '', + 'Help', + 'Sign Out', + ), + 2 => array( // committee + //T: Member Home = Committee Member Home Page (e.g., Reviewer Home Page) + '' . oc_('Member Home') . '', + '' . safeHTMLstr(oc_('Update Profile')) . '', + '' . oc_('Email Chair') . '', + '' . oc_('Sign Out') . '', + ), + 3 => array( // author, sign in/up, other + //T: %s = OpenConf + '' . safeHTMLstr(sprintf(oc_('%s Home'), 'OpenConf')) . '', + '' . safeHTMLstr(oc_('Email Chair')) . '', + ), + 4 => array( // install + 'Restart Install', + ), + ); + $menusFillerAR = array( + 1 => 'Signed in as: ' . safeHTMLstr($GLOBALS['OC_configAR']['OC_chair_uname']), + 2 => safeHTMLstr(sprintf(oc_('Signed in as: %1$s (%2$d)'), safeHTMLstr($_SESSION[OCC_SESSION_VAR_NAME]['acusername']), $_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid'])), + ); + + // privacy policy? + if ($GLOBALS['OC_configAR']['OC_privacy_display'] == 1) { + $privacyMenu = '' . safeHTMLstr(oc_('Privacy Policy')) . ''; + array_splice($menusAR[0], 1, 0, $privacyMenu); + array_splice($menusAR[1], 1, 0, $privacyMenu); + array_splice($menusAR[2], 2, 0, $privacyMenu); + array_splice($menusAR[3], 1, 0, $privacyMenu); + } + + if (oc_hookSet('header-top-pre')) { + foreach ($GLOBALS['OC_hooksAR']['header-top-pre'] as $hook) { + require_once $hook; + } + } + + require_once $GLOBALS['pfx'] . (isset($GLOBALS['OC_configAR']['OC_headerFile']) ? $GLOBALS['OC_configAR']['OC_headerFile'] : 'header.php'); + + print ' + +
    +
    +'; + + if (oc_hookSet('header-top')) { + foreach ($GLOBALS['OC_hooksAR']['header-top'] as $hook) { + require_once $hook; + } + } + + if (isset($GLOBALS['OC_displayTop']) && !empty($GLOBALS['OC_displayTop'])) { + print $GLOBALS['OC_displayTop']; + } + + if (!empty($what)) { + print ' +

    ' . safeHTMLstr($what) . '

    +'; + } + + unset($menusAR); + unset($menusFillerAR); +} + +// Displays page footer +function printFooter() { + global $pfx; + + if (oc_hookSet('footer-top')) { + foreach ($GLOBALS['OC_hooksAR']['footer-top'] as $hook) { + require_once $hook; + } + } + + print ' +
    +

     

    +
    +'; + + if ($GLOBALS['OC_configAR']['OC_privacy_display'] == 2) { + print ''; + } + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// IT IS A VIOLATION OF THE OPENCONF LICENSE TO +// MODIFY OR HIDE THE PRINT STATEMENT BELOW OR ITS ASSOCIATED CSS STYLES +// WITHOUT HAVING FIRST PURCHASED AN OPENCONF BRANDING-FREE LICENSE FOR THIS INSTALLATION +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + print '
    ' . +//T: %2s = OpenConf +/* DO NOT REMOVE, ALTER, OR HIDE THIS COPYRIGHT NOTICE */sprintf(oc_('Powered by %2$s®'), 'https://www.OpenConf.com', 'OpenConf') . '
    ' . +//T: %1s-%2s = YYYY-YYYY, %4$s = Zakon Group LLC +/* DO NOT REMOVE, ALTER, OR HIDE THIS COPYRIGHT NOTICE */sprintf(oc_('Copyright ©%1$s-%2$s %4$s'), '2002', '2020', 'https://www.ZakonGroup.com/', 'Zakon Group LLC') . '
    '; +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// IT IS A VIOLATION OF THE OPENCONF LICENSE TO +// MODIFY OR HIDE THE PRINT STATEMENT ABOVE OR ITS ASSOCIATED CSS STYLES +// WITHOUT HAVING FIRST PURCHASED AN OPENCONF BRANDING-FREE LICENSE FOR THIS INSTALLATION +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + // include Google Analytics tag if it starts with +
    +'; + } elseif (OC_CAPTCHA_service == 'reCAPTCHA') { + print ' + +
    + +'; + } +} + +// verify CAPTCH - returns false if verifies OK, otherwise error string +function mod_captcha_verifyCAPTCHA() { + if (OC_CAPTCHA_service == 'hCaptcha') { + $mod_captcha_var = 'h-captcha-response'; + $mod_catpcha_url = 'https://hcaptcha.com/siteverify'; + } elseif (OC_CAPTCHA_service == 'reCAPTCHA') { + $mod_captch_var = 'g-captcha-response'; + $mod_catpcha_url = 'https://www.google.com/recaptcha/api/siteverify'; + } else { + err('invalid CAPTCHA'); + } + + if (isset($_POST[$mod_captcha_var]) && !empty($_POST[$mod_captcha_var])) { + $mod_catpcha_url .= '?secret=' . urlencode(OC_CAPTCHA_private_key) . '&response=' . urlencode($_POST['h-captcha-response']) . '&remoteip=' . urlencode($_SERVER['REMOTE_ADDR']); + if ($response = file_get_contents($mod_catpcha_url)) { + if ($responseAR = json_decode($response, true)) { + if (trim($responseAR['success']) == true) { + return(false); // OK + } elseif (isset($responseAR['error-codes'])) { + $mod_captcha_err = (is_array($responseAR['error-codes']) ? implode(',', $responseAR['error-codes']) : $responseAR['error-codes']); + } else { + $mod_captcha_err = 3; + } + } else { + $mod_captcha_err = 4; + } + } else { + $mod_captcha_err = 5; + } + } + + return( + oc_('CAPTCHA verification failed') . + (empty($mod_captcha_err) ? '' : (' (' . $mod_captcha_err . ')')) + ); +} diff --git a/modules/captcha/contact-fields.inc b/modules/captcha/contact-fields.inc new file mode 100644 index 0000000..f269a67 --- /dev/null +++ b/modules/captcha/contact-fields.inc @@ -0,0 +1,24 @@ + + + + + +'; + +require_once('captcha-include.inc'); + +mod_captcha_displayCAPTCHA(); + +print ''; \ No newline at end of file diff --git a/modules/captcha/contact-validate.inc b/modules/captcha/contact-validate.inc new file mode 100644 index 0000000..b05f72c --- /dev/null +++ b/modules/captcha/contact-validate.inc @@ -0,0 +1,16 @@ +' . $mod_captcha_err . ''; +} diff --git a/modules/captcha/index.html b/modules/captcha/index.html new file mode 100644 index 0000000..e69de29 diff --git a/modules/captcha/index.php b/modules/captcha/index.php new file mode 100644 index 0000000..e69de29 diff --git a/modules/captcha/init.inc b/modules/captcha/init.inc new file mode 100644 index 0000000..76e1c74 --- /dev/null +++ b/modules/captcha/init.inc @@ -0,0 +1,42 @@ +CAPTCHA')); + + // Register settings export/import hooks + oc_addHook('settings-export-options', '../modules/captcha/settings-export-options.inc'); + oc_addHook('settings-export-prep', '../modules/captcha/settings-export-prep.inc'); + +} + +// Register form hooks +if (defined('OC_CAPTCHA_service')) { + if (preg_match("/submit\.php/", $_SERVER['PHP_SELF'])) { // new subs only + oc_addHook('author-submit-fields', '../modules/captcha/author-fields.inc'); + oc_addHook('author-submission-validate', '../modules/captcha/author-validate.inc'); + } + oc_addHook('author-contact-fields', '../modules/captcha/contact-fields.inc'); + oc_addHook('author-contact-validate', '../modules/captcha/contact-validate.inc'); +} \ No newline at end of file diff --git a/modules/captcha/install-db.sql b/modules/captcha/install-db.sql new file mode 100644 index 0000000..3333c08 --- /dev/null +++ b/modules/captcha/install-db.sql @@ -0,0 +1,21 @@ +## +----------------------------------------------------------------------+ +## | OpenConf | +## +----------------------------------------------------------------------+ +## | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +## +----------------------------------------------------------------------+ +## | This source file is subject to the OpenConf License, available on | +## | the OpenConf web site: www.OpenConf.com | +## +----------------------------------------------------------------------+ + +## NOTE: This file cannot contain a semi-colon (;) except at the end of a +## SQL statement. + +# -------------------------------------------------------- + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('captcha', 'MOD_CAPTCHA_private_key', '', 'reCAPTCHA Private Key', 'obtain from google.com/recaptcha', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('captcha', 'MOD_CAPTCHA_public_key', '', 'reCAPTCHA Public Key', 'obtain from google.com/recaptcha', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('captcha', 'MOD_CAPTCHA_hcaptcha_private_key', '', 'hCaptcha Private Key', 'obtain from hcaptcha.com', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('captcha', 'MOD_CAPTCHA_hcaptcha_public_key', '', 'hCaptcha Public Key', 'obtain from hcaptcha.com', 0); diff --git a/modules/captcha/module.inc b/modules/captcha/module.inc new file mode 100644 index 0000000..c33f746 --- /dev/null +++ b/modules/captcha/module.inc @@ -0,0 +1,22 @@ + 'CAPTCHA', + 'description' => 'Checks that submissions are being made by a human', + 'version' => '3.0.0', + 'dependencies' => array(), + 'developer' => 'OpenConf' +); diff --git a/modules/captcha/settings-export-options.inc b/modules/captcha/settings-export-options.inc new file mode 100644 index 0000000..c4b1c1a --- /dev/null +++ b/modules/captcha/settings-export-options.inc @@ -0,0 +1,16 @@ + +
    +'; diff --git a/modules/captcha/settings-export-prep.inc b/modules/captcha/settings-export-prep.inc new file mode 100644 index 0000000..89a99af --- /dev/null +++ b/modules/captcha/settings-export-prep.inc @@ -0,0 +1,14 @@ +

    Please re-enter your settings, noting the following:

    • ' . implode('
    • ', $err) . '



    '; + } else { // Update settings + updateAllConfigSettings($MOD_CAPTCHA_configVars, $_POST, OCC_MODULE_ID); + // notify user + print '

    Settings Saved

    '; + } +} + +print ' +
    + + +

    OpenConf supports the hCaptcha and Google reCAPTCHA services. Sign up for an account with either service and enter the public/private keys below. If credentials are filled in for both services, hCAPTCHA will be used by default.

    + +
    +hCpatcha +
    In order to use hCaptcha, first sign up for an account at https://hcaptcha.com
    +
    + +
    + + +
    + +
    + + +
    + +
    +
    + + +
    +Google reCAPTCHA v2 +
    In order to use reCAPTCHA, first sign up for an account at https://google.com/recaptcha
    +
    + +
    + + +
    + +
    + + +
    + +
    +
    + +

    +
    +'; diff --git a/modules/captcha/uninstall-db.sql b/modules/captcha/uninstall-db.sql new file mode 100644 index 0000000..9b70b05 --- /dev/null +++ b/modules/captcha/uninstall-db.sql @@ -0,0 +1,15 @@ +## +----------------------------------------------------------------------+ +## | OpenConf | +## +----------------------------------------------------------------------+ +## | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +## +----------------------------------------------------------------------+ +## | This source file is subject to the OpenConf License, available on | +## | the OpenConf web site: www.OpenConf.com | +## +----------------------------------------------------------------------+ + +## NOTE: This file cannot contain a semi-colon (;) except at the end of a +## SQL statement. + +# -------------------------------------------------------- + +DELETE FROM `config` WHERE `module`='captcha'; diff --git a/modules/captcha/upgrade/index.html b/modules/captcha/upgrade/index.html new file mode 100644 index 0000000..e69de29 diff --git a/modules/captcha/upgrade/index.php b/modules/captcha/upgrade/index.php new file mode 100644 index 0000000..e69de29 diff --git a/modules/captcha/upgrade/upgrade-6.20-6.30.inc b/modules/captcha/upgrade/upgrade-6.20-6.30.inc new file mode 100644 index 0000000..aa1bf33 --- /dev/null +++ b/modules/captcha/upgrade/upgrade-6.20-6.30.inc @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/modules/filetype/README.html b/modules/filetype/README.html new file mode 100644 index 0000000..4dbcbb5 --- /dev/null +++ b/modules/filetype/README.html @@ -0,0 +1,82 @@ + + + + +File Format Check Module for OpenConf + + + + +

    File Format Check Module for OpenConf

    +

    This module verifies whether an uploaded file matches the selected format. Instead of relying on the file extension or browser-provided MIME type, at least for the formats below, the file itself is inspected to determine its format through signature matching. If a signature is not available, the file extension is checked instead.

    +

    Signature checking is currently available for the following:
    +

      +
    • Adobe PDF
    • +
    • HTML
    • +
    • Microsoft Word
    • +
    • PostScript
    • +
    • RTF
    • +
    • WordPerfect
    • +
    • XML
    • +
    +

    + +

    Requirements

    + +

    none

    + +

    Configuration

    + +

    Options are provided in this module's settings that allow excluding Office (2007) Open XML documents (.docx) and RTF documents from being accepted as Word documents.

    + +

    Usage

    + +

    When a file is uploaded, the detected file format is automatically verified against the selected format. If the format does not match, the upload will not be completed and a notice is displayed.

    + +
    + +

    Version 3.0.1
    + - Fixed missing setting export/import hooks

    + +

    Version 3.0.0
    + - Added file format identification using PHP Fileinfo

    + +

    Version 2.0.1
    + - Added file extension verification of MS Office 2007+ formats

    + +

    Version 2.0.0
    + - Added settings import/export
    + - Added module installation and activation as part of standard OpenConf installation
    + - Added support for custom Author/Chair name
    + - Added alternative file extensions for jpg and mpg
    + - Renamed module to File Format Check +

    + +

    Version 1.0.5
    + - Fixed HTML file type verification +

    + +

    Version 1.0.4
    + - Dropped setting MOD_FILETYPE_allow_officeopenxml as .docx/.xlsx/.pptx added as MIME types
    + - Changed paperid to mediumint(6)
    + - Changed author-file-validate to handle both submission and upload (dropped author-upload-validate) +

    + +

    Version 1.0.3
    + - Added token check for settings.inc +

    + +

    Version 1.0.2
    + - Added support for file type validation of files uploaded during initial submission +

    + +

    Version 1.0.1
    + - Fixed extraneous print in author-upload-validate.inc +

    + +

    Version 1.0.0
    + - Initial Release

    + + diff --git a/modules/filetype/author-file-validate.inc b/modules/filetype/author-file-validate.inc new file mode 100644 index 0000000..f20911e --- /dev/null +++ b/modules/filetype/author-file-validate.inc @@ -0,0 +1,143 @@ + array('txt', 'text'), + 'jpg' => array('jpg', 'jpeg'), + 'mpg' => array('mpg', 'mpeg', 'mp4') + ); + + // Checks $data for $sig from $offset + function mod_filetype_checksig($data, $sig, $offset=0, $case=1) { + if (($case && (strpos($data, $sig) === $offset)) + || (! $case && stripos($data, $sig) === $offset) + ) { + return(true); + } + return(false); + } + + // Check using Fileinfo + if (function_exists('finfo_open') + && isset($GLOBALS['OC_mimeTypeAR'][$MOD_FILETYPE_format]) + && ($mod_filetype_finfo = finfo_open(FILEINFO_MIME_TYPE)) + && (finfo_file($mod_filetype_finfo, $MOD_FILETYPE_file) == $GLOBALS['OC_mimeTypeAR'][$MOD_FILETYPE_format]) + ) { + $MOD_FILETYPE_valid = true; + } else { // Check using signature + $MOD_FILETYPE_valid = false; + + if ($MOD_FILETYPE_fp = fopen($MOD_FILETYPE_file, 'r')) { + $MOD_FILETYPE_bytes = fread($MOD_FILETYPE_fp, 512); + switch ($MOD_FILETYPE_format) { + case 'doc': + case 'ppt': + case 'xls': + if (mod_filetype_checksig($MOD_FILETYPE_bytes, "\320\317\021\340\241\261\032\341")) { + $MOD_FILETYPE_bytes = fread($MOD_FILETYPE_fp, 512); + if (($MOD_FILETYPE_format == 'doc') && mod_filetype_checksig($MOD_FILETYPE_bytes, "\354\245\301\0")) { + $MOD_FILETYPE_valid = true; + } + elseif (($MOD_FILETYPE_format == 'doc') && $OC_configAR['MOD_FILETYPE_allow_rtfforword'] && mod_filetype_checksig($MOD_FILETYPE_bytes, "{\\rtf")) { + $MOD_FILETYPE_valid = true; + } + elseif (($MOD_FILETYPE_format == 'ppt') && preg_match("/^ppt/", $MOD_FILETYPE_ext)) { # mod_filetype_checksig($MOD_FILETYPE_bytes, "")) { + $MOD_FILETYPE_valid = true; + } elseif (($MOD_FILETYPE_format == 'xls') && preg_match("/^xls/", $MOD_FILETYPE_ext)) { # && mod_filetype_checksig($MOD_FILETYPE_bytes, "")) { + $MOD_FILETYPE_valid = true; + } + } + break; + case 'docx': + case 'pptx': + case 'xlsx': + if ( + mod_filetype_checksig($MOD_FILETYPE_bytes, "PK\003\004\024\0\006\0") + && + preg_match("/^" . substr($MOD_FILETYPE_format, 0, 3) . "/", $MOD_FILETYPE_ext) + ) { + $MOD_FILETYPE_valid = true; + } + break; + case 'pdf': + if (mod_filetype_checksig($MOD_FILETYPE_bytes, '%PDF')) { + $MOD_FILETYPE_valid = true; + } + break; + case 'ps': + if (mod_filetype_checksig($MOD_FILETYPE_bytes, '%!PS-Adobe')) { + $MOD_FILETYPE_valid = true; + } + break; + case 'rtf': + if (mod_filetype_checksig($MOD_FILETYPE_bytes, '{\\rtf')) { + $MOD_FILETYPE_valid = true; + } + break; + case 'wp': + if (mod_filetype_checksig($MOD_FILETYPE_bytes, '\377WPC')) { + $MOD_FILETYPE_valid = true; + } + break; + case 'xml': + if (mod_filetype_checksig($MOD_FILETYPE_bytes, '' . oc_('File uploaded does not match format selected') . ''; + } else { // upload + warn(oc_('File uploaded does not match format selected. Please re-check and try again. If you are unable to upload the file, contact the Chair.')); + } + } +} // skip if chair \ No newline at end of file diff --git a/modules/filetype/index.html b/modules/filetype/index.html new file mode 100644 index 0000000..e69de29 diff --git a/modules/filetype/index.php b/modules/filetype/index.php new file mode 100644 index 0000000..e69de29 diff --git a/modules/filetype/init.inc b/modules/filetype/init.inc new file mode 100644 index 0000000..6087610 --- /dev/null +++ b/modules/filetype/init.inc @@ -0,0 +1,22 @@ +File Format Check')); + +// Settings Export/Import +oc_addHook('settings-export-options', '../modules/filetype/settings-export-options.inc'); +oc_addHook('settings-export-prep', '../modules/filetype/settings-export-prep.inc'); \ No newline at end of file diff --git a/modules/filetype/install-db.sql b/modules/filetype/install-db.sql new file mode 100644 index 0000000..feb09ef --- /dev/null +++ b/modules/filetype/install-db.sql @@ -0,0 +1,22 @@ +## +----------------------------------------------------------------------+ +## | OpenConf | +## +----------------------------------------------------------------------+ +## | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +## +----------------------------------------------------------------------+ +## | This source file is subject to the OpenConf License, available on | +## | the OpenConf web site: www.OpenConf.com | +## +----------------------------------------------------------------------+ + + +## NOTE: UPDATES TO THIS FILE NEED TO BE REFLECTED IN lib/DB.sql + + + +## NOTE: This file cannot contain a semi-colon (;) except at the end of a +## SQL statement. + +# -------------------------------------------------------- + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('filetype', 'MOD_FILETYPE_chairoverride', '1', 'Skip Check if Chair', 'Skips file format check if Chair uploading', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('filetype', 'MOD_FILETYPE_allow_rtfforword', '1', 'Accept RTF for Word Doc', 'Permit RTF MS Word docs', 0); diff --git a/modules/filetype/module.inc b/modules/filetype/module.inc new file mode 100644 index 0000000..90971c7 --- /dev/null +++ b/modules/filetype/module.inc @@ -0,0 +1,23 @@ + 'File Format Check', + 'description' => 'Verifies file uploaded matches selected format', + 'version' => '3.0.1', + 'dependencies' => array(), + 'developer' => 'OpenConf' +); + diff --git a/modules/filetype/settings-export-options.inc b/modules/filetype/settings-export-options.inc new file mode 100644 index 0000000..2f1a98a --- /dev/null +++ b/modules/filetype/settings-export-options.inc @@ -0,0 +1,16 @@ + +
    +'; diff --git a/modules/filetype/settings-export-prep.inc b/modules/filetype/settings-export-prep.inc new file mode 100644 index 0000000..8a40ec4 --- /dev/null +++ b/modules/filetype/settings-export-prep.inc @@ -0,0 +1,14 @@ +Settings Saved

    '; +} + +print ' +
    + + +

    Skip Check if ' . OCC_WORD_CHAIR . ': ' . +generateRadioOptions('MOD_FILETYPE_chairoverride', $yesNoAR, $OC_configAR['MOD_FILETYPE_chairoverride']) +. '
    Skips file format check if ' . OCC_WORD_CHAIR . ' uploading.

    + +

    Allow RTF for Word Doc: ' . +generateRadioOptions('MOD_FILETYPE_allow_rtfforword', $yesNoAR, $OC_configAR['MOD_FILETYPE_allow_rtfforword']) +. '
    Checking Yes will allow Word documents (.doc) in RTF format.

    + +
    +

    +
    +'; diff --git a/modules/filetype/uninstall-db.sql b/modules/filetype/uninstall-db.sql new file mode 100644 index 0000000..3ae18a1 --- /dev/null +++ b/modules/filetype/uninstall-db.sql @@ -0,0 +1,15 @@ +## +----------------------------------------------------------------------+ +## | OpenConf | +## +----------------------------------------------------------------------+ +## | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +## +----------------------------------------------------------------------+ +## | This source file is subject to the OpenConf License, available on | +## | the OpenConf web site: www.OpenConf.com | +## +----------------------------------------------------------------------+ + +## NOTE: This file cannot contain a semi-colon (;) except at the end of a +## SQL statement. + +# -------------------------------------------------------- + +DELETE FROM `config` WHERE `module`='filetype'; diff --git a/modules/index.html b/modules/index.html new file mode 100644 index 0000000..e69de29 diff --git a/modules/index.php b/modules/index.php new file mode 100644 index 0000000..dc17e91 --- /dev/null +++ b/modules/index.php @@ -0,0 +1,5 @@ + diff --git a/modules/install.php b/modules/install.php new file mode 100644 index 0000000..0e0bd64 --- /dev/null +++ b/modules/install.php @@ -0,0 +1,69 @@ + \ No newline at end of file diff --git a/modules/mail/README.html b/modules/mail/README.html new file mode 100644 index 0000000..0ca1594 --- /dev/null +++ b/modules/mail/README.html @@ -0,0 +1,48 @@ + + + + +Mail Module for OpenConf + + + + +

    Mail Module for OpenConf

    +

    This module adds support for using an external SMTP server in addition to the built-in PHP mail() function. The PHPMailer library is required and must be separately installed.

    + +

    Requirements

    + +

    The PHPMailer library must be installed to the plugins/PHPMailer/ directory so that (for PHPMailer version 6+) the PHPMailer.php file is found at plugins/PHPMailer/src/PHPMailer.php or plugins/PHPMailer/PHPMailer.php. In order to use PHPMailer from another directory, modify the MOD_MAIL_PHPMAILER_DIR constant in the module.inc file.

    + +

    For PHPMailer <= 5.2, the file PHPMailerAutoload.php must be in plugins/PHPMailer/PHPMailerAutoload.php, and module/mail/module.inc edited to remove the two use lines atop the file.

    + +

    The SMTP server must support multiple repeated connections. For example, if the Chair is sending an email to all contact authors and there are 100 submissions, the SMTP server will receive 100 connections, one after the other. If the SMTP server is slow, does rate limiting, or PHP is configured with a short script execution time, messages may fail.

    + +

    Configuration

    + +

    Mail options are defined via this module's settings. PHPMailer must be installed prior to accessing the settings.

    + +

    If possible, enter the SMTP server's IP address for the SMTP Host to speed up processing by saving the DNS lookup.

    + +

    A link is displayed at the bottom of the module's settings page to send a test message using the active mailer.

    + +

    Usage

    + +

    Once configured, this module works without user intervention.

    + +

    Note

    + +

    The SMTP server account username and password may optionally be set directly atop the module.inc file found in the module's directory -- see the section // SMTP Auth.

    + +
    + +

    Version 1.0.1
    +- Updated to support PHPMailer 6 +

    + +

    Version 1.0.0
    +- Initial Release

    + + diff --git a/modules/mail/index.html b/modules/mail/index.html new file mode 100644 index 0000000..e69de29 diff --git a/modules/mail/index.php b/modules/mail/index.php new file mode 100644 index 0000000..e69de29 diff --git a/modules/mail/init.inc b/modules/mail/init.inc new file mode 100644 index 0000000..65ea588 --- /dev/null +++ b/modules/mail/init.inc @@ -0,0 +1,24 @@ +Mail')); + +// Settings Export/Import +oc_addHook('settings-export-options', '../modules/mail/settings-export-options.inc'); +oc_addHook('settings-export-prep', '../modules/mail/settings-export-prep.inc'); \ No newline at end of file diff --git a/modules/mail/install-db.sql b/modules/mail/install-db.sql new file mode 100644 index 0000000..23c455f --- /dev/null +++ b/modules/mail/install-db.sql @@ -0,0 +1,32 @@ +## +----------------------------------------------------------------------+ +## | OpenConf | +## +----------------------------------------------------------------------+ +## | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +## +----------------------------------------------------------------------+ +## | This source file is subject to the OpenConf License, available on | +## | the OpenConf web site: www.OpenConf.com | +## +----------------------------------------------------------------------+ + + +## NOTE: This file cannot contain a semi-colon (;) except at the end of a +## SQL statement. + +# -------------------------------------------------------- + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_mailer', 'php', 'Mailer', 'Mailer to use for sending messages, options: php (built-in PHP mail function), smtp (SMTP server)', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_from_email', '', 'From Email', 'Email address to use in From field. Leave blank for Chair Email Address', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_from_name', '', 'From Name', 'Name to use in From field. Leave blank for Event Short Name', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_return_path', 1, 'Return Path', 'Set return path to match From Email (1=Yes, 0=no)', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_smtp_host', '', 'SMTP Host', 'SMTP server name', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_smtp_port', '', 'SMTP Port', 'SMTP server port', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_smtp_encryption', 'none', 'SMTP Encryption', 'SMTP server encryption, options: none, ssl, tls', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_smtp_username', '', 'SMTP Username', 'SMTP server account username', 0); + +INSERT INTO `config` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('mail', 'MOD_MAIL_smtp_password', '', 'SMTP Password', 'SMTP server account password', 0); diff --git a/modules/mail/mail.inc b/modules/mail/mail.inc new file mode 100644 index 0000000..7979afa --- /dev/null +++ b/modules/mail/mail.inc @@ -0,0 +1,98 @@ +Mailer != 'smtp') { + // From name/address to use + if (empty($OC_configAR['MOD_MAIL_from_name'])) { + $from_name = $OC_configAR['OC_confName']; + } else { + $from_name = $OC_configAR['MOD_MAIL_from_name']; + } + + if (empty($OC_configAR['MOD_MAIL_from_email'])) { + $from_email = $OC_configAR['OC_pcemail']; + } else { + $from_email = $OC_configAR['MOD_MAIL_from_email']; + } + + // $hdr set? + if ( isset($hdr) && ($usehdr > 0) && preg_match("/From: \"?([^\"<]+)\"?\s?<([^>]+)>/", $hdr, $matches) && !empty($matches[1]) && validEmail($matches[2])) { + $reply_name = $matches[1]; + $reply_email = $matches[2]; + if ($usehdr == 2) { + $from_name = $reply_name; + $from_email = $reply_email; + } + } else { + $reply_name = $from_name; + $reply_email = $from_email; + } + + // Setup + $mod_mail->isSMTP(); + $mod_mail->Host = $OC_configAR['MOD_MAIL_smtp_host']; + $mod_mail->Port = $OC_configAR['MOD_MAIL_smtp_port']; + if (!empty($OC_configAR['MOD_MAIL_smtp_username']) && !empty($OC_configAR['MOD_MAIL_smtp_password'])) { + if (!isset($GLOBALS['mod_mail_smtp_password'])) { + $GLOBALS['mod_mail_smtp_password'] = oc_decrypt($OC_configAR['MOD_MAIL_smtp_password']); + } + $mod_mail->SMTPAuth = true; + $mod_mail->Username = $OC_configAR['MOD_MAIL_smtp_username']; + $mod_mail->Password = $GLOBALS['mod_mail_smtp_password']; + } elseif (defined('MOD_MAIL_SMTP_USERNAME') && defined('MOD_MAIL_SMTP_PASSWORD')) { + $mod_mail->SMTPAuth = true; + $mod_mail->Username = MOD_MAIL_SMTP_USERNAME; + $mod_mail->Password = MOD_MAIL_SMTP_PASSWORD; + } else { + $mod_mail->SMTPAuth = false; + } + if ($OC_configAR['MOD_MAIL_smtp_encryption'] != 'none') { + $mod_mail->SMTPSecure = $OC_configAR['MOD_MAIL_smtp_encryption']; + } + $mod_mail->setFrom($from_email, $from_name, ($OC_configAR['MOD_MAIL_return_path'] ? true : false)); + $mod_mail->addReplyTo($reply_email, $reply_name); + $mod_mail->CharSet = 'UTF-8'; + $mod_mail->WordWrap = $OC_configAR['OC_emailWrap']; + if ($GLOBALS['mod_mail_debug']) { + $mod_mail->SMTPDebug = $GLOBALS['mod_mail_debug']; + $mod_mail->Debugoutput = 'html'; + } + $GLOBALS['mod_mail_phpmailer'] = $mod_mail; +} + +// Addresse(es) +if ($to_emails = preg_split("/,/", $to)) { + foreach($to_emails as $address) { + $mod_mail->addAddress($address); + } +} else { + $mod_mail->addAddress($to); +} + +// Subject & Body +$mod_mail->Subject = $subject; +$mod_mail->Body = $body; + +// Send it +if ($mod_mail->send()) { + $mod_mail->clearAddresses(); + return(true); +} else { + $mod_mail->clearAddresses(); + oc_logit('email-smtp', 'SMTP Failure to ' . $to . ' -- ' . $mod_mail->ErrorInfo); + return(false); +} diff --git a/modules/mail/module.inc b/modules/mail/module.inc new file mode 100644 index 0000000..e45e2b6 --- /dev/null +++ b/modules/mail/module.inc @@ -0,0 +1,54 @@ + 'Mail', + 'description' => 'Provides support for using an external SMTP server', + 'version' => '1.0.1', + 'dependencies' => array(), + 'developer' => 'OpenConf' +); + +// PHPMailer plugin directory +if (!defined('MOD_MAIL_PHPMAILER_DIR')) { + define('MOD_MAIL_PHPMAILER_DIR', OCC_PLUGINS_DIR . 'PHPMailer/'); +} + +// PHPMailer loader +$GLOBALS['mod_mail_phpmailer'] = false; +$GLOBALS['mod_mail_debug'] = 0; +if ($OC_configAR['MOD_MAIL_mailer'] == 'smtp') { + if (is_file(MOD_MAIL_PHPMAILER_DIR . 'src/PHPMailer.php')) { // >= 6 + require_once MOD_MAIL_PHPMAILER_DIR . 'src/PHPMailer.php'; + require_once MOD_MAIL_PHPMAILER_DIR . 'src/Exception.php'; + require_once MOD_MAIL_PHPMAILER_DIR . 'src/SMTP.php'; + } elseif (is_file(MOD_MAIL_PHPMAILER_DIR . 'PHPMailer.php')) { // >= 6 (no src/) + require_once MOD_MAIL_PHPMAILER_DIR . 'PHPMailer.php'; + require_once MOD_MAIL_PHPMAILER_DIR . 'Exception.php'; + require_once MOD_MAIL_PHPMAILER_DIR . 'SMTP.php'; + } elseif (is_file(MOD_MAIL_PHPMAILER_DIR . 'PHPMailerAutoload.php')) { // <= 5.2 | comment out use statements above + require_once MOD_MAIL_PHPMAILER_DIR . 'PHPMailerAutoload.php'; + } else { + err('Mail SMTP set, however plugin not found; see Mail module info page for requirements'); + } + $GLOBALS['mod_mail_phpmailer'] = new PHPMailer; +} diff --git a/modules/mail/settings-export-options.inc b/modules/mail/settings-export-options.inc new file mode 100644 index 0000000..feba87f --- /dev/null +++ b/modules/mail/settings-export-options.inc @@ -0,0 +1,16 @@ + +
    +'; diff --git a/modules/mail/settings-export-prep.inc b/modules/mail/settings-export-prep.inc new file mode 100644 index 0000000..595497f --- /dev/null +++ b/modules/mail/settings-export-prep.inc @@ -0,0 +1,15 @@ +Download and install it to the directory plugins/PHPMailer/.'); + exit; +} + +$MOD_MAIL_configVars = array('MOD_MAIL_mailer', 'MOD_MAIL_from_email', 'MOD_MAIL_from_name', 'MOD_MAIL_return_path', 'MOD_MAIL_smtp_host', 'MOD_MAIL_smtp_port', 'MOD_MAIL_smtp_encryption'); + +if (!defined('MOD_MAIL_SMTP_USERNAME')) { + $MOD_MAIL_configVars[] = 'MOD_MAIL_smtp_username'; +} + +$mod_mail_mailerOptions = array( + 'php' => 'PHP mail() function', + 'smtp' => 'SMTP server' +); + +$mod_mail_encryptionOptions = array( + 'none' => 'none', + 'ssl' => 'SSL', + 'tls' => 'TLS' +); + +$mod_mail_returnPathOptions = array( + '1' => 'use From Email', + '0' => 'do not set' +); + +$err = array(); + +// Save settings? +if (isset($_POST['submit']) && ($_POST['submit'] == 'Save Settings')) { + + // Check for valid submission + if (!validToken('chair')) { + warn('Invalid submission'); + } + + // Check input + if (!isset($_POST['MOD_MAIL_mailer']) || !isset($mod_mail_mailerOptions[$_POST['MOD_MAIL_mailer']])) { + $err[] = 'Mailer invalid'; + } elseif (($_POST['MOD_MAIL_mailer'] == 'smtp') && (empty(trim($_POST['MOD_MAIL_smtp_host'])) || empty(trim($_POST['MOD_MAIL_smtp_port'])))) { + $err[] = 'SMTP Host and Port must be filled in when SMTP selected'; + } + if (!empty($_POST['MOD_MAIL_from_email']) && !validEmail(trim($_POST['MOD_MAIL_from_email']))) { + $err[] = 'From Email invalid'; + } + if (!isset($_POST['MOD_MAIL_return_path']) || !isset($mod_mail_returnPathOptions[$_POST['MOD_MAIL_return_path']])) { + $err[] = 'Return Path invalid'; + } + if (!empty($_POST['MOD_MAIL_smtp_port']) && !preg_match("/^\d+$/", $_POST['MOD_MAIL_smtp_port'])) { + $err[] = 'SMTP Port invalid'; + } + if (!isset($_POST['MOD_MAIL_smtp_encryption']) || !isset($mod_mail_encryptionOptions[$_POST['MOD_MAIL_smtp_encryption']])) { + $err[] = 'Encryption invalid'; + } + + if (!empty($err)) { + print '

    Please re-enter your settings, noting the following:

    • ' . implode('
    • ', $err) . '



    '; + } else { + if ( + isset($_POST['MOD_MAIL_smtp_password']) + && ($_POST['MOD_MAIL_smtp_password'] != '***') + && !empty($_POST['MOD_MAIL_smtp_password']) + ) { + $_POST['MOD_MAIL_smtp_password'] = oc_encrypt($_POST['MOD_MAIL_smtp_password']); + $MOD_MAIL_configVars[] = 'MOD_MAIL_smtp_password'; + } + elseif ( + !empty($OC_configAR['MOD_MAIL_smtp_password']) + && + (!isset($_POST['MOD_MAIL_smtp_password']) || ($_POST['MOD_MAIL_smtp_password'] == '')) + ) { + $_POST['MOD_MAIL_smtp_password'] = ''; + $MOD_MAIL_configVars[] = 'MOD_MAIL_smtp_password'; + } + + // Update config settings + updateAllConfigSettings($MOD_MAIL_configVars, $_POST, OCC_MODULE_ID); + + // notify user + print '

    Settings Saved

    '; + } +} else { + foreach ($MOD_MAIL_configVars as $var) { + $_POST[$var] = $OC_configAR[$var]; + } + $_POST['MOD_MAIL_smtp_password'] = $OC_configAR['MOD_MAIL_smtp_password']; +} + +// Show settings +print ' +
    + + + + +
    +Mailer (collapse) +
    + +
    +
    ' . generateRadioOptions('MOD_MAIL_mailer', $mod_mail_mailerOptions, varValue('MOD_MAIL_mailer', $_POST)) . '

    If selecting SMTP server, fill out section below
    +
    + + +
    +
    + + +
    +SMTP Server Options (collapse) +
    + +
    The use of an IP address is recommended
    + +
    + +
    +
    ' . generateRadioOptions('MOD_MAIL_smtp_encryption', $mod_mail_encryptionOptions, varValue('MOD_MAIL_smtp_encryption', $_POST)) . '
    +
    +'; + +if (!defined('MOD_MAIL_SMTP_USERNAME')) { + print ' +
    Leave username and password blank if server does not require authentication
    + +
    If password saved, *** will display above
    '; +} + +print ' + +
    +
    ' . generateRadioOptions('MOD_MAIL_return_path', $mod_mail_returnPathOptions, varValue('MOD_MAIL_return_path', $_POST)) . '
    +
    + +
    Leave blank to use Event/Journal Short Name
    + +
    Leave blank to use Chair Email Address
    + + + +
    +
    + +
    +'; + +if (($OC_configAR['MOD_MAIL_mailer'] == 'php') || (($OC_configAR['MOD_MAIL_mailer'] == 'smtp') && !empty($OC_configAR['MOD_MAIL_smtp_host']))) { + print ' +

    Once settings are saved, test by sending a message

    +

    For troubleshooting assistance, see our email guide. If the SMTP mailer is enabled, also see the PHPMailer wiki.

    +'; +} diff --git a/modules/mail/test.php b/modules/mail/test.php new file mode 100644 index 0000000..42fa9f6 --- /dev/null +++ b/modules/mail/test.php @@ -0,0 +1,50 @@ + + + +Send Test Message + + + + +
    +'; + +if (isset($_POST['submit']) && ($_POST['submit'] == 'Send Message') && isset($_POST['email']) && validEmail($_POST['email'])) { + if (!validToken('chair')) { + print '

    invalid submission

    '; + } else { + $GLOBALS['mod_mail_debug'] = 3; + if (oc_mail($_POST['email'], 'Test Message', 'This is a test message.')) { + print '

    Message sent successfully

    '; + } else { + print '

    Message failed

    '; + } + } + print '
    '; +} + +print ' +
    + +

    Enter an email address to send a test message using the ' . safeHTMLstr($OC_configAR['MOD_MAIL_mailer']) . ' mailer to:

    +

    +

    +
    + + +'; + +?> diff --git a/modules/mail/uninstall-db.sql b/modules/mail/uninstall-db.sql new file mode 100644 index 0000000..64afb3d --- /dev/null +++ b/modules/mail/uninstall-db.sql @@ -0,0 +1,15 @@ +## +----------------------------------------------------------------------+ +## | OpenConf | +## +----------------------------------------------------------------------+ +## | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +## +----------------------------------------------------------------------+ +## | This source file is subject to the OpenConf License, available on | +## | the OpenConf web site: www.OpenConf.com | +## +----------------------------------------------------------------------+ + +## NOTE: This file cannot contain a semi-colon (;) except at the end of a +## SQL statement. + +# -------------------------------------------------------- + +DELETE FROM `config` WHERE `module`='mail'; diff --git a/modules/mail/upgrade/index.html b/modules/mail/upgrade/index.html new file mode 100644 index 0000000..e69de29 diff --git a/modules/mail/upgrade/index.php b/modules/mail/upgrade/index.php new file mode 100644 index 0000000..e69de29 diff --git a/modules/mail/upgrade/upgrade-6.80-6.81.inc b/modules/mail/upgrade/upgrade-6.80-6.81.inc new file mode 100644 index 0000000..8f50ad7 --- /dev/null +++ b/modules/mail/upgrade/upgrade-6.80-6.81.inc @@ -0,0 +1,19 @@ +$l['moduleId'], 'moduleActive'=>$l['moduleActive']); + } else { + $NonOCmoduleAR[] = array('moduleId'=>$l['moduleId'], 'moduleActive'=>$l['moduleActive']); + } +} +$moduleAR = array_merge($moduleAR, $NonOCmoduleAR); // process OC modules first +foreach ($moduleAR as $l) { + $OC_moduleDir = $pfx . 'modules/' . $l['moduleId']; + if ((filetype($OC_moduleDir) == 'dir') && is_file($OC_moduleDir . '/module.inc')) { + require_once $OC_moduleDir . '/module.inc'; + if (($l['moduleActive'] == 1)&&(!preg_match("/^oc_/",$moduleId)||(OCC_LICENSE!='Public'))) { + if (preg_match("/^o"."c_/",$moduleId)&&(!preg_match("/^(\w+) /", OCC_LICENSE_TYPE, $m)|| + !preg_match("/\b" . strtolower($m[1]) . "\b/", $OC_modulesAR[$l['moduleId']]['supported']))) + {continue;}else{$mok=true;} + $OC_activeModulesAR[] = $l['moduleId']; + + if (isset($mok) && $mok && is_file($OC_moduleDir . '/init.inc')) { + require_once $OC_moduleDir . '/init.inc'; + } + } + } +} + +?> diff --git a/modules/modules.php b/modules/modules.php new file mode 100644 index 0000000..68a565f --- /dev/null +++ b/modules/modules.php @@ -0,0 +1,157 @@ + +

    Additional OpenConf functionality is available through modules. In order to use a module, you must first install it, and then activate it. If a module is installed, but not active, its data will still be preserved. Uninstalling a module will result in the module's data being deleted.

    +

    The Module Name link provides access to the module's configuration settings.
    +The Version link provides information about the module.

    +
    + +
    +Status Legend:   + Active +    +o Disabled +    +x Not Installed +
    +
    + + + + + $mAR) { + $moduleNamesAR[$mID] = $mAR['name']; +} +asort($moduleNamesAR); +foreach ($moduleNamesAR as $mID => $mName) { + // is module activate or disabled? + if (in_array($mID,$OC_activeModulesAR)) { + $color = '#0f0'; + $symbol = '•'; + $action = 'deactivate'; + } else { + $color = '#f99'; + $symbol = 'o'; + $action = 'activate'; + } + // Is module configurable? + if (is_file($mID . '/settings.inc')) { + $configURL = 'request.php?module=' . $mID . '&action=settings.inc'; + } else { + $configURL = ''; + } + // Readme? + if (preg_match("/^oc_/",$mID)&&(!preg_match("/^(\w+) /", constant('OCC_LI'.'CENSE_T'.'YPE'), $m)|| + !preg_match("/\b" . strtolower($m[1]) . "\b/", $OC_modulesAR[$mID]['sup'.'ported']))){continue;} + if (is_file($mID . '/README.html')) { + $version = '' . safeHTMLstr($OC_modulesAR[$mID]['version']) . ''; + } else { + $version = safeHTMLstr($OC_modulesAR[$mID]['version']); + } + print '' : ('config')) . ''; + $row = $rowAR[$row]; +} + +// Get uninstalled modules +$uninstalledModulesAR = array(); +if ($dh = opendir('./')) { + while (($dir = readdir($dh)) !== false) { + if ((filetype($dir) == 'dir') && !preg_match("/[\.\/]/",$dir) && is_file($dir . '/module.inc') && !oc_module_installed($dir) && oc_moduleValid($dir) && !in_array($dir, $deprecatedModuleAR)) { + require_once $dir . '/module.inc'; + if (preg_match("/^oc_/",$dir)&&(!preg_match("/^(\w+) /", OCC_LICENSE_TYPE, $m)|| + !preg_match("/\b" . strtolower($m[1]) . "\b/", $OC_modulesAR[$dir]['supported']))) + {unset($OC_modulesAR[$dir]);}else{$uninstalledModulesAR[] = $dir;} + } + } +} +// Show a break between uninstalled modules +if (!empty($moduleNamesAR) && !empty($uninstalledModulesAR)) { + print ''; +} +// Sort & display uninstalled modules +$moduleNamesAR = array(); +foreach ($uninstalledModulesAR as $mID) { + if ((OCC_LICENSE != 'Public') || !preg_match("/^oc_/", $mID)) { + $moduleNamesAR[$mID] = $OC_modulesAR[$mID]['name']; + } +} +uasort($moduleNamesAR, 'strcasecmp'); +$color = '#f33'; +$symbol = 'x'; +foreach ($moduleNamesAR as $mID => $mName) { + // Readme? + if (is_file($mID . '/README.html')) { + $version = '' . safeHTMLstr($OC_modulesAR[$mID]['version']) . ''; + } else { + $version = safeHTMLstr($OC_modulesAR[$mID]['version']); + } + print ''; + $row = $rowAR[$row]; +} + +$plusModulesAR = array( + 'Acceptance' => 'Provides Chair with the ability to change acceptance options', + 'Advocate Assign' => 'Allows advocates to assign reviews', + 'Bidding' => 'Bidding on papers by reviewers, and bid-based assignments', + 'Discussion' => 'Online discussion (forum) for committee members', + 'Proceedings' => 'Online proceedings', + 'Rebuttal' => 'Author rebuttal of reviews, and reviewer rebuttal of author comments', + 'Reviewer Upload' => 'Reviewer file upload for assigned reviews (e.g., annotation, feedback)' +); +$proModulesAR = array( + 'Auto Assign' => 'Automatically assigns reviewers/advocate when a submission is made', + 'Custom Forms' => 'Customize submission, review, and committee profile forms', + 'Copyright-ACM' => 'Provides export of submissions in ACM ICPS CSV format', + 'Copyright-IEEE' => 'Provides author referral form to IEEE\'s electronic copyright system', + 'MultiFile' => 'Multiple file type uploads', + 'ORCID' => 'Provides review credit to committee members via ORCID service', + 'Plagiarism-Docoloc' => 'Docoloc plagiarism checking service', + 'Plagiarism-iThenticate' => 'CrossCheck and iThenticate plagiarism checking services', + 'Program' => 'Online and mobile program building and display options', + 'Sub. Pre-Payment' => 'Require payment for making a submission' +); +if (OCC_LICENSE == 'Public') { + $otherModulesAR = array_merge($plusModulesAR, $proModulesAR); +} elseif (defined('OCC_LICENSE_TYPE') && preg_match("/Plus/", OCC_LICENSE_TYPE)) { + $otherModulesAR = $proModulesAR; +} else { + $otherModulesAR = array(); +} +if (count($otherModulesAR) > 0) { + ksort($otherModulesAR); + print ''; + foreach ($otherModulesAR as $k=>$v) { + print ''; + } +} + +?> +
     Module NameVersionSourceDescriptionAction
    ' . $symbol . '' . (empty($configURL) ? safeHTMLstr($OC_modulesAR[$mID]['name']) : ('' . safeHTMLstr($OC_modulesAR[$mID]['name']) . '')) . '' . $version . '' . (($OC_modulesAR[$mID]['developer'] == 'OpenConf') ? 'OpenConf' : 'Third-Party') . '' . safeHTMLstr($OC_modulesAR[$mID]['description']) . '' . (empty($configURL) ? '' . $action . 'uninstall
    ' . $symbol . '' . safeHTMLstr($OC_modulesAR[$mID]['name']) . '' . $version . '' . (($OC_modulesAR[$mID]['developer'] == 'OpenConf') ? 'OpenConf' : 'Third-Party') . '' . safeHTMLstr($OC_modulesAR[$mID]['description']) . '  install
    ' . $symbol . '' . safeHTMLstr($k) . ' OpenConf' . safeHTMLstr($v) . 'upgrade for access
    +

    + + diff --git a/modules/readme.php b/modules/readme.php new file mode 100644 index 0000000..73ddf10 --- /dev/null +++ b/modules/readme.php @@ -0,0 +1,28 @@ + +'; + } else { + print $readme; + } +} else { + print 'Unable to access module information'; +} + +?> \ No newline at end of file diff --git a/modules/request.php b/modules/request.php new file mode 100644 index 0000000..4c2b121 --- /dev/null +++ b/modules/request.php @@ -0,0 +1,82 @@ +Modules » '; + printHeader($OC_modulesAR[OCC_MODULE_ID]['name'] . " Settings",1); + require_once OCC_MODULE_ID . '/settings.inc'; + printFooter(); + exit; +} +// Is action extension valid +elseif (preg_match("/\.(?:inc|sql)$/",$_REQUEST['action'])) { + err('Request for module action is not permitted','Error'); +} +// Is module active +elseif (!in_array($_REQUEST['module'],$OC_activeModulesAR)) { + err('Module is not active','Error'); +} +// OK already +else { + define('OCC_MODULE_ID', $_REQUEST['module']); + // Friendly URL? If so, decipher params + if ((OCC_LICENSE=='P'.'ublic') && preg_match("/^oc_/",$_REQUEST['module'])){exit;} + if (isset($_GET['ocparams']) && !empty($_GET['ocparams'])) { + $params = ''; + if (preg_match_all("/(\w+)--(\w+)_-/", $_GET['ocparams'], $matches)) { + foreach ($matches[1] as $idx => $m) { + if (($m != 'module') && ($m != 'action') && preg_match("/^[\w-]+$/", $m)) { + $params .= '&' . $m . '=' . urlencode($matches[2][$idx]); + $_GET[$m] = $matches[2][$idx]; + } + } + } + unset($_GET['ocparams']); + define('OCC_SELF', $_SERVER['PHP_SELF'] . '?module=' . $_REQUEST['module'] . '&action=' . $_GET['action'] . $params); + } elseif (isset($_SERVER['REQUEST_URI']) && strstr($_SERVER['REQUEST_URI'], '?')) { + define('OCC_SELF', htmlspecialchars($_SERVER['REQUEST_URI'])); + } elseif (isset($_SERVER['QUERY_STRING']) && strstr($_SERVER['QUERY_STRING'], '&')) { + define('OCC_SELF', $_SERVER['PHP_SELF'] . '?' . htmlspecialchars($_SERVER['QUERY_STRING'])); + } else { + err('This server does not support REQUEST_URI or QUERY_STRING','Error'); + } + define('OCC_MODULE_REQUEST_BASE', $_SERVER['PHP_SELF'] . '?module=' . $_REQUEST['module']); + require_once OCC_MODULE_ID . '/' . $_REQUEST['action']; + exit; +} + +exit; + +?> diff --git a/modules/uninstall.php b/modules/uninstall.php new file mode 100644 index 0000000..1962351 --- /dev/null +++ b/modules/uninstall.php @@ -0,0 +1,51 @@ + diff --git a/openconf-rtl.css b/openconf-rtl.css new file mode 100644 index 0000000..66f7b1b --- /dev/null +++ b/openconf-rtl.css @@ -0,0 +1,17 @@ +/* +----------------------------------------------------------------------+ */ +/* | OpenConf | */ +/* +----------------------------------------------------------------------+ */ +/* | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | */ +/* +----------------------------------------------------------------------+ */ +/* | This source file is subject to the OpenConf License, available on | */ +/* | the OpenConf web site: www.OpenConf.com | */ +/* +----------------------------------------------------------------------+ */ + +.menuitem { float: right; } +.menufiller { text-align: left; } +.linfo { float: left; } +.ocform label { float: right; margin-right: 0; margin-left: 1em; text-align: left; } +.ocform label.plain { text-align: right; } +.ocform fieldset.radio label, .ocform fieldset.checkbox label { margin-left: 0; } +.ocform fieldset div.fieldnote { margin-left: 0; margin-right: 13.6em; } +.oclanguage { float: left; } diff --git a/openconf.css b/openconf.css new file mode 100644 index 0000000..963e5ad --- /dev/null +++ b/openconf.css @@ -0,0 +1,131 @@ +/* +----------------------------------------------------------------------+ */ +/* | OpenConf | */ +/* +----------------------------------------------------------------------+ */ +/* | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | */ +/* +----------------------------------------------------------------------+ */ +/* | This source file is subject to the OpenConf License, available on | */ +/* | the OpenConf web site: www.OpenConf.com | */ +/* +----------------------------------------------------------------------+ */ + + +BODY { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; background-color: #fff; color: #000; margin: 0; } +TD { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } +TH { font-family: verdana,arial,helvetica,sans-serif; font-weight: bold; font-size: 10pt; } +A { text-decoration: none; color: #0000ff; } +A:link { color: #0000ff; } +A:visited { color: #0000ff; } +A:hover { color: #ff0000; } +A.confName:link { color: #000000; } +A.confName:visited { color: #000000; } +A.confName:hover { color: #666666; } +A.confName img { max-width: 100%; } +em { font-style: italic; } +strong { font-weight: bold; } +h1 { font-family: arial,helvetica,sans-serif; font-size: 1.2em; font-weight: bold; text-align: center; } + +.mainbody { margin-left: 30px; margin-right: 30px; } +.conf { font-family: arial,helvetica,sans-serif; font-size: 14pt; font-weight: bold; margin-top: 10px; margin-left: 10px; margin-right: 10px;margin-bottom: 10px; } +.header { font-family: arial,helvetica,sans-serif; font-size: 12pt; font-weight: bold; text-align: center; } +.HEADER2 { font-family: arial,helvetica,sans-serif; font-size: 12pt; font-weight: bold; } +.chairHeader { font-weight: bold; margin: 0.5em 0; } +.footerBorder { border-top: 1px solid black; border-bottom: 1px solid black; background-color: #99ccff; font-size: 9pt; font-family: arial, helvetica, sans-serif; padding: 3px; } +.menu { background-color: #99ccff; border-bottom: 1px solid black; width: 100%; clear: both; } +.menuoc { font-family: verdana,helvetica,sans-serif; font-size: 9pt; border-top: 1px solid black; border-bottom: 1px solid black; padding-top: 0.3em; padding-bottom: 0.3em; width: 100%; background-color: #99ccff; color: #000033; clear: both; } +.menufiller { background-color: #99ccff; padding-top: 0.3em; padding-bottom: 0.3em; font-size: 9pt; text-align: right; } +.menuitem { background-color: #eeeeee; border-right: 1px solid black; font-weight: bold; font-size: 9pt; float: left; padding: 0.3em; } +.linkHighlight { font-weight: bold; } +.cat { font-weight: bold; font-size: 10pt; } +.note { font-size: 9pt; font-weight: normal; font-style: italic; color: #006600; } +.note2 { font-weight: bold; color: #006600; } +.note3 { font-weight: bold; color: #800080; font-size: 9pt; font-style: italic; } +.item { font-weight: bold; } +.item2 { font-weight: bold; background-color: #eeeeee; } +.box { border: solid; border-color: black; border-width: 1px; } +.sep { background-color: #cccccc; } +.err { color: #990000; font-weight: bold; } +.warn { color: #800080; font-weight: bold; } +.rowheader { background-color: #ccdddd; } +.row1 { background-color: #eeeeee; } +.row2 { background-color: #dddddd; } +.rowselect:hover { background-color: #fc9; } +.linfo { float: right; text-align: center; padding-top: 0; } +.del { background-color: #ccccff; } +.sel { background-color: #cdd; } + +#processing { font-weight: bold; font-size: 120%; } +#tracks li { margin-bottom: 0.5em; } + +.popup { position: relative; } +.popup a { text-decoration: none; color: #000; background-color: inherit; } +.popup a:hover { text-indent: 0; background-color: #eee; } +.popup a span { display: none; } +.popup a:hover span { display:block; text-align: left; font-weight: normal; font-size: 0.9em; color: #000; position:absolute; top: 1em; left: 6em; z-index: 100; background-color: #F7EFC1; border: 2px solid #cc9; padding:5px; text-decoration: none; white-space: pre;} + + +.ocform fieldset { padding: 10px; border:1px solid #ddd; margin-bottom: 2em; background-color: #fafafa; } +.ocform fieldset fieldset { background-color: #f5f5f5; } +.ocform label { float: left; width: 12em; margin-right: 1em; text-align: right; color: #333; background-color: inherit; } +.ocform label.plain { float: none; width: auto; margin: auto; text-align: left; display: block; } +.ocform legend { color: #47f; font-size: 1.1em; } +.ocform legend span { font-size: 0.8em; color: #555; } +.ocform legend span { cursor: pointer; } +.ocform div.field { margin: 0.5em 0; clear: both; } +.ocform input, .ocform textarea, .ocform select { background-color: #fff; border: 1px solid #ccc; } +.ocform fieldset.radio, .ocform fieldset.checkbox { border: 0; margin-bottom: 0; padding: 0; background-color: #fafafa; } +.ocform fieldset.radio label, .ocform fieldset.checkbox label { float: none; margin-right: 0; width: auto; color: #000; background-color: inherit; } +.ocform fieldset.radio input, .ocform fieldset.checkbox input { background-color: #fafafa; border: none; } +.ocform fieldset div.fieldnote { margin-left: 14.6em; } +.ocform fieldset div.fieldsetnote { margin-bottom: 1em; } +.submit, .ocform .submit { border:1px solid #ccc; background-color: #9cf; color: inherit; padding: 5px; border-radius:0.4em; } +.submit:hover, .ocform .submit:hover { background-color: #ddd; cursor:pointer; } +.submit:disabled, .ocform .submit:hover, .submit:disabled:hover, .ocform .submit:disabled:hover { background-color: #eee; } +.ocform #addauthor a { text-decoration: underline; } +.ocform #fs_authors fieldset fieldset.radio { background-color: #f5f5f5; } + +.occonfigform label { width: 14em; font-weight: bold; color: #555; } +.occonfigform .subfieldset { margin-left: 15.0em; } +.occonfigform fieldset div.fieldnote { margin-left: 16.6em; } +.occonfigform div.field { margin: 0.5em 0 1em 0; } +.occonfigform fieldset.radio label, .ocform fieldset.checkbox label { font-weight: normal; color: #000; } +.occonfigform .submit { background-color: #9cf; color: inherit; padding: 2px; border-radius:0.4em; display: block; clear: left; } +.occonfigform .submit:disabled { background-color: #eee; } +.occonfigform fieldset legend { cursor: pointer; } + +.ocstatusform label { width: 14em; color: #555; background-color: inherit; font-weight: bold; } +.ocstatusform fieldset fieldset label { color: #000; background-color: inherit; font-weight: normal; } +.ocstatusform fieldset div.fieldnote { margin-left: 17em; } +.ocstatusform fieldset div.event { margin-left: 26em; color: #555; } +.ocstatusform div.field { margin: 0.5em 0 1em 0; } +.ocstatusform .submit { background-color: #9cf; color: inherit; padding: 2px; border-radius:0.4em; display: block; clear: left; } +.ocstatusform .submit:disabled { background-color: #eee; } + +.ocreviewform label { float: none; width: auto; margin: auto; text-align: left; display: block; font-weight: bold; } +.ocreviewform fieldset.radio label, .ocform fieldset.checkbox label { float: none; margin-right: 0; width: auto; color: #000; background-color: inherit; font-weight: normal; display: inline; } +.ocreviewform fieldset.radio label { font-weight: normal; } +.ocreviewform input, .ocreviewform textarea, .ocreviewform select { margin-left: 10px; } +.ocreviewform fieldset div.fieldnote { margin: 0.5em 0 0 10px; } +.ocreviewform div.field { margin-bottom: 2.5em; } + +.ocsubauthorutil span { font-size: 0.9em; margin-right: 20px; color: #00f;} +.ocsubauthorutil span:hover { cursor: pointer; } + +table.ocfields { border: none; padding: 0; margin: 0; } +table.ocfields th { width: 10em; text-align: right; color: #36f; vertical-align: top; padding: 0 7px 6px 0; font-weight: normal; } +table.ocfields td { vertical-align: top; padding: 0px 0px 6px 0px; } +table.ocfields table.ocfields th { width: auto; text-align: left; } +table.rowhighlight tbody tr:hover { background-color: #def; } + +.oclanguage { float: right; } +.oclanguage img { vertical-align: text-bottom; } +.oclanguage select { background-color: #eee; color: inherit; } + +.ocskip a { position:absolute; left:-10000px; top:auto; width:1px; height:1px; overflow:hidden; } +.ocskip a:focus { position:static; width:auto; height:auto; } + +.ocprivacy { margin-top: 1em; text-align: center; } + +#oc_submit_emailConfirmInner { display: none; } +#oc_submit_emailConfirm { margin: 1em 0 1.5em 30px; font-size: 1.2em; color: #000; font-weight: bold; } + +/* DO NOT CHANGE OR HIDE */#powered {text-align: center;font-size: 9pt;font-family: arial, helvetica, sans-serif;padding: 3px;color: #000;background-color: inherit;margin-bottom: 20px;}/* DO NOT CHANGE OR HIDE */ + diff --git a/openconf.js b/openconf.js new file mode 100644 index 0000000..a0cd81d --- /dev/null +++ b/openconf.js @@ -0,0 +1,180 @@ +// +----------------------------------------------------------------------+ +// | OpenConf | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2002-2020 Zakon Group LLC. All Rights Reserved. | +// +----------------------------------------------------------------------+ +// | This source file is subject to the OpenConf License, available on | +// | the OpenConf web site: www.OpenConf.com | +// +----------------------------------------------------------------------+ + +var oc_transAR = new Array(); // Translation strings + +// oc_sprintf - sprintf handler +String.prototype.oc_sprintf = function() { + var args = arguments; + return this.replace(/\%(\d+)\$\w/g, function(match, number) { + n = number - 1; + return typeof args[n] != 'undefined' + ? args[n] + : '{' + number + '}' + ; + }); +}; + +// popup - displays an informational blurb +var popupObj; +function popup(fldId) { + if (document.getElementById) { + var field; + if (popupObj) { popupObj.close(); } + if (field = document.getElementById(fldId)) { + popupObj = window.open('','info','width=300,height=300,menubar=no,location=no,resizable=yes,scrollbars=yes,status=no'); + popupObj.document.write('Click to Close
    ' + field.innerHTML + '
    '); + popupObj.focus(); + } + } +} + +// oc_checkWordNum - checks textarea field length for # of words +// Note: oc_transAR must be set globally prior to calling +function oc_checkWordNum(fieldID, fieldName, max, min) { + min = typeof min !== 'undefined' ? parseInt(min) : 0; + max = typeof max !== 'undefined' ? parseInt(max) : 0; + var msg = '%1$s field contains %2$d words; limit is %3$s words.'; + var fieldObj = document.getElementById(fieldID); + var oc_fieldContent = fieldObj.value.replace(/^\s\s*/, "").replace(/\s\s*$/, "").replace(/\s+/g, " "); + var oc_fieldLength = 0; + if ( (oc_fieldContent != "") && (oc_fieldContent != " ") ) { + oc_fieldLength = oc_fieldContent.split(" ").length; + } + if ( ( (max > 0) && (oc_fieldLength > max) ) || ( (min > 0) && (oc_fieldLength < min) ) ) { + var limit = ''; + if (min > 0) { + limit = min; + if (max > 0) { + if (min != max) { + limit = limit + '-' + max; + } + } else { + limit = limit + '+'; + } + } else { + limit = max; + } + alert(oc_transAR[msg].oc_sprintf(fieldName, oc_fieldLength, limit)); + window.setTimeout( function () { fieldObj.focus(); }, 0 ); + } +} + +// oc_checkCharNum - checks text field length for # of characters +// Note: oc_transAR must be set globally prior to calling +function oc_checkCharNum(fieldID, fieldName, max, min) { + min = typeof min !== 'undefined' ? parseInt(min) : 0; + max = typeof max !== 'undefined' ? parseInt(max) : 0; + var msg = '%1$s field contains %2$d characters; limit is %3$s characters.'; + var fieldObj = document.getElementById(fieldID); + var oc_fieldContent = fieldObj.value.replace(/^\s\s*/, "").replace(/\s\s*$/, "").replace(/\s+/g, " "); + var oc_fieldLength = 0; + if ( (oc_fieldContent != "") && (oc_fieldContent != " ") ) { + oc_fieldLength = oc_fieldContent.length; + } + if ( ( (max > 0) && (oc_fieldLength > max) ) || ( (min > 0) && (oc_fieldLength < min) ) ) { + if (min > 0) { + limit = min; + if (max > 0) { + if (min != max) { + limit = limit + '-' + max; + } + } else { + limit = limit + '+'; + } + } else { + limit = max; + } + alert(oc_transAR[msg].oc_sprintf(fieldName, oc_fieldLength, limit)); + window.setTimeout( function () { fieldObj.focus(); }, 0 ); + }} + function oc_checkB() { var oc_b=document.getElementById("powe"+"red"); if (!oc_b||((oc_b.currentStyle ? oc_b.currentStyle.display : getComputedStyle(oc_b, null).display)==='none')||((oc_b.currentStyle ? oc_b.currentStyle.visibility : getComputedStyle(oc_b, null).visibility)==='hidden')){document.body.style.display='none';} +} + +// hide submit button and show processing notice +function oc_processingForm() { + document.getElementById("submit").style.visibility="hidden"; + document.getElementById("processing").style.visibility="visible"; +} + +// add form processing notice event listener +function oc_setupProcessingForm(formName) { + if (document.addEventListener) { + document.getElementById(formName).addEventListener("submit", oc_processingForm); + } else { // IE < 9 support + document.getElementById(formName).attachEvent("onsubmit", oc_processingForm); + } +} + +// toggle fieldset display +function oc_fsToggle(oc_legend) { + var oc_fsdiv = document.getElementById(oc_legend.parentNode.id + '_div'); + if (oc_fsdiv.style.display == 'none') { + oc_fsdiv.style.display = 'block'; + oc_legend.childNodes[1].firstChild.nodeValue = '(collapse)'; + oc_fsdiv.parentNode.scrollIntoView(); + } else { + oc_fsdiv.style.display = 'none'; + oc_legend.childNodes[1].firstChild.nodeValue = '(expand)'; + } +} + +// collapse/expand all fieldsets (w=0/collapse, w=1/expand) +function oc_fsCollapseExpand(w) { + var oc_legends = document.getElementsByTagName('legend'); + for (var i=0; i + + +'; + if ($cssFix) { + print ' + +'; + } + } +} + + +// Setup CK +if (is_file(OCC_PLUGINS_DIR . 'ckeditor/ckeditor.js')) { + oc_addHeader(''); + $OC_ckConfig = '../ckeditor_local_openconf.js'; +} else { + oc_addHeader(''); + $OC_ckConfig = OCC_BASE_URL . 'plugins/ckeditor_cdn_openconf.js'; +} diff --git a/plugins/ckeditor_cdn_openconf.js b/plugins/ckeditor_cdn_openconf.js new file mode 100644 index 0000000..91174f0 --- /dev/null +++ b/plugins/ckeditor_cdn_openconf.js @@ -0,0 +1,32 @@ +// CKEditor default config for OpenConf + +CKEDITOR.editorConfig = function( config ) { + config.toolbar = [ + { name: 'document', items: [ 'Source' ] }, + { name: 'clipboard', items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] }, + { name: 'editing', items: [ 'Find', 'Replace' ] }, + { name: 'basicstyles', items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] }, + { name: 'paragraph', items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight' ] }, + { name: 'links', items: [ 'Link', 'Unlink' ] }, + { name: 'insert', items: [ 'Image', 'Table', 'HorizontalRule', 'SpecialChar' ] }, + { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] }, + { name: 'colors', items: [ 'TextColor', 'BGColor' ] }, + { name: 'tools', items: [ 'Maximize' ] }, + { name: 'about', items: [ 'About' ] } + ]; +}; + +CKEDITOR.on( 'instanceReady', function( ev ) + { + var tags = ['p', 'ol', 'ul', 'li', 'h1', 'h2', 'h3', 'h4', 'h5']; + for (var key in tags) { + ev.editor.dataProcessor.writer.setRules(tags[key], + { + indent : false, + breakBeforeOpen : true, + breakAfterOpen : false, + breakBeforeClose : false, + breakAfterClose : true + }); + } + }); diff --git a/plugins/ckeditor_local_openconf.js b/plugins/ckeditor_local_openconf.js new file mode 100644 index 0000000..4458823 --- /dev/null +++ b/plugins/ckeditor_local_openconf.js @@ -0,0 +1,32 @@ +// CKEditor default config for OpenConf + +CKEDITOR.editorConfig = function( config ) { + config.toolbar = "OPENCONF"; + config.removePlugins = 'elementspath'; + config.toolbar_OPENCONF = [ + { name: 'basicstyles', items : [ 'Bold','Italic','Underline','Subscript','Superscript' ] }, + { name: 'paragraph', items : [ 'NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote' ] }, + { name: 'styles', items : [ 'Styles','Format','Font','FontSize'] }, + { name: 'colors', items : [ 'TextColor','BGColor' ] }, + { name: 'clipboard', items : [ 'Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] }, + { name: 'editing', items : [ 'Find','SelectAll','SpellChecker' ] }, + { name: 'insert', items : [ 'Image','Table','HorizontalRule','SpecialChar' ] }, + { name: 'links', items : [ 'Link','Unlink','Anchor' ] }, + { name: 'document', items : [ 'Source' ] } + ]; +}; + +CKEDITOR.on( 'instanceReady', function( ev ) + { + var tags = ['p', 'ol', 'ul', 'li', 'h1', 'h2', 'h3', 'h4', 'h5']; + for (var key in tags) { + ev.editor.dataProcessor.writer.setRules(tags[key], + { + indent : false, + breakBeforeOpen : true, + breakAfterOpen : false, + breakBeforeClose : false, + breakAfterClose : true + }); + } + }); diff --git a/plugins/index.html b/plugins/index.html new file mode 100644 index 0000000..e69de29 diff --git a/plugins/index.php b/plugins/index.php new file mode 100644 index 0000000..e69de29 diff --git a/plugins/privacy_banner.inc b/plugins/privacy_banner.inc new file mode 100644 index 0000000..59c3a85 --- /dev/null +++ b/plugins/privacy_banner.inc @@ -0,0 +1,93 @@ + 0) { + if (!isset($oc_bannerAR['link']) || empty($oc_bannerAR['link'])) { + $oc_bannerAR['link'] = oc_('Privacy Policy'); + } + if (!isset($oc_bannerAR['href']) || empty($oc_bannerAR['href'])) { + $oc_bannerAR['href'] = OCC_BASE_URL . 'privacy_policy.php'; + } + } + $oc_useBannerAR = array( + 'palette' => array( + 'popup' => array( + 'background' => $oc_banner_popupBG, + 'text' => '#ffffff' + ), + 'button' => array( + 'background' => $oc_banner_buttonBG, + 'text' => '#000000' + ), + 'highlight' => array( + 'background' => '#cccccc' + ) + ), + 'content' => array( + 'message' => safeHTMLstr(oc_($oc_bannerAR['message'])), + 'dismiss' => safeHTMLstr(oc_($oc_bannerAR['dismiss'])) + ), + 'cookie' => array( + 'name' => OCC_SESSION_VAR_NAME . '_cookieconsent', + 'path' => $GLOBALS['OC_basepath'], + //'domain' => '', + 'expiryDays' => 365 + ) + ); + if (!empty($oc_bannerAR['link'])) { + $oc_useBannerAR['content']['link'] = oc_($oc_bannerAR['link']); + } else { + $oc_useBannerAR['showLink'] = false; + } + if (!empty($oc_bannerAR['href'])) { + $oc_useBannerAR['content']['href'] = $oc_bannerAR['href']; + } + + // Select where to serve banner code from -- local plugins dir or CDN + if (is_file($oc_cookieConsentJS)) { + print ' + + +'; + } else { // use CDN + print ' + + +'; + } + + // Banner options + print ' + + +'; + + // Ignored, for translation purposes only + if (false) { + //T: Leave as X - it indicates closing the privacy banner box + $ocIgnore = oc_('X'); + $ocIgnore = oc_('This website uses cookies to provide essential services only.'); + } + +} diff --git a/privacy_policy.php b/privacy_policy.php new file mode 100644 index 0000000..212d21a --- /dev/null +++ b/privacy_policy.php @@ -0,0 +1,38 @@ +' . oc_('This feature is currently disabled') . '

    '; + printFooter(); +} + +?> \ No newline at end of file diff --git a/review/advocate.inc b/review/advocate.inc new file mode 100644 index 0000000..05d5387 --- /dev/null +++ b/review/advocate.inc @@ -0,0 +1,107 @@ + 0) { + while ($topl = ocsql_fetch_assoc($topr)) { + $topicAR[$topl['topicid']] = $topl['topicname']; + } +} + +// Hooks +if (oc_hookSet('committee-advocate-preinc')) { + foreach ($GLOBALS['OC_hooksAR']['committee-advocate-preinc'] as $v) { + require_once $v; + } +} + +if (!isset($mod_oc_customforms_customAdvForm) || (!$mod_oc_customforms_customAdvForm)) { // skip if we have a custom form + + $OC_advocateQuestionsAR = array( + 'adv_recommendation' => array( + 'name' => oc_('Recommendation'), + 'short' => oc_('Recommendation'), + 'note' => '', + 'type' => 'radio', + 'display' => 'newline', + 'required' => false, + 'longlabel' => true, + 'usekey' => false, + 'values' => $accValues + ), + + 'adv_comments' => array( + 'name' => oc_('Committee Comments'), + 'short' => oc_('Committee Comments'), + 'note' => oc_('Reasons must be included for all submissions, because they help us determine what to do when reviewers disagree with each other.'), + 'longlabel' => true, + 'type' => 'textarea' + ) + + ); + + // Set up fieldset + $OC_advocateQuestionsFieldsetAR = array( + 'fs_advocate' => array( + 'fieldset' => '', + 'note' => '', + 'fields' => array_keys($OC_advocateQuestionsAR) + ) + ); + +} // if ! custom form + + +if (oc_hookSet('committee-advocate-inc')) { + foreach ($GLOBALS['OC_hooksAR']['committee-advocate-inc'] as $v) { + require_once $v; + } +} + +// Make updates if not customforms edit +if (! isset($mod_oc_customforms_edit) || ! $mod_oc_customforms_edit) { + // Update valuetypes + foreach ($OC_advocateQuestionsAR as $sfk => $sf) { + if (isset($sf['valuetype']) && !empty($sf['valuetype']) && ($sf['valuetype'] != 'custom')) { + switch($sf['valuetype']) { + case 'country': + require_once OCC_COUNTRY_FILE; + $OC_advocateQuestionsAR[$sfk]['values'] = $GLOBALS['OC_countryAR']; + break; + + case 'topic': + $OC_advocateQuestionsAR[$sfk]['values'] = $topicAR; + break; + + default: // lib file + require_once OCC_LIB_DIR . $sf['valuetype'] . '.inc'; + $OC_advocateQuestionsAR[$sfk]['values'] = $GLOBALS['OC_' . $sf['valuetype'] . 'AR']; + break; + } + } + } +} diff --git a/review/advocate.php b/review/advocate.php new file mode 100644 index 0000000..3234a40 --- /dev/null +++ b/review/advocate.php @@ -0,0 +1,185 @@ +' . safeHTMLstr($subinfo['title']) . '
    ' . oc_('Submission ID') . ': ' . $pid; + + if (isset($subinfo['type']) && !empty($subinfo['type'])) { + print '
    (' . safeHTMLstr($subinfo['type']) . ')
    '; + } + + print ' +
    + + + + +'; + + if (oc_hookSet('committee-advocate-fields')) { + foreach ($GLOBALS['OC_hooksAR']['committee-advocate-fields'] as $v) { + require_once $v; + } + } + + oc_displayFieldSet($GLOBALS['OC_advocateQuestionsFieldsetAR'], $GLOBALS['OC_advocateQuestionsAR'], $recommendation); + + if (oc_hookSet('committee-advocate-extra')) { + foreach ($GLOBALS['OC_hooksAR']['committee-advocate-extra'] as $v) { + require_once $v; + } + } + + print ' + + +'; + + // Display Reviews + print '

    Reviews

    '; + if ($emailList = getPaperReviewersEmail($pid)) { // email reviewers link + print '

    (' . oc_('Email Reviewers') . ')

    '; + } + + $q = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.*, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) as `name`, `" . OCC_TABLE_REVIEWER . "`.`email` FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`='" . safeSQLstr($pid) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid` ORDER BY `score`, `reviewerid`"; + $r = ocsql_query($q) or err("Unable to get information"); + if (ocsql_num_rows($r)==0) { + print '

    ' . oc_('No reviews found') . ' (2)

    '; + } else { + displayReviews($pid, $r, $subinfo['type']); + } +} + +// submission? +if (isset($_POST['ocaction']) && ($_POST['ocaction'] == "Submit Recommendation")) { + // Check for valid submission + if (!validToken('ac')) { + $w = sprintf(oc_('This submission failed our security check, possibly due to you have signed in again, or a third-party having redirected you here. Below is the information provided. If you were attempting to submit a review, print this information out or copy/paste it to a new document so it can be re-entered; then try again. If the problem persists, please contact the Chair.'), ($_SERVER['PHP_SELF'] . '?pid=' . (is_numeric($_POST['pid']) ? $_POST['pid'] : ''))) . '
    '; + $OC_advocateQuestionsARkeys = array_keys($OC_advocateQuestionsAR); + foreach ($_POST as $k => $v) { + if (($k == 'submit') || ($k == 'token')) { continue; } + if (in_array($k, $OC_advocateQuestionsARkeys)) { + $w .= "
    \n

    \n" . safeHTMLstr($OC_advocateQuestionsAR[$k]['short']) . " "; + if ($OC_advocateQuestionsAR[$k]['usekey']) { + $w .= $OC_advocateQuestionsAR[$k]['values'][$v]; + } else { + $w .= safeHTMLstr($v); + } + } else { + $w .= "
    \n

    \n" . safeHTMLstr($k) . ": " . safeHTMLstr($v); + } + } + $w .= '
    '; + warn($w); + } + + // Validate fields + $qfields = array(); + $err = ''; + foreach ($GLOBALS['OC_advocateQuestionsFieldsetAR'] as $fsid => $fs) { + foreach ($fs['fields'] as $fid) { + oc_validateField($fid, $GLOBALS['OC_advocateQuestionsAR'], $qfields, $err); + } + } + + // Hooks + if (oc_hookSet('committee-advocate-validate')) { + foreach ($GLOBALS['OC_hooksAR']['committee-advocate-validate'] as $v) { + require_once $v; + } + } + + // Error? + if (!empty($err)) { + print '
    ' . oc_('Please check the following:') . '
      ' . $err . '

    '; + printAdvocateForm($_POST, $pid, $subinfo); + return; + } + + // Compose sql and update + $q = "UPDATE `" . OCC_TABLE_PAPERADVOCATE . "` SET "; + foreach ($qfields as $qid => $qval) { + $q .= "`" . $qid . "`=" . $qval . ","; + } + $q = rtrim($q, ','); + $q .= " WHERE `paperid`='" . safeSQLstr($pid) . "' AND `advocateid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "'"; + ocsql_query($q) or err("Unable to submit recommendation"); + + + if (oc_hookSet('committee-advocate-save')) { + foreach ($GLOBALS['OC_hooksAR']['committee-advocate-save'] as $v) { + require_once $v; + } + } + + + print '

    ' . oc_('Recommendation has been submitted.') . '

    '; + print '

    » ' . oc_('Return to Recommendation') . '

    '; + //T: Member = Committee Member -- see "Member Home" string + print '

    » ' . sprintf('Return to Member home page', 'reviewer.php') . '

    '; + printFooter(); + exit; +} + + +// Retrieve advocate recommendation +$advq = "SELECT * FROM `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `paperid`='" . safeSQLstr($pid) . "' AND `advocateid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "'"; +$advr = ocsql_query($advq) or err("Unable to get advocate info"); +$recommendation = ocsql_fetch_array($advr); + +// Display form +printAdvocateForm($recommendation, $pid, $subinfo); + +printFooter(); + +?> diff --git a/review/committee-validate.inc b/review/committee-validate.inc new file mode 100644 index 0000000..2033a1a --- /dev/null +++ b/review/committee-validate.inc @@ -0,0 +1,92 @@ +' . sprintf(oc_('An account for the email address entered already exists. Would you like to Sign In or Recover Username?'), 'signin.php', 'email_username.php') . '

    '; + printFooter(); + exit; + } +} + +// Validate fields +foreach ($GLOBALS['OC_reviewerFieldSetAR'] as $fsid => $fs) { + foreach ($fs['fields'] as $fid) { + if (!preg_match("/^(?:username|password\d)$/", $fid)) { // skip validation of special fields + oc_validateField($fid, $GLOBALS['OC_reviewerFieldAR'], $qfields, $err); + } + } +} + +// Check account +if (isset($OC_reviewerFieldAR['username']) && oc_fieldEnabled('username', $GLOBALS['OC_reviewerFieldAR'])) { + if (!isset($_POST['username']) || !preg_match("/^[\p{L}\p{Nd}_\.\-\@]{5,50}$/u", trim($_POST['username']))) { + //T: $1$d and $2$d = range of characters permitted (e.g., 5 and 50) + $err .= '
  • ' . sprintf(oc_('Username must be between %1$d and %2$d characters: letters, numbers, period, hyphen, @'), 5, 50) . '
  • '; + } elseif (preg_match("/signup\.php/", $_SERVER['PHP_SELF'])) { + // check that user does not yet have an account; notify & bail if they do + $uq = "SELECT `reviewerid` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `username`='" . safeSQLstr(oc_strtolower(trim($_POST['username']))) . "'"; + $ur = ocsql_query($uq) or err("could not check username"); + if (ocsql_num_rows($ur) != 0) { + $err .= '
  • ' . sprintf(oc_('Username is already taken; select a different username (or Sign In if you already registered)'), 'signin.php') . '
  • '; + } else { + $qfields['username'] = "'" . safeSQLstr(oc_strtolower(trim($_POST['username']))) . "'"; + } + } +} + +// Check password if either field is not empty or it's an original signup +if ( (isset($_POST['password1']) && !empty($_POST['password1'])) // fld pwd1 set + || (isset($_POST['password2']) && !empty($_POST['password2'])) // fld pwd 2 set + || ( ! isset($OC_cmtEdit) ) // profile update +) { + if (!isset($_POST['password1']) || !isset($_POST['password2']) || empty($_POST['password1'])) { + $err .= '
  • ' . oc_('Password must be entered twice') . '
  • '; + } elseif ($_POST['password1'] != $_POST['password2']) { + $err .= '
  • ' . oc_('Passwords entered do not match') . '
  • '; + } elseif ( ! preg_match("/^.{8}/",$_POST['password1'])) { + //T: %d = number of characters + $err .= '
  • ' . sprintf(oc_('Password must be at least %d characters'), 8) . '
  • '; + } else { + $qfields['password'] = "'" . safeSQLstr(oc_password_hash($_POST['password1'])) . "'"; + } +} + +// Update topics +if (isset($qfields['topics'])) { + if ($qfields['topics'] != 'NULL') { + if (!preg_match("/^'[\d\,]*'$/", $qfields['topics'])) { + $err .= '
  • ' . sprintf(oc_('%s field does not appear to be valid'), oc_('Topic')) . '
  • '; // should only trigger if validateField above fails + } else { + $tfields = explode(',', trim($qfields['topics'], "'")); + } + } + unset($qfields['topics']); +} + +// Add datetime to consent +if (isset($qfields['consent']) && preg_match("/^\'.*\'$/", $qfields['consent'])) { + $qfields['consent'] = rtrim($qfields['consent'], "'") . safeSQLstr(" (" . gmdate('Y-m-d H:i:s') . " UTC)") . "'"; // add datetime to consent field +} + +// hook +if (oc_hookSet('committee-profile-validate')) { + foreach ($GLOBALS['OC_hooksAR']['committee-profile-validate'] as $hook) { + require_once $hook; + } +} diff --git a/review/committee.inc b/review/committee.inc new file mode 100644 index 0000000..c60f790 --- /dev/null +++ b/review/committee.inc @@ -0,0 +1,280 @@ + 0) { + while ($topl = ocsql_fetch_assoc($topr)) { + if ($topl['topicname'] == 'N/A') { continue; } + $topicAR[$topl['topicid']] = $topl['topicname']; + if (!empty($topl['short'])) { + $shortTopicAR[$topl['topicid']] = $topl['short']; + } + } +} + +$OC_reviewerFieldAR = array(); +$OC_reviewerFieldSetAR = array(); + +// Hooks +if (oc_hookSet('committee-profile-preinc')) { + foreach ($GLOBALS['OC_hooksAR']['committee-profile-preinc'] as $v) { + require_once $v; + } +} + +if (!isset($mod_oc_customforms_customCmtForm) || (!$mod_oc_customforms_customCmtForm)) { // skip if we have a custom form + + // Consent + if ( + (OCC_LICENSE != 'Public') + || + ((OCC_LICENSE == 'Public') && ($OC_configAR['OC_privacy_display'] > 0)) + ) { + $OC_reviewerFieldAR['consent'] = array( + 'name' => oc_('Consent'), + 'short' => oc_('Consent'), + 'note' => '', + 'type' => 'checkbox', + 'usekey' => false, + 'required' => true, + 'delimiter' => '', + 'values' => array(oc_('I consent to the collection and use of my personal information, including receiving emails, consistent with the Privacy Policy linked above.')) + ); + + $OC_reviewerFieldSetAR['fs_consent'] = array( + 'fieldset' => oc_('Consent'), + 'note' => '', + 'fields' => array('consent') + ); + } + + // Personal Info + $OC_reviewerFieldAR['orcid'] = array( + 'name' => oc_('ORCID'), + 'short' => oc_('ORCID'), + 'note' => '', + 'type' => 'text', + 'width' => 30, + 'maxchars' => 30, + 'required' => false + ); + + $OC_reviewerFieldAR['name_first'] = array( + 'name' => oc_('First/Given Name'), + 'short' => oc_('First Name'), + 'note' => '', + 'type' => 'text', + 'maxchars' => 60, + 'required' => false + ); + + $OC_reviewerFieldAR['name_last'] = array( + 'name' => oc_('Last/Family Name'), + 'short' => oc_('Last Name'), + 'note' => '', + 'type' => 'text', + 'maxchars' => 40, + 'required' => true + ); + + $OC_reviewerFieldAR['email'] = array( + 'name' => oc_('Email'), + 'short' => oc_('Email'), + 'note' => '', + 'type' => 'email', + 'required' => true + ); + + $OC_reviewerFieldAR['organization'] = array( + 'name' => oc_('Organization'), + 'short' => oc_('Organization'), + 'note' => '', + 'type' => 'text', + 'maxchars' => 150, // limitation as a result of utf8mb4 keys + 'required' => false + ); + + $OC_reviewerFieldAR['country'] = array( + 'name' => oc_('Country'), + 'short' => oc_('Country'), + 'note' => '', + 'type' => 'dropdown', + 'blank' => true, + 'required' => false, + 'valuetype' => 'country' + ); + + $OC_reviewerFieldAR['telephone'] = array( + 'name' => oc_('Telephone'), + 'short' => oc_('Telephone'), + 'note' => '', + 'type' => 'text', + 'required' => false + ); + + $OC_reviewerFieldAR['url'] = array( + 'name' => oc_('Web Site'), + 'short' => oc_('Web Site'), + 'note' => '', + 'type' => 'text', + 'required' => false, + 'placeholder' => 'https://' + ); + + $OC_reviewerFieldSetAR['fs_personal'] = array( + 'fieldset' => oc_('Personal Info'), + 'note' => '', + 'fields' => array('orcid', 'name_first', 'name_last', 'email', 'organization', 'country', 'telephone', 'url') + ); + + // Topics + $OC_reviewerFieldAR['topics'] = array( + 'name' => oc_('Topic Areas'), + 'short' => oc_('Topic(s)'), + 'note' => '', + 'type' => 'checkbox', + 'usekey' => true, + 'display' => 'newline', + 'required' => true, + 'valuetype' => 'topic' + ); + if ($OC_configAR['OC_multipleCommitteeTopics'] != 1) { // (!1 = limited to 1) + $OC_reviewerFieldAR['topics']['maxselections'] = 1; + } + + $OC_reviewerFieldSetAR['fs_topics'] = array( + 'fieldset' => oc_('Topic Areas'), + 'note' => oc_('To help match submissions to reviewers, please select the area(s) most applicable to your submission'), + 'fields' => array('topics') + ); + + + // Comments + $OC_reviewerFieldAR['comments'] = array( + 'name' => oc_('Comments to Chair'), + 'short' => oc_('Comments'), + 'note' => '', + 'type' => 'textarea', + 'height' => 5, + 'required' => false + ); + + $OC_reviewerFieldSetAR['fs_comments'] = array( + 'fieldset' => oc_('Comments'), + 'note' => '', + 'fields' => array('comments') + ); + + // Account + $OC_reviewerFieldAR['username'] = array( + 'name' => oc_('Username'), + 'short' => oc_('Username'), + //T: %1$d-%2$d = range of letters allowed (e.g., 5-50) + 'note' => sprintf(oc_('%1$d-%2$d characters: letters, numbers, @, period (.), hyphen (-)'), 5, 50), + 'minchars' => 5, + 'maxchars' => 50, + 'type' => 'text', + 'donotvalidate' => true, + 'required' => true // always true + ); + $OC_reviewerFieldAR['password1'] = array( + 'name' => oc_('Password'), + 'short' => oc_('Password'), + 'note' => sprintf(oc_('%d or more characters (any)'), 8), + 'type' => 'password', + 'donotvalidate' => true, + 'required' => true + ); + + $OC_reviewerFieldAR['password2'] = array( + 'name' => oc_('Re-enter Password'), + 'short' => oc_('Confirm'), + 'note' => '', + 'type' => 'password', + 'donotvalidate' => true, + 'required' => true + ); + + $OC_reviewerFieldSetAR['fs_passwords'] = array( + 'fieldset' => oc_('Account'), + 'note' => '', + 'fields' => array('username', 'password1', 'password2') + ); + + // Unset fields that should not be displayed on form + if (!empty($GLOBALS['OC_configAR']['OC_hideCmtFields'])) { + $hCF = explode(',', $GLOBALS['OC_configAR']['OC_hideCmtFields']); + foreach ($hCF as $hc_f) { + list($a_fs, $a_f) = explode(':', $hc_f); + unset($OC_reviewerFieldAR[$a_f]); + if (in_array($a_f, $OC_reviewerFieldSetAR[$a_fs]['fields'])) { + $OC_reviewerFieldSetAR[$a_fs]['fields'] = array_values(array_diff($OC_reviewerFieldSetAR[$a_fs]['fields'], array($a_f))); + } + } + } + +} // if ! custom form + + +if (oc_hookSet('committee-profile-inc')) { + foreach ($GLOBALS['OC_hooksAR']['committee-profile-inc'] as $v) { + require_once $v; + } +} + +// Make updates if not customforms edit +if (! isset($mod_oc_customforms_edit) || ! $mod_oc_customforms_edit) { + foreach ($OC_reviewerFieldAR as $sfk => $sf) { + // remove fields designated for new submissions (sign up) only if profile being edited + if (isset($sf['newsubonly']) && $sf['newsubonly'] && isset($GLOBALS['OC_cmtEdit']) && $GLOBALS['OC_cmtEdit']) { + unset($OC_reviewerFieldAR[$sfk]); + foreach ($OC_reviewerFieldSetAR as $fsid => $fsar) { + if (in_array($sfk, $fsar['fields'])) { + $OC_reviewerFieldSetAR[$fsid]['fields'] = array_diff($OC_reviewerFieldSetAR[$fsid]['fields'], array($sfk)); + continue; // field should only be in one fieldset + } + } + } else { // update valuetypes + if (isset($sf['valuetype']) && !empty($sf['valuetype']) && ($sf['valuetype'] != 'custom')) { + switch($sf['valuetype']) { + case 'country': + require_once OCC_COUNTRY_FILE; + $OC_reviewerFieldAR[$sfk]['values'] = $GLOBALS['OC_countryAR']; + break; + + case 'topic': + $OC_reviewerFieldAR[$sfk]['values'] = $topicAR; + break; + + default: // lib file + require_once OCC_LIB_DIR . $sf['valuetype'] . '.inc'; + $OC_reviewerFieldAR[$sfk]['values'] = $GLOBALS['OC_' . $sf['valuetype'] . 'AR']; + break; + } + } + } + } + + // Update Topics to radio if required and max selections = 1 + if (isset($OC_reviewerFieldAR['topics']['required']) && $OC_reviewerFieldAR['topics']['required'] && isset($OC_reviewerFieldAR['topics']['maxselections']) && ($OC_reviewerFieldAR['topics']['maxselections'] == 1) && ($OC_reviewerFieldAR['topics']['type'] == 'checkbox')){ + $OC_reviewerFieldAR['topics']['type'] = 'radio'; + } +} diff --git a/review/download.php b/review/download.php new file mode 100644 index 0000000..3d194f7 --- /dev/null +++ b/review/download.php @@ -0,0 +1,57 @@ + 1) { + $formatDBFldName = 'oc_multifile_' . $_GET['t'] . '_format'; +} + +$q = "SELECT `" . OCC_TABLE_PAPER . "`.`paperid`, `" . OCC_TABLE_PAPER . "`.`" . $formatDBFldName . "` FROM `" . OCC_TABLE_PAPER . "`, `" . $table . "` WHERE `" . $table . "`.`" . $field . "`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "' AND `" . OCC_TABLE_PAPER . "`.`paperid`=`" . $table . "`.`paperid` AND `" . OCC_TABLE_PAPER . "`.`" . $formatDBFldName . "` IS NOT NULL AND `" . OCC_TABLE_PAPER . "`.`" . $formatDBFldName . "`!='' ORDER BY `paperid`"; + +require_once '../include-download.inc'; + +exit; + +?> diff --git a/review/email_username.php b/review/email_username.php new file mode 100644 index 0000000..5b4bd93 --- /dev/null +++ b/review/email_username.php @@ -0,0 +1,57 @@ +' . oc_('Email address entered is invalid') . '

    '; + printFooter(); + exit; + } + $q = "SELECT `reviewerid`, `username`, `email` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `email`='" . safeSQLstr(oc_strtolower($_POST['email'])) . "'"; + $r = ocsql_query($q) or err("Error checking email"); + if (($rnum=ocsql_num_rows($r)) == 0) { + print '

    ' . oc_('Email address entered is invalid') . ' (2)

    '; + } + elseif ($rnum > 1) { + err("multiple accounts with this email address"); + } else { + $e = ocsql_fetch_array($r); + //T: %s = conference short name (e.g., CONF2012) + $msg = "\n" . sprintf(oc_('Your username for accessing the %s OpenConf system is:'), $OC_configAR['OC_confName']) . "\n\n " . $e['username'] . "\n\n"; + sendEmail($_POST['email'], oc_('Username Recovery'), $msg, $OC_configAR['OC_notifyReviewerEmailUsername']); + print '

    ' . sprintf(oc_('We have emailed your username. Once you receive it, you may sign in here.'), 'signin.php') . '

    '; + printFooter(); + exit; + } +} +else { + print '

    ' . oc_('Please enter the email you registered with below') . '

    '; +} + +print ' +
    + + + + +

    +
    +

    +'; + +printFooter(); + +?> diff --git a/review/index.html b/review/index.html new file mode 100644 index 0000000..e69de29 diff --git a/review/index.php b/review/index.php new file mode 100644 index 0000000..e69de29 diff --git a/review/list_papers.php b/review/list_papers.php new file mode 100644 index 0000000..8da4a89 --- /dev/null +++ b/review/list_papers.php @@ -0,0 +1,165 @@ +' . oc_('File') . ''; // table header used for file column +$formatField = '`format`'; // paper table format field +$blanks = '  '; // cell padding (see below) + +beginSession(); + +printHeader(oc_('View Submissions'), 2); + +// Get permissions +$readOtherPapers = 0; +$seeAssignedReviews = 0; +$seeOtherReviews = 0; +$seeIncomplete = 1; +$seeDecision = 0; +// If advocate, apply advocate permissions +if ($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] == "T") { + $seeAssignedReviews = 1; + if ($OC_configAR['OC_advocateReadPapers']) { + $readOtherPapers = 1; + if ($OC_configAR['OC_advocateSeeOtherReviews']) { + $seeOtherReviews = 1; + } + } + if ($OC_configAR['OC_advocateSeeDecision']) { $seeDecision = 1; } +} +if ($OC_configAR['OC_reviewerReadPapers']) { + $readOtherPapers = 1; + if ($OC_configAR['OC_reviewerSeeOtherReviews']) { + $seeOtherReviews = 1; + } +} +if ($OC_configAR['OC_reviewerSeeAssignedReviews']) { $seeAssignedReviews = 1; } +if ($OC_configAR['OC_reviewerCompleteBeforeSAR']) { $seeIncomplete = 0; } +if ($OC_configAR['OC_reviewerSeeDecision']) { $seeDecision = 1; } +// Anything left to see? +if (!$readOtherPapers && !$seeAssignedReviews && !$seeOtherReviews) { + warn(oc_('Settings prohibit viewing additional submission information')); +} + +// Get list of assigned papers & incomplete reviews +$assignedPaperAR = array(); +$incompleteReviewAR = array(); +$q = "SELECT `paperid`, `completed`, `score` FROM `" . OCC_TABLE_PAPERREVIEWER . "` WHERE `reviewerid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "'"; +$r = ocsql_query($q) or err("Unable to retrieve permitted reviews"); +while ($l=ocsql_fetch_array($r)) { + $assignedPaperAR[] = $l['paperid']; + if (($l['completed'] == 'F') || !$l['score']) { + $incompleteReviewAR[] = $l['paperid']; + } +} + +// If advocate, get list of advocating papers +$advocatingPaperAR = array(); +if ($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] == "T") { + $q = "SELECT `paperid` FROM `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `advocateid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "'"; + $r = ocsql_query($q) or err("Unable to retrieve advocating submissions"); + while ($l=ocsql_fetch_array($r)) { + $advocatingPaperAR[] = $l['paperid']; + } +} + +// Get list of conflicts +$conflictAR = getConflicts($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']); + +if (oc_hookSet('committee-list_papers-preprocess')) { + foreach ($OC_hooksAR['committee-list_papers-preprocess'] as $v) { + require_once $v; + } +} + +// List papers +$q = "SELECT `paperid`, `title`, `accepted`, " . $formatField . " FROM `" . OCC_TABLE_PAPER . "` ORDER BY `paperid`"; +$r = ocsql_query($q) or err("Unable to get submissions"); +if (ocsql_num_rows($r) == 0) { + print '

    ' . oc_('No submissions have been made yet.') . '

    '; +} else { + $row = 1; + $count = 0; + print '

    ' . oc_('Note: bold submission titles indicate ones assigned to you') . '

    '; + print ''; + if ($seeAssignedReviews || $seeOtherReviews) { print ''; } + print '' . $fileTableHeader . ''; + if ($seeDecision) { print ''; } + print "\n\n"; + while ($l = ocsql_fetch_array($r)) { + // Skip if in conflict + if (in_array($l['paperid'].'-'.$_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid'],$conflictAR) + && !in_array($l['paperid'], $assignedPaperAR) + && !in_array($l['paperid'], $advocatingPaperAR) + ) { + continue; + } + + if (in_array($l['paperid'],$assignedPaperAR)) { $assigned = 1; } + else { $assigned = 0; } + if (in_array($l['paperid'],$incompleteReviewAR)) { $completed = 0; } + else { $completed = 1; } + if (in_array($l['paperid'],$advocatingPaperAR)) { $advocating = 1; } + else { $advocating = 0; } + + $i = 0; + $tr = ''; + + if ($seeAssignedReviews || $seeOtherReviews) { + if ($advocating || (($seeIncomplete || $completed) && (($seeOtherReviews && !$assigned) || ($seeAssignedReviews && $assigned)))) { + $tr .= ''; + $i++; + } else { + $tr .= ''; + } + } + if (($assigned || $advocating || $readOtherPapers)) { + $i++; + $tr .= '' . oc_printFileCells($l); + } else { + $tr .= $blanks; + } + if ($i > 0) { + print '' . $tr . ''; + if ($seeDecision) { + if (!empty($l['accepted'])) { + print '' . safeHTMLstr($l['accepted']) . ''; + } else { + print ''; + } + } + print ''; + $row = $rowAR[$row]; + $count++; + } + } + print '
    ' . oc_('Reviews') . '' . oc_('Abstract') . '' . oc_('Submission') . '' . oc_('Status') . '
    ' . safeHTMLstr(oc_('view')) . ' ' . safeHTMLstr(oc_('view abstract')) . '
    '; + $paperstr = $l['paperid'] . '. ' . safeHTMLstr($l['title']); + if ($assigned || $advocating) { print "$paperstr"; } + else { print $paperstr; } + print '' . safeHTMLstr(oc_('Pending')) . '
    '; + if ($count == 0) { + print ' +

    ' . oc_('There are no submissions available for you to view.') . '

    + +'; + } +} + +printFooter(); + +?> diff --git a/review/paper.php b/review/paper.php new file mode 100644 index 0000000..45ef60a --- /dev/null +++ b/review/paper.php @@ -0,0 +1,84 @@ + diff --git a/review/recover.php b/review/recover.php new file mode 100644 index 0000000..d0f7d84 --- /dev/null +++ b/review/recover.php @@ -0,0 +1,84 @@ + 'review.php', + 'Recommendation' => 'advocate.php' +); + +// Submit type +$what = substr($_SESSION[OCC_SESSION_VAR_NAME]['POST']['submit'], (strrpos($_SESSION[OCC_SESSION_VAR_NAME]['POST']['submit'], " ") + 1)); + +// Valid submit type? +if (!in_array($what, array_keys($whatLocAR))) { + header('Location: reviewer.php?' . strip_tags(SID)); + exit; +} + +ob_start(); +printHeader("Recover Submission", 2); + +// Display form with current POST values +print '

    ' . oc_('Your session timed out prior to your submission being completed. Would you like to submit it now?') . '

    +
    + +
    + + +'; + +// Undefine submit so it doesn't get included +unset($_SESSION[OCC_SESSION_VAR_NAME]['POST']['submit']); + +foreach ($_SESSION[OCC_SESSION_VAR_NAME]['POST'] as $k => $v) { + if ($k == 'token') { // skip old token + continue; + } + if (is_array($v)) { + foreach ($v as $vv) { + print '' . "\n"; + } + } else { + print '' . "\n"; + } +} + +// Undefine session POST var so user not asked again later +unset($_SESSION[OCC_SESSION_VAR_NAME]['POST']); + +ob_end_flush(); + +print ' + +
    +

    +
    + +
    + +
    +

    +'; + +printFooter(); + +?> diff --git a/review/reset.php b/review/reset.php new file mode 100644 index 0000000..a78595d --- /dev/null +++ b/review/reset.php @@ -0,0 +1,60 @@ +Invalid username.

    '; } + elseif ($rnum > 1) { err("multiple accounts with this username"); } + else { + $e = ocsql_fetch_array($r); + if (oc_strtolower($e['email']) != oc_strtolower($_POST['email'])) { + print '

    ' . oc_('Email does not match username.') . '

    '; + } + else { // username valid, reset pwd + $newpwd = oc_password_generate(); + $q2 = "UPDATE `" . OCC_TABLE_REVIEWER . "` SET `password`='" . oc_password_hash($newpwd) . "' WHERE `reviewerid`='" . safeSQLstr($e['reviewerid']) . "'"; + $r2 = ocsql_query($q2) or err(oc_('Unable to update password')); + //T: $s = conference short name (e.g., CONF2012) + $msg = "\n" . sprintf(oc_('Per your request, we have issued you a new password for accessing the %s OpenConf system. The new password is:'), $OC_configAR['OC_confName']) . "\n\n " . $newpwd . "\n\n" . oc_('You may change this password at any time by signing in to the OpenConf system and updating your profile.') . "\n\n"; + if (sendEmail($_POST['email'], "Reviewer Password Reset", $msg, $OC_configAR['OC_notifyReviewerReset'])) { + print sprintf(oc_('We have emailed you a new password. Once you receive it, please sign in and change it.'), 'signin.php') . '

    '; + } else { + warn(oc_('We have reset your password, but have been unable to email it to you. Please contact the administrator.')); + } + printFooter(); + exit; + } + } +} +else { + print '

    ' . oc_('Please enter your username and the email you registered with below') . '

    '; +} + +print ' +
    + + + + + +

    +
    +

    +'; + +printFooter(); + +?> diff --git a/review/review.inc b/review/review.inc new file mode 100644 index 0000000..9a067a6 --- /dev/null +++ b/review/review.inc @@ -0,0 +1,252 @@ + 0) { + while ($topl = ocsql_fetch_assoc($topr)) { + $topicAR[$topl['topicid']] = $topl['topicname']; + } +} + +// Hooks +if (oc_hookSet('committee-review-preinc')) { + foreach ($GLOBALS['OC_hooksAR']['committee-review-preinc'] as $v) { + require_once $v; + } +} + +if (!isset($mod_oc_customforms_customRevForm) || (!$mod_oc_customforms_customRevForm)) { // skip if we have a custom form + + // Note: The recommendation field value is used for calculating a submission's score. + // The field is defined as TINYINT(3), which may need to be changed if a larger value will be stored + $OC_reviewQuestionsAR = array( + 'recommendation' => array( + 'name' => oc_('Recommendation'), + 'short' => oc_('Recommendation'), + 'note' => '', + 'type' => 'radio', + 'display' => 'newline', + 'required' => true, + 'score' => true, + 'usekey' => true, + 'longlabel' => true, + 'values' => array( + 1 => oc_('Reject: Content inappropriate to the conference or has little merit'), + 2 => oc_('Probable Reject: Basic flaws in content or presentation or very poorly written'), + 3 => oc_('Marginal Tend to Reject: Not as badly flawed; major effort necessary to make acceptable but content well-covered in literature already'), + 4 => oc_('Marginal Tend to Accept: Content has merit, but accuracy, clarity, completeness, and/or writing should and could be improved in time'), + 5 => oc_('Clear Accept: Content, presentation, and writing meet professional norms; improvements may be advisable but acceptable as is'), + 6 => oc_('Must Accept: Candidate for outstanding submission. Suggested improvements still appropriate') + ) + ), + + 'category' => array( + 'name' => oc_('Submission Categorization'), + 'short' => oc_('Category'), + 'note' => '', + 'type' => 'radio', + 'display' => 'newline', + 'longlabel' => true, + 'usekey' => true, + 'values' => array( + 1 => oc_('Highly theoretical'), + 2 => oc_('Tends towards theoretical'), + 3 => oc_('Balanced theory and practice'), + 4 => oc_('Tends toward practical'), + 5 => oc_('Highly practical') + ) + ), + + 'value' => array( + 'name' => oc_('Overall Value Added to the Field'), + 'short' => oc_('Value'), + 'note' => oc_('Check as many as appropriate'), + 'type' => 'checkbox', + 'display' => 'newline', + 'longlabel' => true, + 'usekey' => true, + 'values' => array( + 1 => oc_('New information'), + 2 => oc_('Valuable confirmation of present knowledge'), + 3 => oc_('Clarity to present understanding'), + 4 => oc_('New perspective, issue, or problem definition'), + 5 => oc_('Not much'), + 6 => oc_('Other') + ) + ), + + 'familiar' => array( + 'name' => oc_('Reviewer Familiarity with Subject Matter'), + 'short' => oc_('Familiarity'), + 'note' => oc_('Relates to the confidence you have in your review'), + 'type' => 'radio', + 'display' => 'newline', + 'longlabel' => true, + 'usekey' => true, + 'values' => array( + 'Low' => oc_('Low'), + 'Moderate' => oc_('Moderate'), + 'High' => oc_('High') + ) + ), + + 'bpcandidate' => array( + 'name' => oc_('Is this submission a candidate for the best submission award'), + 'short' => oc_('Best Sub.'), + 'note' => '', + 'type' => 'radio', + 'display' => 'newline', + 'longlabel' => true, + 'usekey' => true, + 'values' => array( + 'Yes' => oc_('Yes'), + 'No' => oc_('No'), + 'Unsure' => oc_('Unsure') + ) + ), + + 'length' => array( + 'name' => oc_('Is the submission length appropriate'), + 'short' => oc_('Length'), + 'note' => '', + 'type' => 'radio', + 'display' => 'newline', + 'longlabel' => true, + 'usekey' => true, + 'values' => array( + 'Yes' => oc_('Yes'), + 'No' => oc_('No'), + 'Unsure' => oc_('Unsure') + ) + ), + + 'difference' => array( + 'name' => oc_('If from reading the submission you know who the author is, how different is this from earlier submissions on the same topic by the same author? That is, is it the same as or a slight modification of other submissions, with little or no new information'), + 'short' => oc_('Prior Work Diff.'), + 'note' => oc_('We use these suggestions in assigning submissions to sessions for the conference, but not in determining whether the submission is accepted)'), + 'type' => 'radio', + 'display' => 'newline', + 'longlabel' => true, + 'usekey' => true, + 'values' => array( + 1 => oc_('Totally or largely different from other submissions'), + 2 => oc_('Moderately different from other submissions'), + 3 => oc_('Totally or largely identical to other submissions'), + 4 => oc_("Don't know") + ) + ), + + 'sessions' => array( // NOTE: sessions field should not have showauthor attribute set + 'name' => oc_('Which of the following session(s) would be the most appropriate for this submission'), + 'short' => oc_('Session(s)'), + 'note' => oc_('We use these suggestions in assigning submissions to sessions for the conference, but not in determining whether the submission is accepted)'), + 'type' => 'checkbox', + 'longlabel' => true, + 'usekey' => true, + 'display' => 'newline', + 'required' => false, + 'valuetype' => 'topic' + ), + + 'authorcomments' => array( + 'name' => oc_('Comments for the Authors'), + 'short' => oc_('Author Comments'), + 'note' => oc_('Constructive comments to the author(s) would be appreciated.'), + 'type' => 'textarea', + 'showauthor' => true, + 'longlabel' => true + ), + + 'pccomments' => array( + 'name' => oc_('Comments for the Program Committee (authors will not see these comments)'), + 'short' => oc_('PC Comments'), + 'note' => oc_('Reasons must be included for all submissions, because they help us determine what to do when reviewers disagree with each other.'), + 'type' => 'textarea', + 'longlabel' => true + ) + + ); + + // Set up fieldset + $OC_reviewQuestionsFieldsetAR = array( + 'fs_review' => array( + 'fieldset' => oc_('Review'), + 'note' => '', + 'fields' => array_keys($OC_reviewQuestionsAR) + ) + ); + + // Unset fields that should not be displayed on form -- defaults to fs_review fieldset + if (!empty($GLOBALS['OC_configAR']['OC_hideRevFields'])) { + $hRF = explode(',', $GLOBALS['OC_configAR']['OC_hideRevFields']); + foreach ($hRF as $hr_f) { + unset($OC_reviewQuestionsAR[$hr_f]); + if (in_array($hr_f, $OC_reviewQuestionsFieldsetAR['fs_review']['fields'])) { + $OC_reviewQuestionsFieldsetAR['fs_review']['fields'] = array_values(array_diff($OC_reviewQuestionsFieldsetAR['fs_review']['fields'], array($hr_f))); + } + } + } + +} // if ! custom form + + +// Fill in session topics +if (isset($OC_reviewQuestionsAR['sessions'])) { + $tq = "SELECT * FROM `" . OCC_TABLE_TOPIC . "`"; + $tr = ocsql_query($tq) or err("Unable to retrieve topics"); + while ($tt = ocsql_fetch_assoc($tr)) { + $OC_reviewQuestionsAR['sessions']['values'][$tt['topicid']] = $tt['topicname']; + } +} + +if (oc_hookSet('committee-review-inc')) { + foreach ($GLOBALS['OC_hooksAR']['committee-review-inc'] as $v) { + require_once $v; + } +} + +// Make updates if not customforms edit +if (! isset($mod_oc_customforms_edit) || ! $mod_oc_customforms_edit) { + // Update valuetypes + foreach ($OC_reviewQuestionsAR as $sfk => $sf) { + if (isset($sf['valuetype']) && !empty($sf['valuetype']) && ($sf['valuetype'] != 'custom')) { + switch($sf['valuetype']) { + case 'country': + require_once OCC_COUNTRY_FILE; + $OC_reviewQuestionsAR[$sfk]['values'] = $GLOBALS['OC_countryAR']; + break; + + case 'topic': + $OC_reviewQuestionsAR[$sfk]['values'] = $topicAR; + break; + + default: // lib file + require_once OCC_LIB_DIR . $sf['valuetype'] . '.inc'; + $OC_reviewQuestionsAR[$sfk]['values'] = $GLOBALS['OC_' . $sf['valuetype'] . 'AR']; + break; + } + } + } + + // Update Topics to radio if required and max selections = 1 + if (isset($OC_reviewQuestionsAR['sessions']['required']) && $OC_reviewQuestionsAR['sessions']['required'] && isset($OC_reviewQuestionsAR['sessions']['maxselections']) && ($OC_reviewQuestionsAR['sessions']['maxselections'] == 1) && ($OC_reviewQuestionsAR['sessions']['type'] == 'checkbox')){ + $OC_reviewQuestionsAR['sessions']['type'] = 'radio'; + } +} diff --git a/review/review.php b/review/review.php new file mode 100644 index 0000000..0a48358 --- /dev/null +++ b/review/review.php @@ -0,0 +1,336 @@ +try again. If the problem persists, please contact the Chair.'), ($_SERVER['PHP_SELF'] . '?pid=' . (is_numeric($_POST['pid']) ? $_POST['pid'] : ''))) . '

    '; + $OC_reviewQuestionsARkeys = array_keys($OC_reviewQuestionsAR); + foreach ($_POST as $k => $v) { + if (($k == 'submit') || ($k == 'token')) { continue; } + if (in_array($k, $OC_reviewQuestionsARkeys)) { + $w .= "
    \n

    \n" . safeHTMLstr($OC_reviewQuestionsAR[$k]['short']) . " "; + if ($OC_reviewQuestionsAR[$k]['usekey']) { + $w .= $OC_reviewQuestionsAR[$k]['values'][$v]; + } else { + $w .= safeHTMLstr($v); + } + } else { + $w .= "
    \n

    \n" . safeHTMLstr($k) . ": " . safeHTMLstr($v); + } + } + $w .= '
    '; + warn($w); + } + + // Email review copy - do it here in case of errors/problems below + if (isset($_POST['emailcopy']) && ($_POST['emailcopy'] == "1")) { + // ocIgnore included so poEdit picks up (DB) template translation + //T: [:sid:] is the numeric submission ID + $ocIgnoreSubject = oc_('Review of submission [:sid:]'); + //T: [:OC_confName:] is the event name; [:sid:] is the numeric submission ID + $ocIgnoreBody = oc_('Following is a copy of your review for submission number [:sid:] submitted to [:OC_confName:]. Note that you will receive this email even if an error occurred during submission. + +[:fields:]'); + list($mailsubject, $msg) = oc_getTemplate('committee-review'); + $fields = oc_genFieldMessage($GLOBALS['OC_reviewQuestionsFieldsetAR'], $GLOBALS['OC_reviewQuestionsAR'], $_POST); + $templateExtraAR = array( + 'sid' => $thepid, + 'fields' => $fields + ); + $mailsubject = oc_replaceVariables($mailsubject, $templateExtraAR); + $msg = oc_replaceVariables($msg, $templateExtraAR); + + if (oc_hookSet('committee-review-msg')) { + foreach ($GLOBALS['OC_hooksAR']['committee-review-msg'] as $v) { + require_once $v; + } + } + + if (!sendEmail($review['email'], $mailsubject, $msg)) { + print '

    ' . oc_('We were unable to send copy of the review via email') . '

    '; + } + } + + // Validate fields + $qfields = array(); + $err = ''; + foreach ($GLOBALS['OC_reviewQuestionsFieldsetAR'] as $fsid => $fs) { + foreach ($fs['fields'] as $fid) { + if (isset($GLOBALS['OC_reviewQuestionsAR'][$fid])) { + oc_validateField($fid, $GLOBALS['OC_reviewQuestionsAR'], $qfields, $err); + } + } + } + // Check for completion and calculate score + $score = null; + if (isset($_POST['completed']) && ($_POST['completed'] == 1)) { + $completed = 'T'; + } else { + $completed = 'F'; + } + foreach ($OC_reviewQuestionsAR as $fid => $far) { + if (isset($far['score']) && $far['score'] && isset($_POST[$fid]) && preg_match("/^\d+$/", $_POST[$fid])) { + if ( + $useFieldValueForScore + && isset($far['values']) + && isset($far['values'][$_POST[$fid]]) + && preg_match("/^[0-9]+$/", $far['values'][$_POST[$fid]]) + ) { + $scoreValue = $far['values'][$_POST[$fid]]; + } else { + $scoreValue = $_POST[$fid]; + } + if ($score === null) { + $score = $scoreValue; + } else { + $score += $scoreValue; + } + } + if (($completed == 'T') && isset($far['required']) && $far['required'] && !isset($qfields[$fid])) { + $completed = 'F'; + } + } + + // Hooks + if (oc_hookSet('committee-review-validate')) { + foreach ($GLOBALS['OC_hooksAR']['committee-review-validate'] as $v) { + require_once $v; + } + } + + // Error? + if (!empty($err)) { + print '
    ' . oc_('Your review has not been saved.') . ' ' . oc_('Please check the following:') . '
      ' . $err . '

    '; + printReviewForm($_POST, $thepid); + return; + } + + // Update sessions + $sfields = array(); + if (isset($qfields['sessions'])) { + if ($qfields['sessions'] != 'NULL') { + if (!preg_match("/^'[\d\,]*'$/", $qfields['sessions'])) { + $err .= '
  • ' . sprintf(oc_('%s field does not appear to be valid'), oc_('Session(s)')) . '
  • '; // should only trigger if validation above fails + } else { + $sfields = explode(',', trim($qfields['sessions'], "'")); + } + } + unset($qfields['sessions']); + } + + // Compose sql and update + $q = "UPDATE `" . OCC_TABLE_PAPERREVIEWER . "` SET `updated`='" . safeSQLstr(date('Y-m-d')) . "', "; + if ($score !== null) { + $q .= "`score`=" . (int) $score . ", "; + } + foreach ($qfields as $qid => $qval) { + $q .= "`" . $qid . "`=" . $qval . ", "; + } + $q .= "`completed`='" . safeSQLstr($completed) . "' WHERE `paperid`='" . safeSQLstr($thepid) . "' AND `reviewerid`='" . safeSQLstr(safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid'])) . "'"; + ocsql_query($q) or err("Unable to submit review"); + + // Update papersession + if (isset($OC_reviewQuestionsAR['sessions'])) { + $q2 = "DELETE FROM `" . OCC_TABLE_PAPERSESSION . "` WHERE `paperid`='" . safeSQLstr($thepid) . "' AND `reviewerid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "'"; + ocsql_query($q2) or err("Unable to update sessions"); + if (!empty($sfields) && ($sfields != 'NULL')) { + $q3 = "INSERT INTO `" . OCC_TABLE_PAPERSESSION . "` (`paperid`,`reviewerid`,`topicid`) VALUES"; + foreach ($sfields as $s) { + $q3 .= " ('" . safeSQLstr($thepid) . "','" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "','" . safeSQLstr($s) . "'),"; + } + ocsql_query(rtrim($q3, ',')) or err(oc_('Unable to add sessions')); + } + } + + if (oc_hookSet('committee-review-save')) { + foreach ($GLOBALS['OC_hooksAR']['committee-review-save'] as $v) { + require_once $v; + } + } + + print '

    ' . oc_('Review has been submitted.') . '

    '; + if (isset($_POST['completed']) && ($_POST['completed'] == 1) && ($completed == 'F')) { + print '

    ' . oc_('However as not all required questions were answered, the review was not marked as completed.') . '

    '; + } + print '

    » ' . oc_('Return to Review') . '

    '; + //T: Member = Committee Member -- see "Member Home" string + print '

    » ' . oc_('Return to Member home page') . '

    '; +}// function saveReviewForm + +function printReviewForm($review, $thepid) { + global $OC_configAR, $OC_reviewQuestionsAR; + + print '

    ' . safeHTMLstr($review['title']) . ''; + + if (isset($review['type']) && !empty($review['type'])) { + print '
    (' . safeHTMLstr($review['type']) . ')'; + } + + print '
    ' . oc_('Submission ID') . ': ' . safeHTMLstr($thepid); + + if (isset($OC_configAR['OC_reviewerSeeAdvocate']) && $OC_configAR['OC_reviewerSeeAdvocate'] && isset($review['advocate_name']) && !empty($review['advocate_name'])) { + print '
    ' . oc_('Advocate') . ': ' . safeHTMLstr($review['advocate_name']) . ''; + } + + print '

    '; + + $tip = '
    ' . oc_("TIP: Use a local text editor to write your review, and then select/copy the information below. This way, in case of a network outage, you won't lose the review.") . '

    '; + + print ' +
    + + + + + + + '; + + if (oc_hookSet('committee-review-fields')) { + foreach ($GLOBALS['OC_hooksAR']['committee-review-fields'] as $v) { + require_once $v; + } + } + + print $tip; + + oc_displayFieldSet($GLOBALS['OC_reviewQuestionsFieldsetAR'], $GLOBALS['OC_reviewQuestionsAR'], $review); + + if (oc_hookSet('committee-review-extra')) { + foreach ($GLOBALS['OC_hooksAR']['committee-review-extra'] as $v) { + require_once $v; + } + } + + if ($GLOBALS['showEmailCopy']) { + print '
    ' . oc_('Useful for your own record or in case there is some kind of error during updating.') . ' '; + if ($OC_configAR['OC_ReviewerTimeout'] > 0) { + print oc_('Note that if your session times out, you may not receive an email; you should log back in right away to recover the review.'); + } + print "
    \n"; + } + + if ($GLOBALS['showCompletedReview']) { + print '
    ' . oc_('Check this box when you have finished the review for this submission. This is used only to track how many outstanding reviews there are. You will still be able to edit this review after checking this box, until the review deadline date.') . "
    \n"; + } + + print "
    \n"; + + if ($thepid != "blank") { + print '

    '; + } + else { + print '

    [ ' . oc_('Sample Review Form - Fill in and submit review by clicking the submission title on main reviewer page') . ' ]

    '; + } + + if ($OC_configAR['OC_ReviewerTimeout'] > 0) { + print '

    ' . oc_('Should your session timeout while filling out this review, log back in right away as we may be able to recover your review.') . '

    '; + } + +} // function printReviewForm + + +if (isset($_POST['ocaction']) && ($_POST['ocaction'] == "Submit Review")) { + if (!isset($_POST['pid']) || !preg_match("/^\d+$/", $_POST['pid'])) { + warn('Invalid submission ID'); + } + $q = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`, `" . OCC_TABLE_REVIEWER . "`.`email` FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`='" . safeSQLstr($_POST['pid']) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + $thepid = $_POST['pid']; +} else { + if (!isset($_GET['pid']) || (($_GET['pid'] != 'blank') && !preg_match("/^\d+$/", $_GET['pid']))) { + warn(oc_('Submission ID is invalid')); + } + $q = "SELECT `title`, `format`, `type`, `" . OCC_TABLE_PAPERREVIEWER . "`.* FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`='" . safeSQLstr($_GET['pid']) . "' AND `reviewerid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid`"; + $thepid = $_GET['pid']; +} + +require_once OCC_FORM_INC_FILE; +require_once OCC_REVIEW_INC_FILE; + +if ($thepid == "blank") { // display blank form + $review = array(); + $review['title'] = oc_('Sample Review'); + $review['format'] = ""; + $review['type'] = ""; + printReviewForm($review, 0); +} elseif (!preg_match("/^\d+$/", $thepid)) { + print '' . oc_('Submission ID is invalid') . '

    '; +} else { + $r = ocsql_query($q) or err("Unable to retrieve submission for review"); + if (ocsql_num_rows($r) == 0) { + //T: Use care with href - "mailto" and "subject" should not be translated + print '' . sprintf(oc_('Either the submission does not exist, or you have not been assigned it for review. If this is in error, please contact the Chair.'), $OC_configAR['OC_pcemail']) . '

    '; + } else { + $review = ocsql_fetch_array($r); + + // remove fields with matching hidesubtypes + $subtype = varValue('type', $_POST, varValue('type', $review)); + if (!empty($subtype)) { + foreach ($OC_reviewQuestionsAR as $fid => $far) { + if (isset($far['hidesubtypes']) && is_array($far['hidesubtypes']) && in_array($subtype, $far['hidesubtypes'])) { + unset($OC_reviewQuestionsAR[$fid]); + } + } + } + + // process action + if (isset($_POST['ocaction']) && ($_POST['ocaction'] == "Submit Review")) { + saveReviewForm($review, $thepid); // save form + } else { + // Add sessions to review array + $sq = "SELECT `topicid` FROM `" . OCC_TABLE_PAPERSESSION . "` WHERE `paperid`='" . safeSQLstr($thepid) . "' AND `reviewerid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "'"; + $sr = ocsql_query($sq); + $review['sessions'] = array(); + while ($sl = ocsql_fetch_array($sr)) { + $review['sessions'][] = $sl['topicid']; + } + if ( isset($OC_reviewQuestionsAR['sessions']['type']) && ($OC_reviewQuestionsAR['sessions']['type'] == 'radio') && isset($review['sessions'][0]) ) { + $review['sessions'] = $review['sessions'][0]; + } + // Add advocate to review array + if (isset($OC_configAR['OC_reviewerSeeAdvocate']) && $OC_configAR['OC_reviewerSeeAdvocate']) { + $aq = "SELECT CONCAT_WS(' ', `name_first`, `name_last`) AS `name`, `email` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`='" . safeSQLstr($thepid) . "' AND `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; + $ar = ocsql_query($aq) or err('Unable to retrieve advocate'); + if (ocsql_num_rows($ar) == 1) { + $al = ocsql_fetch_assoc($ar); + $review['advocate_name'] = $al['name']; + $review['advocate_email'] = $al['email']; + } + } + // print form + printReviewForm($review, $thepid); + } + } +} + +printFooter(); + +?> diff --git a/review/reviewer.php b/review/reviewer.php new file mode 100644 index 0000000..7102cab --- /dev/null +++ b/review/reviewer.php @@ -0,0 +1,252 @@ +' . oc_('File') . ''; // table header used for file column +$formatField = '`format`'; // paper table format field + +$extraCols = 0; // extra columns to skip when displaying ZIP download icons (e.g., abstract, type) + +$abstractCol = 'Abstract'; // name for abstract column -- set to empty to not display + +$advocateOrder = '!ISNULL(`adv_recommendation`), `paperid`'; // Submission to Advocate ORDER BY fields + +$showReviewScore = false; // EXPERIMENTAL. Displays review score in Submissions to Review table + +beginSession(); + +printHeader(oc_('Committee Member'), 2); + +print "

    \n"; + +$conflictAR = getConflicts($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']); + +if (oc_hookSet('committee-menu-preprocess')) { + foreach ($OC_hooksAR['committee-menu-preprocess'] as $v) { + require_once $v; + } +} + +if (!empty($abstractCol)) { $extraCols++; } // it's here so it's checked after the hook + +// Track Type? +$OC_trackType = false; +$sr = ocsql_query("SELECT COUNT(*) AS `count` FROM `" . OCC_TABLE_PAPER . "` WHERE `type`!='' AND `type` IS NOT NULL") or err('Unable to check type field'); +if (($sl = ocsql_fetch_assoc($sr)) && ($sl['count'] > 0)) { + $OC_trackType = true; + $extraCols++; +} + +// Can reviewers still sign-in? +if ($OC_statusAR['OC_rev_signin_open']) { + $extraFields = ''; + + print '
    ' . safeHTMLstr(oc_('View Submissions')) . '

    '; + + if (oc_hookSet('committee-menu-prereview')) { + foreach ($OC_hooksAR['committee-menu-prereview'] as $v) { + print '
    • ' . $v . '

    '; + } + } + if (oc_hookSet('committee-menu-pc-prereview') && ($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] == "T") && $OC_statusAR['OC_pc_signin_open']) { + foreach ($OC_hooksAR['committee-menu-pc-prereview'] as $v) { + print '
    • ' . $v . '

    '; + } + } + + // Is reviewing open? + if ($OC_statusAR['OC_reviewing_open']) { + print ' +
    ' . safeHTMLstr(oc_('Submissions to Review:')) . '
    +

    +'; + // delete assignments? + if (($OC_configAR['OC_reviewerUnassignReviews'] == 1) + && isset($_POST['ocaction']) && ($_POST['ocaction'] == 'Delete Review Assignments') + && isset($_POST['submissions']) && is_array($_POST['submissions']) && (count($_POST['submissions'] > 0)) + ) { + // Check for valid submission + if (!validToken('ac')) { + warn(oc_('Invalid submission')); + } + // iterate through subs + foreach ($_POST['submissions'] as $sid) { + if (!preg_match("/^[1-9]\d*$/", $sid)) { + warn(oc_('Invalid request')); + } + // verify assignment + if (($unassign_r1 = ocsql_query("SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid` AS `sid`, `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`, `" . OCC_TABLE_PAPER . "`.`title`, `" . OCC_TABLE_REVIEWER . "`.`username`, CONCAT_WS(' ', `" . OCC_TABLE_REVIEWER . "`.`name_first`, `" . OCC_TABLE_REVIEWER . "`.`name_last`) AS `name` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_PAPER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`='" . safeSQLstr($sid) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`")) + && (ocsql_num_rows($unassign_r1) == 1) + && ($unassign_l1 = ocsql_fetch_assoc($unassign_r1)) + ) { + $mailto = ''; + // retrieve advocate email for notification + if ( + ($unassign_r2 = ocsql_query("SELECT `" . OCC_TABLE_REVIEWER . "`.`email` FROM `" . OCC_TABLE_REVIEWER . "`, `" . OCC_TABLE_PAPERADVOCATE . "` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`='" . safeSQLstr($sid) . "' AND `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`")) + && (ocsql_num_rows($unassign_r2) == 1) + && ($unassign_l2 = ocsql_fetch_assoc($unassign_r2)) + ) { + $mailto = $unassign_l2['email']; + } + // delete assignment + oc_deleteAssignments($sid, $_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid'], 'reviewer', 'reviewer'); + // notify + list($mailsubject, $mailbody) = oc_getTemplate('committee-reviewunassign'); + $mailsubject = oc_replaceVariables($mailsubject, $unassign_l1); + $mailbody = oc_replaceVariables($mailbody, $unassign_l1); + sendEmail($mailto, $mailsubject, $mailbody, 1); + } + } + } + // show reviews + $q = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`, `" . OCC_TABLE_PAPERREVIEWER . "`.`score`, " . $formatField . ", `title`, `type`, `completed`" . $extraFields . " FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_PAPER . "` WHERE `reviewerid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` ORDER BY CAST(`completed` AS CHAR), `paperid`"; + $r = ocsql_query($q) or err("Unable to retrieve submissions for review"); + if (ocsql_num_rows($r) == 0) { + print '' . safeHTMLstr(oc_('You do not have any submissions to review.')) . '

    '; + } else { + print '

    ' . sprintf(oc_('A blank review form (that opens in a separate window) is available for you to print out if you prefer writing it out before typing it in.'), 'review.php?pid=blank') . '

    '; + print '
    ' . safeHTMLstr(oc_('Legend:')) . '    o    ' . safeHTMLstr(oc_('Review completed')) . ($showReviewScore ? (' (' . oc_('Score') . ')') : '') . '      x    ' . safeHTMLstr(oc_('Review not yet completed')) . '


    '; + if ($OC_configAR['OC_reviewerUnassignReviews'] == 1) { + print ''; + } + print ''; + if ($OC_configAR['OC_reviewerUnassignReviews'] == 1) { + print ''; + $extraCols++; // do it here so it doesn't impact advocate table + } + print '' . (!empty($abstractCol) ? ('') : ''); + if ($OC_trackType) { + //T: Type = Submission Type (e.g., paper, poster) + print ''; + } + print $fileTableHeader . ''; + $row = 1; + $OC_downloadZipAR = array(); + while ($p = ocsql_fetch_array($r)) { + if ($p['completed'] == "T") { + $bgcolor = '#afa'; + $symbol = (($showReviewScore && preg_match("/^\d+$/", $p['score'])) ? $p['score'] : 'o'); + } + else { + $bgcolor = '#fcc'; + $symbol = 'x'; + } + print ''; + if ($OC_configAR['OC_reviewerUnassignReviews']) { + print ''; + } + print ''; + if (!empty($abstractCol)) { + print ''; + } + if ($OC_trackType) { + print ''; + } + print oc_printFileCells($p) . "\n"; + $row = $rowAR[$row]; + } + if (class_exists('ZipArchive')) { + if (oc_hookSet('print_file_cells_zip')) { + $str = call_user_func($GLOBALS['OC_hooksAR']['print_file_cells_zip'][0], $row, ($extraCols + 2)); // only one hook allowed here + print $str; + } elseif (isset($OC_downloadZipAR[1]) && ($OC_downloadZipAR[1] > 1)) { + print ''; + } + } + print "
    * ' . safeHTMLstr(oc_('Title - click for review form')) . '' . safeHTMLstr(oc_($abstractCol)) . '' . safeHTMLstr(oc_('Type')) . '
     ' . $symbol . ' ' . $p['paperid'] . ' - ' . safeHTMLstr($p['title']) . '' . safeHTMLstr(oc_('view abstract')) . '' . varValue('type', $p, ' ', true) . '
     ' . safeHTMLstr(oc_('Download All')) . '
    ZIP
    \n"; + if ($OC_configAR['OC_reviewerUnassignReviews']) { + print '
    *
    '; + $extraCols--; // undo it here so it doesn't impact advocate table + } + } + print ''; + } +} + +if (($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] == "T") && $OC_statusAR['OC_pc_signin_open']) { + $extraFields = ''; + $extraGroupByFields = ''; + + if (! $OC_statusAR['OC_rev_signin_open']) { + print '
    ' . safeHTMLstr(oc_('View Submissions')) . '

    '; + if (oc_hookSet('committee-menu-prereview')) { + foreach ($OC_hooksAR['committee-menu-prereview'] as $v) { + print '
    • ' . $v . '

    '; + } + } + if (oc_hookSet('committee-menu-pc-prereview') && ($_SESSION[OCC_SESSION_VAR_NAME]['acpc'] == "T") && $OC_statusAR['OC_pc_signin_open']) { + foreach ($OC_hooksAR['committee-menu-pc-prereview'] as $v) { + print '
    • ' . $v . '

    '; + } + } + } + if ($OC_configAR['OC_paperAdvocates'] && $OC_statusAR['OC_advocating_open']) { + print ' +
    ' . safeHTMLstr(oc_('Submissions to Advocate:')) . '
    +

    +'; + $q = "SELECT `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`, `" . OCC_TABLE_PAPERADVOCATE . "`.`adv_recommendation`, " . $formatField . ", `title`, `type`, AVG(`score`) AS `paperavg`" . $extraFields . " FROM (`" . OCC_TABLE_PAPERADVOCATE . "`, `" . OCC_TABLE_PAPER . "`) LEFT JOIN `" . OCC_TABLE_PAPERREVIEWER . "` ON `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`=`" . OCC_TABLE_PAPERREVIEWER . "`.`paperid` WHERE `" . OCC_TABLE_PAPERADVOCATE . "`.`advocateid`='" . safeSQLstr($_SESSION[OCC_SESSION_VAR_NAME]['acreviewerid']) . "' AND `" . OCC_TABLE_PAPERADVOCATE . "`.`paperid`=`" . OCC_TABLE_PAPER . "`.`paperid` GROUP BY `paperid`, `adv_recommendation`, " . $formatField . ", `title`, `type`" . $extraGroupByFields . " ORDER BY " . $advocateOrder; + $r = ocsql_query($q) or err("Unable to retrieve submissions for advocating"); + if (ocsql_num_rows($r) == 0) { + print '' . safeHTMLstr(oc_('You do not have any submissions to advocate.')) . '

    '; + } else { + //T: Recom. = Recommendation (e.g., Accept, Reject) [abbreviate if possible]; Score = Average reviews score + print '' . (!empty($abstractCol) ? ('') : ''); + if ($OC_trackType) { + //T: Type = Submission Type (e.g., paper, poster) + print ''; + } + print $fileTableHeader . ''; + $row = 1; + $OC_downloadZipAR = array(); + while ($p = ocsql_fetch_array($r)) { + if ($p['paperavg'] != '') { + $usescore = number_format($p['paperavg'], 2); + } else { + $usescore = '–'; + } + + print ''; + if (!empty($abstractCol)) { + print ' '; + } + + if ($OC_trackType) { + print ''; + } + print oc_printFileCells($p) . "\n"; + $row = $rowAR[$row]; + } + if (class_exists('ZipArchive')) { + if (oc_hookSet('print_file_cells_zip')) { + $str = call_user_func($GLOBALS['OC_hooksAR']['print_file_cells_zip'][0], $row, ($extraCols + 3), 1); // only one hook allowed here + print $str; + } elseif (isset($OC_downloadZipAR[1]) && ($OC_downloadZipAR[1]['count'] > 1)) { + print ''; + } + } + print "
    ' . safeHTMLstr(oc_('Recom.')) . '' . safeHTMLstr(oc_('Score')) . '' . safeHTMLstr(oc_('Title - click for recommendation form')) . '' . safeHTMLstr(oc_($abstractCol)) . '' . safeHTMLstr(oc_('Type')) . '
    '. safeHTMLstr($p['adv_recommendation']) . '' . $usescore . '' . $p['paperid'] . ' - ' . safeHTMLstr($p['title']) . '' . safeHTMLstr(oc_('view abstract')) . '' . varValue('type', $p, ' ', true) . '
     ' . safeHTMLstr(oc_('Download All')) . '
    ZIP
    \n"; + } + print '

    '; + } +} +print "
    \n"; + +if (!empty($OC_configAR['OC_committeeFooter'])) { + print '
    ' . (preg_match("/\<(?:p|br) ?\/?\>/", $OC_configAR['OC_committeeFooter']) ? oc_($OC_configAR['OC_committeeFooter']) : nl2br(oc_($OC_configAR['OC_committeeFooter']))) . '
    '; +} + +printFooter(); + +?> diff --git a/review/show_abstract.php b/review/show_abstract.php new file mode 100644 index 0000000..6e273d0 --- /dev/null +++ b/review/show_abstract.php @@ -0,0 +1,125 @@ + $aval) { + if (preg_match("/^(?:paperid|position)$/", $akey)) { continue; } + $spl[$akey . $apos] = $aval; + } +} +$oc_authorNum = $apos; + +// Get topics +$qt = "SELECT `topicid` FROM `" . OCC_TABLE_PAPERTOPIC . "` WHERE `paperid`='" . safeSQLstr($pid) . "'"; +$rt = ocsql_query($qt) or err("Unable to get topics "); +$spl['topics'] = array(); +while ($t = ocsql_fetch_array($rt)) { + $spl['topics'][] = $t['topicid']; +} + +// Display fields +print ' + + +'; + +oc_showFieldSet($OC_submissionFieldSetAR, $OC_submissionFieldAR, $spl, $blind, true, $showReferenceSites); + +print '
    ' . oc_('Submission ID') . ':' . safeHTMLstr($pid) . '
    '; + +if (oc_hookSet('committee-show-abstract')) { + foreach ($GLOBALS['OC_hooksAR']['committee-show-abstract'] as $v) { + require_once $v; + } +} + +printFooter(); + +?> diff --git a/review/show_reviews.php b/review/show_reviews.php new file mode 100644 index 0000000..14488b7 --- /dev/null +++ b/review/show_reviews.php @@ -0,0 +1,91 @@ +' . safeHTMLstr($sl['title']) . '
    ' . sprintf(oc_('Submission ID %s'), safeHTMLstr($_GET['pid'])); +if (!empty($sl['type'])) { + $subtype = $sl['type']; + print '
    (' . safeHTMLstr($subtype) . ')'; +} else { + $subtype = ''; +} +print '

    '; + +if ($OC_configAR['OC_reviewerSeeOtherReviewers'] && $assigned && ($emailList = getPaperReviewersEmail($_GET['pid']))) { + print '

    ' . oc_('Email Reviewers') . '

    '; +} + +// Display reviews +$q = "SELECT `" . OCC_TABLE_PAPERREVIEWER . "`.*, CONCAT_WS(' ',`" . OCC_TABLE_REVIEWER . "`.`name_first`,`" . OCC_TABLE_REVIEWER . "`.`name_last`) as `name` FROM `" . OCC_TABLE_PAPERREVIEWER . "`, `" . OCC_TABLE_REVIEWER . "` WHERE `" . OCC_TABLE_PAPERREVIEWER . "`.`paperid`='" . safeSQLstr($_GET['pid']) . "' AND `" . OCC_TABLE_PAPERREVIEWER . "`.`reviewerid`=`" . OCC_TABLE_REVIEWER . "`.`reviewerid`"; +$r = ocsql_query($q) or err("Unable to get information"); +if (ocsql_num_rows($r) == 0) { + warn(oc_('No reviews found')); +} +displayReviews($_GET['pid'], $r, $subtype); + +printFooter(); + +?> diff --git a/review/signin.php b/review/signin.php new file mode 100644 index 0000000..b100bad --- /dev/null +++ b/review/signin.php @@ -0,0 +1,162 @@ +' . oc_('Committee sign-in is closed') . '

    '; + printFooter(); + exit; +} + +if (oc_hookSet('committee-signin')) { + foreach ($GLOBALS['OC_hooksAR']['committee-signin'] as $hook) { + require_once $hook; + } +} + +session_regenerate_id(); // prevent login session fixation + +$vformar[1] = "lkalskjo24uakd"; +$vformar[2] = "lkiqwje0913284"; +$vformar[3] = "loj0923489wefs"; + +$errmsg = ""; + +if (isset($_POST['ocaction']) && ($_POST['ocaction'] == "Sign In")) { + // Check for bad uname or pwd + if (!preg_match("/^[\p{L}\p{Nd}_\.\-\@]{5,50}$/u",$_POST['uname']) || empty($_POST['upwd'])) { + //T: Use care with href - "mailto" and "subject" should not be translated + $errmsg = '' . sprintf(oc_('Username and/or password not valid. Please try again. If you continue to have a problem signing in, please contact the Chair.'), $OC_configAR['OC_pcemail']) . '

    '; + } else { + $lowusername = oc_strtolower(trim($_POST['uname'])); + $q = "SELECT `reviewerid`, `name_last`, `name_first`, `password`, `onprogramcommittee` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `username`='" . safeSQLstr($lowusername) . "'"; + $r = ocsql_query($q) or err("Unable to query database"); + // Check for multiple matching usernames + if (($rnum=ocsql_num_rows($r)) > 1) { + printHeader(safeHTMLstr(oc_('Sign In'))); + err("Multiple usernames"); + } + // Check for unknown username + if ($rnum == 0) { + //T: Use care with href - "mailto" and "subject" should not be translated + $errmsg = '' . sprintf(oc_('Incorrect username or password. Please try again. If you continue to have a problem signing in, please contact the Chair.'), $OC_configAR['OC_pcemail']) . '

    '; + } else { + $p = ocsql_fetch_array($r); + // Check that sign-in is still open for user + if (!$OC_statusAR['OC_rev_signin_open']) { + if ($p['onprogramcommittee'] == "F") { + signInClosed(); + } elseif (!$OC_statusAR['OC_pc_signin_open']) { + signInClosed(); + } + } + // Check for bad pwd + if (!oc_password_verify($_POST['upwd'], $p['password'], 'committee', $p['reviewerid'])) { + $errmsg = ' +' . sprintf(oc_('Incorrect username or password. Please try again below or click here to reset your password.'), 'reset.php') . ' +

    + '; + } else { // We have a winner! + oc_committeeSignIn($p, $lowusername); + } + } + } + // Weak attempt at catching multiple failed logins + if ($_POST['validform'] == $vformar[1]) { $vform = $vformar[2]; } + else { + $vform = $vformar[3]; + if ($_POST['validform'] == $vformar[3]) { + $errmsg .= ' +' . oc_('If you click the "forgot" links, we will be glad to help you out.') . '

    + '; + } + } +} +else { + $vform = $vformar[1]; +} + +printHeader(oc_('Sign In'),3); + +if (!empty($errmsg)) { + print $errmsg; +} +elseif (isset($_GET['e']) && ($_GET['e'] == "exp")) { + print '

    ' . safeHTMLstr(oc_('Your session has timed out or you did not sign in properly. Please sign in again.')) . '

    '; + if (isset($_SESSION[OCC_SESSION_VAR_NAME]['POST']['submit'])) { + print '

    ' . safeHTMLstr(oc_('It appears you were filling out a review form -- by signing back in right now with the same username, you will have the option to save the review.')) . '

    '; + } + +} + +print ' +
    +
    + + + + + +
    ( ' . oc_('forgot username?') . ' )
    ( ' . safeHTMLstr(oc_('forgot password?')) . ' )

    + +
    +

    + +'; + +if ($OC_configAR['OC_ReviewerTimeout'] > 0) { + print '

    ' . safeHTMLstr(sprintf(oc_('Note: Session times out after %d minutes of inactivity'), $OC_configAR['OC_ReviewerTimeout'])) . '

    '; +} + + +printFooter(); + +?> diff --git a/review/signout.php b/review/signout.php new file mode 100644 index 0000000..783fede --- /dev/null +++ b/review/signout.php @@ -0,0 +1,32 @@ + diff --git a/review/signup.php b/review/signup.php new file mode 100644 index 0000000..336c298 --- /dev/null +++ b/review/signup.php @@ -0,0 +1,161 @@ +sign out first before trying to create a new account.'), 'signout.php'), $hdr, $hdrfn); + printFooter(); + exit; +} + +oc_sendNoCacheHeaders(); + +require_once OCC_FORM_INC_FILE; +require_once OCC_COMMITTEE_INC_FILE; + +if (oc_hookSet('committee-signup-pre')) { + foreach ($GLOBALS['OC_hooksAR']['committee-signup-pre'] as $hook) { + require_once $hook; + } +} + +// Verify keycode +$programKeycodeAR = explode(',', $OC_configAR['OC_keycode_program']); +$reviewerKeycodeAR = explode(',', $OC_configAR['OC_keycode_reviewer']); +if ($OC_configAR['OC_paperAdvocates'] && isset($_POST['keycode']) && in_array($_POST['keycode'], $programKeycodeAR)) { + printHeader(oc_('Program Committee Signup'), 3); + if (! $OC_statusAR['OC_pc_signup_open']) { + warn(oc_('Committee sign-up is closed')); + } + $committee = "program"; + $committeeTrans = oc_('Program Committee'); + $oncommittee = "T"; + $signUpNotice = $OC_configAR['OC_programSignUpNotice']; +} +elseif (isset($_POST['keycode']) && in_array($_POST['keycode'], $reviewerKeycodeAR)) { + printHeader(oc_('Reviewer Committee Signup'), 3); + if (! $OC_statusAR['OC_rev_signup_open']) { + warn(oc_('Committee sign-up is closed')); + } + $committee = "reviewer"; + $committeeTrans = oc_('Review Committee'); + $oncommittee = "F"; + $signUpNotice = $OC_configAR['OC_reviewerSignUpNotice']; +} else { + warn(oc_('The keycode entered is incorrect. Please click on the Back button to try again. If you are still unable to access the committee sign up page, please contact the Chair.'), $hdr, $hdrfn); +} + +if (isset($_POST['ocaction']) && ($_POST['ocaction'] == "Sign Up")) { + $err = ''; + $qfields = array(); + $tfields = array(); + + require_once 'committee-validate.inc'; + + if (!empty($err)) { + print '
    ' . oc_('Please check the following:') . '
      ' . $err . '
    '; + } else { // let's submit + $q = "INSERT INTO `" . OCC_TABLE_REVIEWER . "` SET `onprogramcommittee`='" . $oncommittee . "', `signupdate`='" . safeSQLstr(date("Y-m-d")) . "'"; + foreach ($qfields as $qid => $qval) { + $q .= ", `" . $qid . "`=" . $qval; + } + $r = ocsql_query($q) or err("unable to submit form"); + $rid = ocsql_insert_id() or err("unable to get reviewer id"); + + // add topic(s) + if (!empty($tfields)) { + $q = "INSERT INTO `" . OCC_TABLE_REVIEWERTOPIC . "` (`reviewerid`,`topicid`) VALUES"; + foreach ($tfields as $t) { + $q .= " ($rid,$t),"; + } + $r = ocsql_query(rtrim($q, ',')) or err("unable to add reviewer topic, but account created "); + } + + $confirmmsg = ' +

    ' . oc_('Thank you for signing up. We have emailed you a confirmation with your information.') . '

    +

    ' . +//T: Use care when translating the href - "mailto" and "subject" are not translated. %2%s = event short name (e.g., CONF2012) +sprintf(oc_('If you have any questions, please contact the Chair'), $OC_configAR['OC_pcemail'], $OC_configAR['OC_confName']) . '

    +'; + + // ocIgnore included so poEdit picks up (DB) template translation + $ocIgnoreSubject = oc_('Committee Signup'); + //T: [:OC_confName:] is the event name; [:committee:] will be either "Program Committee" or "Review Committee"; [:OC_pcemail:] is an email address + $ocIgnoreBody = oc_('Thank you for signing up for the [:OC_confName:] [:committee:]. Below is the information you provided. If you have any questions, please contact [:OC_pcemail:] or reply to this email. + +[:fields:]'); + + list($mailsubject, $mailbody) = oc_getTemplate('committee-signup'); + $fields = oc_genFieldMessage($OC_reviewerFieldSetAR, $OC_reviewerFieldAR, $_POST); + $templateExtraAR = array( + 'committee' => $committeeTrans, + 'fields' => oc_('Reviewer ID') . ': ' . $rid . "\n\n" . $fields + ); + $mailsubject = oc_replaceVariables($mailsubject, $templateExtraAR); + $mailbody = oc_replaceVariables($mailbody, $templateExtraAR); + + if (oc_hookSet('committee-signup-add')) { + foreach ($GLOBALS['OC_hooksAR']['committee-signup-add'] as $hook) { + require_once $hook; + } + } + + print $confirmmsg; + + sendEmail($_POST['email'], $mailsubject, $mailbody, $OC_configAR['OC_notifyReviewerSignup']); + + printFooter(); + exit; + } +} + +// Display notice & form +if (!empty($signUpNotice)) { + print '
    ' . (preg_match("/\<(?:p|br) ?\/?\>/", $signUpNotice) ? oc_($signUpNotice) : nl2br(oc_($signUpNotice))) . '


    '; +} + +print ' +
    + + +'; + +oc_displayFieldSet($OC_reviewerFieldSetAR, $OC_reviewerFieldAR, $_POST); + +if (oc_hookSet('committee-signup-fields')) { + foreach ($GLOBALS['OC_hooksAR']['committee-signup-fields'] as $hook) { + require_once $hook; + } +} + +print ' +
    +
    +

    ' . oc_('The confirmation email will be sent to:') . '

    +

    +
    +
    + +

    + + +'; + +printFooter(); + +?> diff --git a/review/update.php b/review/update.php new file mode 100644 index 0000000..c772b32 --- /dev/null +++ b/review/update.php @@ -0,0 +1,212 @@ + $fsar) { // remove from fieldset + if (in_array('consent', $fsar['fields'])) { + $OC_reviewerFieldSetAR[$fsid]['fields'] = array_diff($OC_reviewerFieldSetAR[$fsid]['fields'], array('consent')); + continue; // field should only be in one fieldset + } + } + } +} + +// Process submission +if (isset($_POST['ocaction']) && ($_POST['ocaction'] == "Update Profile")) { + // Check for valid submission + if ( $chair ) { + if ( !validToken('chair') ) { + warn(oc_('Invalid submission')); + } + } elseif ( ! validToken('ac') ) { + warn(oc_('Invalid submission')); + } + + $err = ''; + $qfields = array(); + $tfields = array(); + + require_once 'committee-validate.inc'; + + if (!empty($err)) { + print '
    ' . oc_('Please check the following:') . '
      ' . $err . '

    '; + } else { + // check password + $q = "SELECT `password` FROM `" . OCC_TABLE_REVIEWER . "` WHERE `reviewerid`='" . safeSQLstr($rid) . "'"; + $r = ocsql_query($q) or err('Unable to retrieve reviewer information'); + $rinfo = ocsql_fetch_array($r); + if ($chair || oc_password_verify($_POST['oldpwd'], $rinfo['password'])) { + // Update fields + $q = "UPDATE `" . OCC_TABLE_REVIEWER . "` SET `lastupdate`='" . safeSQLstr(date('Y-m-d')) . "', "; + foreach ($qfields as $qid => $qval) { + $q .= "`" . $qid . "`=" . $qval . ", "; + } + $q = rtrim($q, ', '); + $q .= " WHERE `reviewerid`='" . safeSQLstr($rid) . "' LIMIT 1"; + ocsql_query($q) or err('Unable to update database'); + + // Update topics + issueSQL("DELETE FROM `" . OCC_TABLE_REVIEWERTOPIC . "` WHERE `reviewerid`='" . safeSQLstr($rid) . "'"); + if (!empty($tfields)) { + $q = "INSERT INTO `" . OCC_TABLE_REVIEWERTOPIC . "` (`reviewerid`,`topicid`) VALUES"; + foreach ($tfields as $t) { + $q .= " (" . safeSQLstr($rid) . ",$t),"; + } + $r = ocsql_query(rtrim($q, ',')) or err("unable to add reviewer topic, but account created "); + } + + if ($chair) { // display back links + print ''; + } else { + print '

    ' . sprintf(oc_('Your profile has been successfully updated. Return to the main Committee page.'), 'reviewer.php') . '

    '; + + // ocIgnore included so poEdit picks up (DB) template translation + $ocIgnoreSubject = oc_('Committee Member Profile Updated'); + $ocIgnoreBody = oc_('Your profile has been updated. The submitted information follows below: + +[:fields:]'); + + list($mailsubject, $mailbody) = oc_getTemplate('committee-update'); + $fields = oc_genFieldMessage($OC_reviewerFieldSetAR, $OC_reviewerFieldAR, $_POST); + $templateExtraAR = array( + 'fields' => oc_('Username') . ": " . $_SESSION[OCC_SESSION_VAR_NAME]['acusername'] . "\n\n" . $fields + ); + $mailsubject = oc_replaceVariables($mailsubject, $templateExtraAR); + $mailbody = oc_replaceVariables($mailbody, $templateExtraAR); + + if (oc_hookSet('committee-signup-update')) { + foreach ($GLOBALS['OC_hooksAR']['committee-signup-update'] as $hook) { + require_once $hook; + } + } + + sendEmail($_POST['email'], $mailsubject, $mailbody, $OC_configAR['OC_notifyReviewerProfileUpdate']); + } + + printFooter(); + + // log + oc_logit('committee', 'Member ID ' . $rid . ' profile edited' . ($chair ? ' by Chair' : '')); + + exit; + } else { + print '

    ' . oc_('Current password is not correct') . '


    '; + } + } + $postFields = $_POST; +} else { // not submitting + // get stored values + $q = "SELECT * FROM `" . OCC_TABLE_REVIEWER . "` WHERE `reviewerid`='" . safeSQLstr($rid) . "'"; + $r = ocsql_query($q) or err("Unable to retrieve reviewer information"); + $postFields = array_merge((array)$_POST, ocsql_fetch_assoc($r)); + // Get list of reviewer topics + $tq = "SELECT * FROM `" . OCC_TABLE_REVIEWERTOPIC . "` WHERE `reviewerid`='" . safeSQLstr($rid) . "'"; + $tr = ocsql_query($tq) or err("Unable to retrieve topics"); + $postFields['topics'] = array(); + while ($tl = ocsql_fetch_assoc($tr)) { + $postFields['topics'][] = $tl['topicid']; + } + if ( isset($OC_reviewerFieldAR['topics']['type']) && ($OC_reviewerFieldAR['topics']['type'] == 'radio') && isset($postFields['topics'][0]) ) { + $postFields['topics'] = $postFields['topics'][0]; + } +} + +print ' +
    + +'; + +if ( $chair ) { + print ' + + + +'; +} else { + print ' +

    ' . oc_('Make the changes you want below, then enter your password for verification and click the Update Profile button at the bottom.') . '

    + +'; +} + +oc_displayFieldSet($OC_reviewerFieldSetAR, $OC_reviewerFieldAR, $postFields); + +if (! $chair ) { + print ' +' . oc_('Enter your current password and click the Update Profile button') . '

    +' . oc_('Current Password') . ': +      +'; +} + +print ' + +

    +'; + +printFooter(); + +?> \ No newline at end of file diff --git a/upgrade/.htaccess b/upgrade/.htaccess new file mode 100644 index 0000000..8d2f256 --- /dev/null +++ b/upgrade/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/upgrade/index.html b/upgrade/index.html new file mode 100644 index 0000000..e69de29 diff --git a/upgrade/index.php b/upgrade/index.php new file mode 100644 index 0000000..e69de29 diff --git a/upgrade/upgrade-5.31-6.00.inc b/upgrade/upgrade-5.31-6.00.inc new file mode 100644 index 0000000..66cffc3 --- /dev/null +++ b/upgrade/upgrade-5.31-6.00.inc @@ -0,0 +1,73 @@ + 0)) { + while ($upgradel = ocsql_fetch_assoc($upgrader)) { + $subtypes[] = preg_replace("/,/", ";", $upgradel['sub_type']); + } + } else { + $subtypes[] = 'Paper'; + } + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_subtypes', '" . safeSQLstr(implode(',', $subtypes)) . "', 'Sub. Types', 'Internal Use Only', 0)"); + ocsql_query("DELETE FROM `" . OCC_TABLE_MODULES . "` WHERE `moduleId`='oc_subtype' LIMIT 1"); +} else { + ocsql_query("ALTER TABLE `" . OCC_TABLE_PAPER . "` ADD `type` VARCHAR(255) NULL"); + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_subtypes', 'Paper', 'Sub. Types', 'Internal Use Only', 0)"); +} + +if ($OC_configAR['OC_includeSubmissionUploadField'] != 1) { + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`=CONCAT(`value`, ',fs_content:file') WHERE `module`='OC' AND `setting`='OC_hideSubFields' LIMIT 1"); +} + +ocsql_query("ALTER TABLE `" . OCC_TABLE_AUTHOR . "` ADD `orcid` VARCHAR(30) NULL"); + +ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`=CONCAT(`value`, ',fs_authors:orcid') WHERE `module`='OC' AND `setting`='OC_hideSubFields' LIMIT 1"); + +ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_editAcceptedOnly', '0', 'Edit Accepted Only', 'Restrict Edit Submission to accepted submissions only (1=Accepted only, 0=All)', 0)"); + +ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_includeReferenceSearchLinks', '1', 'Include Reference Service Links', 'Include reference service links on committee abstract page (1=Yes, 0=No)', 0)"); + + +ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_wordForAuthor', 'Author', 'Word for Author', 'English word to be used for Author (e.g., Author, Presenter, Applicant); must pluralize with s at the end', 0)"); + +ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_wordForChair', 'Chair', 'Word for Chair', 'English word to be used for Chair (e.g., Chair, Administrator, Editor)', 0)"); + +if ($OC_configAR['OC_includeSubmissionUploadLink'] == 1) { + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_subConfirmNotice', '

    Thank you for your submission. Your submission ID number is [:sid:]. Please write this number down and include it in any communications with us.

    \n\n

    Below is the information submitted. We have also emailed a copy to the submission contact. If you notice any problems or do not receive the email within 24 hours, please contact us.

    \n\n

    >>> Proceed to upload file

    \n\n
    \n

    [:formfields:]

    ', 'Sub. Confirm Notice', 'Notice displayed on Make Submission confirmation page. Variables: [:sid:] = submission ID, [:formfields:] = form fields', 0)"); +} else { + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_subConfirmNotice', '

    Thank you for your submission. Your submission ID number is [:sid:]. Please write this number down and include it in any communications with us.

    \n\n

    Below is the information submitted. We have also emailed a copy to the submission contact. If you notice any problems or do not receive the email within 24 hours, please contact us.

    \n\n

    [:formfields:]

    ', 'Sub. Confirm Notice', 'Notice displayed on Make Submission confirmation page. Variables: [:sid:] = submission ID, [:formfields:] = form fields', 0)"); +} +ocsql_query("UPDATE `" . OCC_TABLE_MODULES . "` SET `moduleId`='oc_formfields' WHERE `moduleId`='oc_customforms' LIMIT 1"); + +if ($OC_configAR['OC_trackStudent'] != 1) { + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`=CONCAT(`value`, ',fs_general:student') WHERE `setting`='OC_hideSubFields' LIMIT 1"); +} + +ocsql_query("ALTER TABLE `" . OCC_TABLE_PAPERREVIEWER . "` ADD `score` TINYINT UNSIGNED NULL AFTER `updated`"); + +ocsql_query("ALTER TABLE `" . OCC_TABLE_PAPERREVIEWER . "` CHANGE `recommendation` `recommendation` TINYINT UNSIGNED NULL DEFAULT NULL"); + +ocsql_query("UPDATE `" . OCC_TABLE_PAPERREVIEWER . "` SET `score`=`recommendation`"); + +ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='6.00' WHERE `setting`='OC_version'"); + +ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='6.00' WHERE `setting`='OC_versionLatest'"); diff --git a/upgrade/upgrade-6.00-6.01.inc b/upgrade/upgrade-6.00-6.01.inc new file mode 100644 index 0000000..c261c02 --- /dev/null +++ b/upgrade/upgrade-6.00-6.01.inc @@ -0,0 +1,14 @@ +

    We were unable to edit the config.php file. Please edit the file using a plain text or code editor and add the following lines to the end, then click the Continue with Upgrade button.

    Be sure to use standard quotes and that they are not converted to smart or curly quotes.

    + +
    + + +

    +
    +'; + printFooter(); + exit; + } +} else { + $enckeyok = true; +} + +if ($enckeyok) { + $upgradeModulesAR = array('captcha', 'mail', 'oc_ieee_copyright', 'oc_ithenticate', 'oc_payment', 'oc_program', 'oc_revupload', 'oc_subpayment'); + + ocsql_query("ALTER TABLE `" . OCC_TABLE_PAPER . "` CHANGE `submissiondate` `submissiondate` DATE NOT NULL"); + + ocsql_query("ALTER TABLE `" . OCC_TABLE_PAPER . "` ADD `consent` text AFTER `lastupdate`"); + + ocsql_query("ALTER TABLE `" . OCC_TABLE_REVIEWER . "` ADD `signupdate` date DEFAULT NULL AFTER `comments`, ADD `consent` text AFTER `lastsignin`"); + + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_authorViewSubIfEditClosed', '0', 'View Sub. if Edit Closed', 'Allow author to view submission if editing is closed (1=Yes, 0=No (default)', 0)"); + + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_privacy_display', '0', 'Privacy Policy Link Display', 'Whether and where to display a Privacy Policy Link (0: none, 1: menu, 2: page footer).', 0)"); + + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_privacy_link', '', 'Privacy Policy Web Address', 'Full web address for privacy policy on remote site. Leave blank to use built-in privacy template.', 0)"); + + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_chairMFA', '', 'Chair Multi-Factor Authentication', 'Enter email address to receive authentication code or leave blank to disable', 0)"); + + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_chairMFAcode', '', 'Chair MFA Code', 'for internal use', 0)"); + + ocsql_query("INSERT INTO `" . OCC_TABLE_CONFIG . "` (`module`, `setting`, `value`, `name`, `description`, `parse`) VALUES ('OC', 'OC_privacy_banner_options', '{\"display\":0,\"message\":\"This website uses cookies to offer you a better user experience. By using this website, you agree to the placement of these cookies.\",\"dismiss\":\"Accept\",\"link\":\"\",\"href\":\"\"}', 'Cookie Banner Options', 'JSON-encoded list of attributes (display, message, dismiss, link, href)', 0)"); + + + ocsql_query("INSERT INTO `" . OCC_TABLE_TEMPLATE . "` VALUES ('privacy_policy', 'other', 'OC', 'Privacy Policy', '', '

    What information is being collected?

    \n\n

    For anyone browsing our web site, our server records the page visited, IP address where the request came from, and if included the browser type and referring web page.

    \n\n

    If you choose to make a submission, become a reviewer or advocate, or serve as a discussant or session chair, we will request your name, email address, and affiliation, along with possibly other information as denoted when filling out the respective form for each role.

    \n\n

    Who is collecting it?

    \n\n

    Information is collected by the entity and/or activity named atop this page. You may contact us by using the Email menu link above.

    \n\n

    How is it collected?

    \n\n

    Information used in this system is collected through the forms provided (e.g., submission, account sign up), or automatically through our server logs (e.g., page visited, IP address).

    \n\n

    Why is it being collected?

    \n\n

    Information is being collected in relation to the activity named atop this page and your optional participation in this activity.

    \n\n

    How will it be used?

    \n\n

    The information automatically recorded by our server is used to troubleshoot issues and improve our service. Other information collected is used for evaluation, communication, and publishing related to the activity specified above.

    \n\n

    Who will it be shared with?

    \n\n

    Information collected is shared with the organizers of the above activity. A subset of information may also be shared with other participants in the activity (e.g., reviewers). Some of the information (e.g., name, affiliation) of accepted submitters and other participants may also be made publicly available to meet the goals of the activity.

    \n\n

    By virtue of the information being hosted on a server, the information is accessible to our hosting provider and subject to their privacy policy. Additional third-party providers may include: payment processor, plagiarism detection service, copyright processing service, reviewer credit service, publishing service.

    \n\n

    How do I correct information or request its erasure?

    \n\n

    In order to correct information, submitters and committee members may use the Edit Submission and Update Profile options respectively. If these do not apply to you, are no longer accessible, or you wish to request erasure of your data, use the Email menu link above to contact us. We ask that you contact us as erasure of the data may impact others on the system and the activity specified above, thus requiring manual intervention and notification on our part.

    \n\n

    Are cookies or other trackers used?

    \n\n

    Cookies are used to maintain language selection and allow you to remain logged into your account without having to keep re-entering credentials. Cookies are removed upon signing out of your account or exiting your browser.

    ', NULL, NULL)"); + + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`=CONCAT(`value`, ',fs_consent:consent') WHERE `module`='OC' AND `setting`='OC_hideSubFields' LIMIT 1"); + + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`=CONCAT(`value`, ',fs_consent:consent') WHERE `module`='OC' AND `setting`='OC_hideCmtFields' LIMIT 1"); + + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='6.81' WHERE `setting`='OC_version'"); + + ocsql_query("UPDATE `" . OCC_TABLE_CONFIG . "` SET `value`='6.81' WHERE `setting`='OC_versionLatest'"); +} diff --git a/upgrade/upgrade-6.81-6.90.inc b/upgrade/upgrade-6.81-6.90.inc new file mode 100644 index 0000000..ed088e7 --- /dev/null +++ b/upgrade/upgrade-6.81-6.90.inc @@ -0,0 +1,18 @@ +Add the following line to the config.php file on your server:

    define(\'OCC_MAILPARAMS\', \'' . safeHTMLstr($OC_configAR['OC_mailParams']) . '\');

    Continuing with upgrade...

    '; +} +ocsql_query("DELETE FROM `" . OCC_TABLE_CONFIG . "` WHERE `module`='OC' AND `setting`='OC_mailParams' LIMIT 1"); diff --git a/upgrade/v b/upgrade/v new file mode 100644 index 0000000..c639bc7 --- /dev/null +++ b/upgrade/v @@ -0,0 +1 @@ +7.20