function run(Contact $user, $qreq, $ssel) { global $Conf; $o = cvtint($qreq->decision); $decision_map = $Conf->decision_map(); if ($o === null || !isset($decision_map[$o])) { return Conf::msg_error("Bad decision value."); } $result = Dbl::qe_raw($Conf->paperQuery($user, array("paperId" => $ssel->selection()))); $success = $fails = array(); while ($prow = PaperInfo::fetch($result, $user)) { if ($user->can_set_decision($prow, true)) { $success[] = $prow->paperId; } else { $fails[] = "#" . $prow->paperId; } } if (count($fails)) { Conf::msg_error("You cannot set paper decisions for " . pluralx($fails, "paper") . " " . commajoin($fails) . "."); } if (count($success)) { Dbl::qe("update Paper set outcome={$o} where paperId ?a", $success); $Conf->update_paperacc_setting($o > 0); redirectSelf(array("atab" => "decide", "decision" => $o)); } }
function save_password($email, $encoded_password, $iscdb = false) { global $Conf, $Now; $dblink = $iscdb ? Contact::contactdb() : $Conf->dblink; Dbl::qe($dblink, "update ContactInfo set password=?, passwordTime=? where email=?", $encoded_password, $Now, $email); ++$Now; }
static function enable($ids, $contact) { global $Conf; $result = $Conf->qe_raw("update ContactInfo set disabled=1 where contactId" . sql_in_numeric_set($ids) . " and password='' and contactId!=" . $contact->contactId); $result = Dbl::qe("update ContactInfo set disabled=0 where contactId" . sql_in_numeric_set($ids) . " and contactId!=" . $contact->contactId); if ($result && $result->affected_rows) { return self::modify_password_mail("password='' and contactId!=" . $contact->contactId, true, "create", $ids); } else { if ($result) { return (object) array("ok" => true, "warnings" => array("Those accounts were already enabled.")); } else { return (object) array("error" => true); } } }
static function tagreport($user, $prow) { $ret = (object) ["ok" => $user->can_view_tags($prow), "warnings" => [], "messages" => []]; if (!$ret->ok) { return $ret; } if ($vt = TagInfo::vote_tags()) { $myprefix = $user->contactId . "~"; $qv = $myvotes = array(); foreach ($vt as $tag => $v) { $qv[] = $myprefix . $tag; $myvotes[strtolower($tag)] = 0; } $result = Dbl::qe("select tag, sum(tagIndex) from PaperTag where tag ?a group by tag", $qv); while ($row = edb_row($result)) { $lbase = strtolower(substr($row[0], strlen($myprefix))); $myvotes[$lbase] += +$row[1]; } Dbl::free($result); $vlo = $vhi = array(); foreach ($vt as $tag => $vlim) { $lbase = strtolower($tag); if ($myvotes[$lbase] < $vlim) { $vlo[] = '<a class="q" href="' . hoturl("search", "q=editsort:-%23~{$tag}") . '">~' . $tag . '</a>#' . ($vlim - $myvotes[$lbase]); } else { if ($myvotes[$lbase] > $vlim && (!$prow || $prow->has_tag($myprefix . $tag))) { $vhi[] = '<span class="nw"><a class="q" href="' . hoturl("search", "q=sort:-%23~{$tag}+edit:%23~{$tag}") . '">~' . $tag . '</a> (' . ($myvotes[$lbase] - $vlim) . " over)</span>"; } } } if (count($vlo)) { $ret->messages[] = 'Remaining <a class="q" href="' . hoturl("help", "t=votetags") . '">votes</a>: ' . join(", ", $vlo); } if (count($vhi)) { $ret->warnings[] = 'Overallocated <a class="q" href="' . hoturl("help", "t=votetags") . '">votes</a>: ' . join(", ", $vhi); } } return $ret; }
function fix_one_delegation() { global $Conf; $row = Dbl::fetch_first_row("select r.paperId, r.contactId, u.email, q.ct, q.cs, r.reviewNeedsSubmit\n from PaperReview r\n left join (select paperId, requestedBy, count(reviewId) ct, count(reviewSubmitted) cs\n from PaperReview where reviewType<" . REVIEW_SECONDARY . "\n group by paperId, requestedBy) q\n on (q.paperId=r.paperId and q.requestedBy=r.contactId)\n left join ContactInfo u on (u.contactId=r.contactId)\n where r.reviewType=" . REVIEW_SECONDARY . " and r.reviewSubmitted is null\n and if(coalesce(q.ct,0)=0,1,if(q.cs=0,-1,0))!=r.reviewNeedsSubmit\n limit 1"); if (!$row) { return false; } $pid = (int) $row[0]; $req_cid = (int) $row[1]; $req_email = $row[2]; $prow = $Conf->paperRow(["paperId" => $pid], null); fwrite(STDERR, "Problem: #{$pid} review by {$req_email}\n"); fwrite(STDERR, " reviewNeedsSubmit {$row['5']}, " . plural($row[3] ?: 0, "delegate") . ", " . plural($row[4] ?: 0, "submitted delegate") . "\n"); $result = Dbl::qe("select l.* from ActionLog l where paperId=? order by logId asc", $pid); $proposals = $confirmations = []; while ($row = edb_orow($result)) { if ($row->contactId == $req_cid && preg_match('/\\ALogged proposal for (\\S+) to review/', $row->action, $m) && ($xid = Contact::id_by_email($m[1]))) { $proposals[$xid] = true; } else { if (preg_match('/\\AAdded External review by (\\S+)/', $row->action, $m) && ($pc = pcByEmail($m[1])) && $pc->can_administer($prow)) { $confirmations[$row->contactId] = $pc->contactId; } } } Dbl::free($result); foreach ($proposals as $xid => $x) { if (isset($confirmations[$xid])) { $result1 = Dbl::qe("update PaperReview set requestedBy=? where paperId=? and contactId=? and requestedBy=?", $req_cid, $pid, $xid, $confirmations[$xid]); $result2 = Dbl::qe("update PaperReview r, PaperReview q set r.reviewNeedsSubmit=0 where r.paperId=? and r.contactId=? and q.paperId=? and q.contactId=? and q.reviewSubmitted is not null", $pid, $req_cid, $pid, $xid); if ($result1->affected_rows || $result2->affected_rows) { return true; } } } error_log("Failed to resolve paper #{$pid} review by {$req_email}"); return false; }
static function enable($ids, $contact) { global $Conf; $old_logged_errors = Dbl::$logged_errors; Dbl::qe("update ContactInfo set disabled=1 where contactId ?a and password='' and contactId!=?", $ids, $contact->contactId); $disabled_cids = Dbl::fetch_first_columns("select contactId from ContactInfo where contactId ?a and disabled=1 and contactId!=?", $ids, $contact->contactId); if ($disabled_cids) { Dbl::qe("update ContactInfo set disabled=0 where contactId ?a", $disabled_cids); } if (Dbl::$logged_errors > $old_logged_errors) { return (object) ["error" => true]; } else { if (!count($disabled_cids)) { return (object) ["ok" => true, "warnings" => ["Those accounts were already enabled."]]; } else { $Conf->save_logs(true); foreach ($disabled_cids as $cid) { $Conf->log("Account enabled by {$contact->email}", $cid); } $Conf->save_logs(false); return self::modify_password_mail("password='' and contactId!=" . $contact->contactId, true, "create", $disabled_cids); } } }
private static function load_optdata($pid) { $result = Dbl::qe("select optionId, value, data from PaperOption where paperId=?", $pid); $optdata = array(); while ($row = edb_row($result)) { $optdata[$row[0] . "." . $row[1]] = $row[2]; } Dbl::free($result); return $optdata; }
function show_pset_table($pset) { global $Conf, $Me, $Now, $Profile, $LastPsetFix; echo '<div id="', $pset->urlkey, '">'; echo "<h3>", htmlspecialchars($pset->title), "</h3>"; if ($Me->privChair) { show_pset_actions($pset); } if ($pset->disabled) { echo "</div>\n"; return; } $t0 = $Profile ? microtime(true) : 0; // load students if ($Conf->opt("restrictRepoView")) { $view = "l2.link repoviewable"; $viewjoin = "left join ContactLink l2 on (l2.cid=c.contactId and l2.type=" . LINK_REPOVIEW . " and l2.link=l.link)\n"; } else { $view = "4 repoviewable"; $viewjoin = ""; } $result = Dbl::qe("select c.contactId, c.firstName, c.lastName, c.email,\n\tc.huid, c.github_username, c.seascode_username, c.anon_username, c.extension, c.disabled, c.dropped, c.roles, c.contactTags,\n\tgroup_concat(pl.link) pcid, group_concat(rpl.link) rpcid,\n\tr.repoid, r.cacheid, r.heads, r.url, r.open, r.working, r.lastpset, r.snapcheckat, {$view},\n\trg.gradehash, rg.gradercid, rg.placeholder, rg.placeholder_at\n\tfrom ContactInfo c\n\tleft join ContactLink l on (l.cid=c.contactId and l.type=" . LINK_REPO . " and l.pset={$pset->id})\n\t{$viewjoin}\n\tleft join Repository r on (r.repoid=l.link)\n\tleft join ContactLink pl on (pl.cid=c.contactId and pl.type=" . LINK_PARTNER . " and pl.pset={$pset->id})\n\tleft join ContactLink rpl on (rpl.cid=c.contactId and rpl.type=" . LINK_BACKPARTNER . " and rpl.pset={$pset->id})\n\tleft join RepositoryGrade rg on (rg.repoid=r.repoid and rg.pset={$pset->id})\n\twhere (c.roles&" . Contact::ROLE_PCLIKE . ")=0\n\tand (rg.repoid is not null or not c.dropped)\n\tgroup by c.contactId, r.repoid"); $t1 = $Profile ? microtime(true) : 0; $anonymous = $pset->anonymous; if (req("anonymous") !== null && $Me->privChair) { $anonymous = !!req("anonymous"); } $students = array(); while ($result && ($s = Contact::fetch($result))) { $s->set_anonymous($anonymous); Contact::set_sorter($s, req("sort")); $students[$s->contactId] = $s; // maybe lastpset links are out of order if ($s->lastpset < $pset) { $LastPsetFix = true; } } uasort($students, "Contact::compare"); $checkbox = $Me->privChair || !$pset->gitless && $pset->runners; $rows = array(); $max_ncol = 0; $incomplete = array(); $pcmembers = pcMembers(); $jx = []; foreach ($students as $s) { if (!$s->visited) { $row = (object) ["student" => $s, "text" => "", "ptext" => []]; $j = render_pset_row($pset, $students, $s, $row, $pcmembers, $anonymous); if ($s->pcid) { foreach (array_unique(explode(",", $s->pcid)) as $pcid) { if (isset($students[$pcid])) { $jj = render_pset_row($pset, $students, $students[$pcid], $row, $pcmembers, $anonymous); $j["partners"][] = $jj; } } } if ($row->sortprefix) { $j["boring"] = true; } $jx[$row->sortprefix . $s->sorter] = $j; $max_ncol = max($max_ncol, $row->ncol); if ($s->incomplete) { $u = $Me->user_linkpart($s); $incomplete[] = '<a href="' . hoturl("pset", array("pset" => $pset->urlkey, "u" => $u, "sort" => req("sort"))) . '">' . htmlspecialchars($u) . '</a>'; } } } if (count($incomplete)) { echo '<div id="incomplete_pset', $pset->id, '" style="display:none" class="merror">', '<strong>', htmlspecialchars($pset->title), '</strong>: ', 'Your grading is incomplete. Missing grades: ', join(", ", $incomplete), '</div>', '<script>jQuery("#incomplete_pset', $pset->id, '").remove().show().appendTo("#incomplete_notices")</script>'; } if ($checkbox) { echo Ht::form_div(hoturl_post("index", array("pset" => $pset->urlkey, "save" => 1))); } $sort_key = $anonymous ? "anon_username" : "username"; usort($jx, function ($a, $b) use($sort_key) { if (get($a, "boring") != get($b, "boring")) { return get($a, "boring") ? 1 : -1; } return strcmp($a[$sort_key], $b[$sort_key]); }); echo '<table class="s61', $anonymous ? " s61anonymous" : "", '" id="pa-pset' . $pset->id . '"></table>'; $jd = ["checkbox" => $checkbox, "anonymous" => $anonymous, "grade_keys" => array_keys($pset->grades), "gitless" => $pset->gitless, "gitless_grades" => $pset->gitless_grades, "urlpattern" => hoturl("pset", ["pset" => $pset->urlkey, "u" => "@", "sort" => req("sort")])]; $i = $nintotal = $last_in_total = 0; foreach ($pset->grades as $ge) { if (!$ge->no_total) { ++$nintotal; $last_in_total = $ge->name; } ++$i; } if ($nintotal > 1) { $jd["need_total"] = true; } else { if ($nintotal == 1) { $jd["total_key"] = $last_in_total; } } echo Ht::unstash(), '<script>pa_render_pset_table(', $pset->id, ',', json_encode($jd), ',', json_encode(array_values($jx)), ')</script>'; if ($Me->privChair && !$pset->gitless_grades) { echo "<div class='g'></div>"; $sel = array("none" => "N/A"); foreach (pcMembers() as $pcm) { $sel[$pcm->email] = Text::name_html($pcm); } $sel["__random__"] = "Random"; echo '<span class="nb" style="padding-right:2em">', Ht::select("grader", $sel, "none"), Ht::submit("setgrader", "Set grader"), '</span>'; } if (!$pset->gitless) { $sel = array(); foreach ($pset->runners as $r) { if ($Me->can_run($pset, $r)) { $sel[$r->name] = htmlspecialchars($r->title); } } if (count($sel)) { echo '<span class="nb" style="padding-right:2em">', Ht::select("runner", $sel), Ht::submit("runmany", "Run all"), '</span>'; } } if ($checkbox) { echo "</div></form>\n"; } if ($Profile) { $t2 = microtime(true); echo sprintf("<div>Δt %.06f DB, %.06f total</div>", $t1 - $t0, $t2 - $t0); } echo "</div>\n"; }
function assign_paper_pc($pids, $type, $reviewer, $extra = array()) { global $Conf; // check arguments assert($type == "lead" || $type == "shepherd" || $type == "manager"); if ($reviewer) { $revcid = is_object($reviewer) ? $reviewer->contactId : $reviewer; } else { $revcid = 0; } assert(is_int($revcid)); if (!is_array($pids)) { $pids = array($pids); } $px = array(); foreach ($pids as $p) { assert(is_object($p) && is_numeric($p->paperId) || is_numeric($p)); $px[] = (int) (is_object($p) ? $p->paperId : $p); } // make assignments if (isset($extra["old_cid"])) { $result = Dbl::qe("update Paper set {$type}ContactId=? where paperId" . sql_in_numeric_set($px) . " and {$type}ContactId=?", $revcid, $extra["old_cid"]); } else { $result = Dbl::qe("update Paper set {$type}ContactId=? where paperId" . sql_in_numeric_set($px), $revcid); } // log, update settings if ($result && $result->affected_rows) { $this->log_activity_for($revcid, "Set {$type}", $px); if (($type == "lead" || $type == "shepherd") && !$revcid != !$Conf->setting("paperlead")) { $Conf->update_paperlead_setting(); } if ($type == "manager" && !$revcid != !$Conf->setting("papermanager")) { $Conf->update_papermanager_setting(); } return true; } else { return false; } }
function run(Contact $user, $qreq, $ssel) { global $Conf; $mt = $qreq->assignfn; $mpc = (string) $qreq->markpc; $pc = null; if ($mpc != "" && $mpc != "0") { $pc = Contact::find_by_email($mpc); } if ($mt == "auto") { $t = in_array($qreq->t, array("acc", "s")) ? $qreq->t : "all"; $q = join("+", $ssel->selection()); go(hoturl("autoassign", "pap={$q}&t={$t}&q={$q}")); } else { if ($mt == "lead" || $mt == "shepherd") { if ($user->assign_paper_pc($ssel->selection(), $mt, $pc)) { $Conf->confirmMsg(ucfirst(pluralx($ssel->selection(), $mt)) . " set."); } else { if ($OK) { $Conf->confirmMsg("No changes."); } } } else { if (!$pc) { Conf::msg_error("“" . htmlspecialchars($mpc) . "” is not a PC member."); } else { if ($mt == "conflict" || $mt == "unconflict") { if ($mt == "conflict") { Dbl::qe("insert into PaperConflict (paperId, contactId, conflictType) (select paperId, ?, ? from Paper where paperId" . $ssel->sql_predicate() . ") on duplicate key update conflictType=greatest(conflictType, values(conflictType))", $pc->contactId, CONFLICT_CHAIRMARK); $user->log_activity("Mark conflicts with {$mpc}", $ssel->selection()); } else { Dbl::qe("delete from PaperConflict where PaperConflict.conflictType<? and contactId=? and (paperId" . $ssel->sql_predicate() . ")", CONFLICT_AUTHOR, $pc->contactId); $user->log_activity("Remove conflicts with {$mpc}", $ssel->selection()); } } else { if (substr($mt, 0, 6) == "assign" && ($asstype = substr($mt, 6)) && isset(ReviewForm::$revtype_names[$asstype])) { Dbl::qe_raw("lock tables PaperConflict write, PaperReview write, PaperReviewRefused write, Paper write, ActionLog write, Settings write"); $result = Dbl::qe_raw("select Paper.paperId, reviewId, reviewType, reviewModified, conflictType from Paper left join PaperReview on (Paper.paperId=PaperReview.paperId and PaperReview.contactId=" . $pc->contactId . ") left join PaperConflict on (Paper.paperId=PaperConflict.paperId and PaperConflict.contactId=" . $pc->contactId . ") where Paper.paperId" . $ssel->sql_predicate()); $conflicts = array(); $assigned = array(); $nworked = 0; while ($row = PaperInfo::fetch($result, $user)) { if ($asstype && $row->conflictType > 0) { $conflicts[] = $row->paperId; } else { if ($asstype && $row->reviewType >= REVIEW_PC && $asstype != $row->reviewType) { $assigned[] = $row->paperId; } else { $user->assign_review($row->paperId, $pc->contactId, $asstype); $nworked++; } } } if (count($conflicts)) { Conf::msg_error("Some papers were not assigned because of conflicts (" . join(", ", $conflicts) . "). If these conflicts are in error, remove them and try to assign again."); } if (count($assigned)) { Conf::msg_error("Some papers were not assigned because the PC member already had an assignment (" . join(", ", $assigned) . ")."); } if ($nworked) { $Conf->confirmMsg($asstype == 0 ? "Unassigned reviews." : "Assigned reviews."); } Dbl::qe_raw("unlock tables"); $Conf->update_rev_tokens_setting(false); } } } } } }
function change_review_tokens() { global $Conf, $Me; $cleared = $Me->change_review_token(false, false); $tokeninfo = array(); foreach (preg_split('/\\s+/', $_REQUEST["token"]) as $x) { if ($x == "") { /* no complaints */ } else { if (!($token = decode_token($x, "V"))) { Conf::msg_error("Invalid review token “" . htmlspecialchars($x) . "”. Check your typing and try again."); } else { if ($Conf->session("rev_token_fail", 0) >= 5) { Conf::msg_error("Too many failed attempts to use a review token. <a href='" . hoturl("index", "signout=1") . "'>Sign out</a> and in to try again."); } else { $result = Dbl::qe("select paperId from PaperReview where reviewToken=" . $token); if ($row = edb_row($result)) { $tokeninfo[] = "Review token “" . htmlspecialchars($x) . "” lets you review <a href='" . hoturl("paper", "p={$row['0']}") . "'>paper #" . $row[0] . "</a>."; $Me->change_review_token($token, true); } else { Conf::msg_error("Review token “" . htmlspecialchars($x) . "” hasn’t been assigned."); $nfail = $Conf->session("rev_token_fail", 0) + 1; $Conf->save_session("rev_token_fail", $nfail); } } } } } if ($cleared && !count($tokeninfo)) { $tokeninfo[] = "Review tokens cleared."; } if (count($tokeninfo)) { $Conf->infoMsg(join("<br />\n", $tokeninfo)); } redirectSelf(); }
function saveWatchPreference($paperId, $contactId, $watchtype, $on) { global $Conf, $OK; $explicit = $watchtype << WATCHSHIFT_EXPLICIT; $selected = $watchtype << WATCHSHIFT_NORMAL; $onvalue = $explicit | ($on ? $selected : 0); Dbl::qe("insert into PaperWatch (paperId, contactId, watch)\n values ({$paperId}, {$contactId}, {$onvalue})\n on duplicate key update watch = (watch & ~" . ($explicit | $selected) . ") | {$onvalue}"); return $OK; }
private function _prepare_sort() { global $Conf; $this->default_sort_column = PaperColumn::lookup("id"); $this->sorters[0]->field = null; if ($this->search->sorters) { foreach ($this->search->sorters as $sorter) { if ($sorter->type && ($field = PaperColumn::lookup($sorter->type)) && $field->prepare($this, PaperColumn::PREP_SORT) && $field->comparator) { $sorter->field = $field; } else { if ($sorter->type) { if ($this->contact->can_view_tags(null) && ($tagger = new Tagger()) && ($tag = $tagger->check($sorter->type)) && ($result = Dbl::qe("select paperId from PaperTag where tag=? limit 1", $tag)) && edb_nrows($result)) { $this->search->warn("Unrecognized sort “" . htmlspecialchars($sorter->type) . "”. Did you mean “sort:#" . htmlspecialchars($sorter->type) . "”?"); } else { $this->search->warn("Unrecognized sort “" . htmlspecialchars($sorter->type) . "”."); } continue; } } ListSorter::push($this->sorters, $sorter); } if (count($this->sorters) > 1 && $this->sorters[0]->empty) { array_shift($this->sorters); } } if (get($this->sorters[0], "field")) { /* all set */ } else { if ($this->sorters[0]->type && ($c = PaperColumn::lookup($this->sorters[0]->type)) && $c->prepare($this, PaperColumn::PREP_SORT)) { $this->sorters[0]->field = $c; } else { $this->sorters[0]->field = $this->default_sort_column; } } $this->sorters[0]->type = $this->sorters[0]->field->name; // set defaults foreach ($this->sorters as $s) { if ($s->reverse === null) { $s->reverse = false; } if ($s->score === null) { $s->score = ListSorter::default_score_sort(); } } }
public function fetch_comments($where) { $result = Dbl::qe("select PaperComment.*, firstName reviewFirstName, lastName reviewLastName, email reviewEmail\n from PaperComment join ContactInfo on (ContactInfo.contactId=PaperComment.contactId)\n where {$where} order by commentId"); $comments = array(); while ($c = CommentInfo::fetch($result, $this)) { $comments[$c->commentId] = $c; } Dbl::free($result); return $comments; }
$Conf->ajaxExit(array("ok" => false, "error" => $Info->repo ? "No repository." : "Commit " . htmlspecialchars($Commit) . " isn’t connected to this repository.")); } return $Info; } ContactView::set_path_request(array("/@", "/@/p", "/@/p/H", "/p", "/p/H", "/p/u", "/p/u/H")); // user, pset, runner $User = $Me; if (isset($_REQUEST["u"]) && !($User = ContactView::prepare_user($_REQUEST["u"]))) { $Conf->ajaxExit(array("ok" => false)); } assert($User == $Me || $Me->isPC); $Pset = ContactView::find_pset_redirect(@$_REQUEST["pset"]); $Psetid = $Pset->id; if (isset($_POST["reqregrade"]) && check_post() && user_pset_info()) { Dbl::qe("insert into RepositoryGradeRequest (repoid,pset,hash,requested_at) values (?, ?, ?, ?) on duplicate key update requested_at=values(requested_at)", $Info->repo->repoid, $Info->pset->psetid, $Info->commit_hash(), $Now); Dbl::qe("delete from RepositoryGradeRequest where repoid=? and pset=? and requested_at<?", $Info->repo->repoid, $Info->pset->psetid, $Now); $Conf->ajaxExit(array("ok" => true)); } if (!$Pset->run_dirpattern) { quit("Configuration error (run_dirpattern)"); } else { if (!$Pset->run_jailfiles) { quit("Configuration error (run_jailfiles)"); } } $Runner = null; foreach ($Pset->runners as $r) { if ($r->name == $_REQUEST["run"]) { $Runner = $r; } }
function save_paper_json($pj) { global $Conf, $Now; assert(!$this->hide_docids); $paperid = null; if (isset($pj->pid) && is_int($pj->pid) && $pj->pid > 0) { $paperid = $pj->pid; } else { if (!isset($pj->pid) && isset($pj->id) && is_int($pj->id) && $pj->id > 0) { $paperid = $pj->id; } else { if (isset($pj->pid) || isset($pj->id)) { $key = isset($pj->pid) ? "pid" : "id"; $this->set_error_html($key, "Format error [{$key}]"); return false; } } } if (get($pj, "error") || get($pj, "error_html")) { $this->set_error_html("error", "Refusing to save paper with error"); return false; } $this->prow = $old_pj = null; $this->paperid = $paperid ?: -1; if ($paperid) { $this->prow = $Conf->paperRow(["paperId" => $paperid, "topics" => true, "options" => true], $this->contact); } if ($this->prow) { $old_pj = $this->paper_json($this->prow, ["forceShow" => true]); } if ($pj && $old_pj && $paperid != $old_pj->pid) { $this->set_error_html("pid", "Saving paper with different ID"); return false; } $this->normalize($pj, $old_pj); if ($old_pj) { $this->normalize($old_pj, null); } if ($this->nerrors) { return false; } $this->check_invariants($pj, $old_pj); // store documents (options already stored) if (isset($pj->submission) && $pj->submission) { $this->upload_document($pj->submission, PaperOption::find_document(DTYPE_SUBMISSION)); } if (isset($pj->final) && $pj->final) { $this->upload_document($pj->final, PaperOption::find_document(DTYPE_FINAL)); } // create contacts foreach (self::contacts_array($pj) as $c) { $c->only_if_contactdb = !get($c, "contact"); $c->disabled = !!$this->disable_users; if (!Contact::create($c, !$this->no_email) && get($c, "contact")) { $this->set_error_html("contacts", "Could not create an account for contact " . Text::user_html($c) . "."); } } // catch errors if ($this->nerrors) { return false; } // update Paper table $q = array(); foreach (array("title", "abstract", "collaborators") as $k) { $v = convert_to_utf8((string) get($pj, $k)); if (!$old_pj || get($pj, $k) !== null && $v !== (string) get($old_pj, $k)) { $q[] = "{$k}='" . sqlq($v) . "'"; } } if (!$old_pj || get($pj, "authors") !== null) { $autext = convert_to_utf8(self::author_information($pj)); $old_autext = self::author_information($old_pj); if ($autext !== $old_autext || !$old_pj) { $q[] = "authorInformation='" . sqlq($autext) . "'"; } } if ($Conf->submission_blindness() == Conf::BLIND_OPTIONAL && (!$old_pj || get($pj, "nonblind") !== null && !$pj->nonblind != !$old_pj->nonblind)) { $q[] = "blind=" . (get($pj, "nonblind") ? 0 : 1); } if (!$old_pj || get($pj, "submission") !== null) { $new_id = get($pj, "submission") ? $pj->submission->docid : 1; $old_id = $old_pj && get($old_pj, "submission") ? $old_pj->submission->docid : 1; if (!$old_pj || $new_id != $old_id) { $q[] = "paperStorageId={$new_id}"; } } if (!$old_pj || get($pj, "final") !== null) { $new_id = get($pj, "final") ? $pj->final->docid : 0; $old_id = $old_pj && get($old_pj, "final") ? $old_pj->final->docid : 0; if (!$old_pj || $new_id != $old_id) { $q[] = "finalPaperStorageId={$new_id}"; } } if (get($pj, "withdrawn") !== null || get($pj, "submitted") !== null || get($pj, "draft") !== null) { if (get($pj, "submitted") !== null) { $submitted = $pj->submitted; } else { if (get($pj, "draft") !== null) { $submitted = !$pj->draft; } else { if ($old_pj) { $submitted = get($old_pj, "submitted_at") > 0; } else { $submitted = false; } } } if (get($pj, "withdrawn")) { if (!$old_pj || !get($old_pj, "withdrawn")) { $q[] = "timeWithdrawn=" . (get($pj, "withdrawn_at") ?: $Now); $q[] = "timeSubmitted=" . ($submitted ? -100 : 0); } else { if (get($old_pj, "submitted_at") > 0 !== $submitted) { $q[] = "timeSubmitted=" . ($submitted ? -100 : 0); } } } else { if ($submitted) { if (!$old_pj || !get($old_pj, "submitted")) { $q[] = "timeSubmitted=" . (get($pj, "submitted_at") ?: $Now); } if ($old_pj && get($old_pj, "withdrawn")) { $q[] = "timeWithdrawn=0"; } } else { if ($old_pj && (get($old_pj, "withdrawn") || get($old_pj, "submitted"))) { $q[] = "timeSubmitted=0"; $q[] = "timeWithdrawn=0"; } } } } if (get($pj, "final_submitted") !== null) { if ($pj->final_submitted) { $time = get($pj, "final_submitted_at") ?: $Now; } else { $time = 0; } if (!$old_pj || get($old_pj, "final_submitted_at") != $time) { $q[] = "timeFinalSubmitted={$time}"; } } if (!empty($q)) { if ($Conf->submission_blindness() == Conf::BLIND_NEVER) { $q[] = "blind=0"; } else { if ($Conf->submission_blindness() != Conf::BLIND_OPTIONAL) { $q[] = "blind=1"; } } $joindoc = $old_joindoc = null; if (get($pj, "final")) { $joindoc = $pj->final; $old_joindoc = $old_pj ? get($old_pj, "final") : null; } else { if (get($pj, "submission")) { $joindoc = $pj->submission; $old_joindoc = $old_pj ? get($old_pj, "submission") : null; } } if ($joindoc && (!$old_joindoc || $old_joindoc->docid != $joindoc->docid) && get($joindoc, "size") && get($joindoc, "timestamp")) { $q[] = "size=" . $joindoc->size; $q[] = "mimetype='" . sqlq($joindoc->mimetype) . "'"; $q[] = "sha1='" . sqlq($joindoc->sha1) . "'"; $q[] = "timestamp=" . $joindoc->timestamp; } else { if (!$joindoc) { $q[] = "size=0,mimetype='',sha1='',timestamp=0"; } } if ($paperid) { $result = Dbl::qe_raw("update Paper set " . join(",", $q) . " where paperId={$paperid}"); if ($result && $result->affected_rows === 0 && edb_nrows(Dbl::qe_raw("select paperId from Paper where paperId={$paperid}")) === 0) { $result = Dbl::qe_raw("insert into Paper set paperId={$paperid}, " . join(",", $q)); } } else { $result = Dbl::qe_raw("insert into Paper set " . join(",", $q)); if (!$result || !($paperid = $pj->pid = $result->insert_id)) { return $this->set_error_html(false, "Could not create paper."); } if (!empty($this->uploaded_documents)) { Dbl::qe_raw("update PaperStorage set paperId={$paperid} where paperStorageId in (" . join(",", $this->uploaded_documents) . ")"); } } // maybe update `papersub` settings $is_submitted = !get($pj, "withdrawn") && get($pj, "submitted"); $was_submitted = $old_pj && !get($old_pj, "withdrawn") && get($old_pj, "submitted"); if ($is_submitted != $was_submitted) { $Conf->update_papersub_setting($is_submitted); } } // update PaperTopics if (get($pj, "topics")) { $topics = self::topics_sql($pj, $paperid); $old_topics = self::topics_sql($old_pj, $paperid); if ($topics !== $old_topics) { $result = Dbl::qe_raw("delete from PaperTopic where paperId={$paperid}"); if ($topics) { $result = Dbl::qe_raw("insert into PaperTopic (topicId,paperId) values {$topics}"); } } } // update PaperOption if (get($pj, "options")) { $options = convert_to_utf8(self::options_sql($pj, $paperid)); $old_options = self::options_sql($old_pj, $paperid); if ($options !== $old_options) { $result = Dbl::qe("delete from PaperOption where paperId={$paperid} and optionId?a", array_keys($pj->parsed_options)); if ($options) { $result = Dbl::qe_raw("insert into PaperOption (paperId,optionId,value,data) values {$options}"); } } } // update PaperConflict $conflict = $this->conflicts_array($pj, $old_pj); $old_conflict = $this->conflicts_array($old_pj, null); if (join(",", array_keys($conflict)) !== join(",", array_keys($old_conflict)) || join(",", array_values($conflict)) !== join(",", array_values($old_conflict))) { $q = array(); foreach ($conflict as $email => $type) { $q[] = "'" . sqlq($email) . "'"; } $ins = array(); if (!empty($q)) { $result = Dbl::qe_raw("select contactId, email from ContactInfo where email in (" . join(",", $q) . ")"); while ($row = edb_row($result)) { $ins[] = "({$paperid},{$row['0']}," . $conflict[strtolower($row[1])] . ")"; } } $result = Dbl::qe_raw("delete from PaperConflict where paperId={$paperid}"); if (!empty($ins)) { $result = Dbl::qe_raw("insert into PaperConflict (paperId,contactId,conflictType) values " . join(",", $ins)); } } return $paperid; }
function mark_grading_commit() { if ($this->pset->gitless_grades) { Dbl::qe("insert into ContactGrade (cid,pset,gradercid) values (?, ?, ?) on duplicate key update gradercid=gradercid", $this->user->contactId, $this->pset->psetid, $this->viewer->contactId); } else { assert(!!$this->commit); $grader = $this->commit_info("gradercid"); if (!$grader) { $grader = $this->grading_info("gradercid"); } Dbl::qe("insert into RepositoryGrade (repoid,pset,gradehash,gradercid,placeholder) values (?, ?, ?, ?, 0) on duplicate key update gradehash=values(gradehash), gradercid=values(gradercid), placeholder=0", $this->repo->repoid, $this->pset->psetid, $this->commit ?: null, $grader ?: null); } $this->grade = $this->repo_grade = false; }
if (TagInfo::has_vote()) { $q = array(); foreach (TagInfo::vote_tags() as $t => $v) { $q[] = "tag='" . sqlq($t) . "' or tag like '%~" . sqlq_for_like($t) . "'"; } Dbl::qe_raw("delete from PaperTag where paperId={$prow->paperId} and (" . join(" or ", $q) . ")"); } $Me->log_activity("Withdrew", $prow->paperId); redirectSelf(); } else { Conf::msg_error(whyNotText($whyNot, "withdraw")); } } if (isset($_REQUEST["revive"]) && !$newPaper && check_post()) { if (!($whyNot = $Me->perm_revive_paper($prow))) { Dbl::qe("update Paper set timeWithdrawn=0, timeSubmitted=if(timeSubmitted=-100,{$Now},0), withdrawReason=null where paperId={$prow->paperId}"); $Conf->update_papersub_setting(true); loadRows(); $Me->log_activity("Revived", $prow->paperId); redirectSelf(); } else { Conf::msg_error(whyNotText($whyNot, "revive")); } } // send watch messages global $Qreq; $Qreq = make_qreq(); function final_submit_watch_callback($prow, $minic) { if ($minic->can_view_paper($prow)) { HotCRPMailer::send_to($minic, "@finalsubmitnotify", $prow);
function __construct($contact, $type, $papersel, $newrev_since) { global $Conf, $Now; $this->contact = $contact; assert(!!$contact->isPC); $any_newpcrev = $any_lead = $any_shepherd = 0; if ($contact->is_manager()) { $this->defsel("s", "Contact authors of submitted papers"); $this->defsel("unsub", "Contact authors of unsubmitted papers"); $this->defsel("au", "All contact authors"); // map "somedec:no"/"somedec:yes" to real decisions $result = Dbl::qe("select outcome, count(*) from Paper where timeSubmitted>0 group by outcome"); $dec_pcount = edb_map($result); $dec_tcount = array(0 => 0, 1 => 0, -1 => 0); foreach ($dec_pcount as $dnum => $dcount) { $dec_tcount[$dnum > 0 ? 1 : ($dnum < 0 ? -1 : 0)] += $dcount; } if ($type == "somedec:no" || $type == "somedec:yes") { $dmaxcount = -1; foreach ($dec_pcount as $dnum => $dcount) { if (($type[8] == "n" ? $dnum < 0 : $dnum > 0) && $dcount > $dmaxcount && ($dname = $Conf->decision_name($dnum))) { $type = "dec:{$dname}"; $dmaxcount = $dcount; } } } $by_dec = array(); foreach ($Conf->decision_map() as $dnum => $dname) { $k = "dec:{$dname}"; if ($dnum && (@$dec_pcount[$dnum] > 0 || $type == $k)) { $by_dec[$k] = "Contact authors of " . htmlspecialchars($dname) . " papers"; } } if ($dec_tcount[1] > 0 || $type == "dec:yes") { $by_dec["dec:yes"] = "Contact authors of accept-class papers"; } if ($dec_tcount[-1] > 0 || $type == "dec:no") { $by_dec["dec:no"] = "Contact authors of reject-class papers"; } if ($dec_tcount[0] > 0 || $type == "dec:none") { $by_dec["dec:none"] = "Contact authors of undecided papers"; } if ($type == "dec:any") { $by_dec["dec:any"] = "Contact authors of decided papers"; } if (count($by_dec)) { $this->sel["bydec_group"] = array("optgroup", "Contact authors by decision"); foreach ($by_dec as $k => $v) { $this->defsel($k, $v); } $this->sel["bydec_group_end"] = array("optgroup"); } $this->sel["rev_group"] = array("optgroup", "Reviewers"); $this->defsel("rev", "Reviewers"); $this->defsel("crev", "Reviewers with complete reviews"); $this->defsel("uncrev", "Reviewers with incomplete reviews"); $this->defsel("allcrev", "Reviewers with no incomplete reviews"); $this->defsel("pcrev", "PC reviewers"); $this->defsel("uncpcrev", "PC reviewers with incomplete reviews"); // new assignments query // XXX this exposes information about PC review assignments // for conflicted papers to the chair; not worth worrying about $aq = "select PaperReview.paperId any_newpcrev from PaperReview"; if (!$contact->privChair) { $aq .= " join Paper on (Paper.paperId=PaperReview.paperId and Paper.managerContactId=" . $contact->contactId . ")"; } $aq .= "\n\twhere reviewType>=" . REVIEW_PC . " and reviewSubmitted is null and reviewNeedsSubmit!=0 and timeRequested>timeRequestNotified limit 1"; $bcq_manager = ""; if (!$contact->privChair) { $bcq_manager = " and managerContactId=" . $contact->contactId; } $q = "select any_newpcrev, any_lead, any_shepherd\n\tfrom ({$aq}) a\n\tleft join (select paperId any_lead from Paper where timeSubmitted>0 and leadContactId!=0{$bcq_manager} limit 1) b on (true)\n\tleft join (select paperId any_shepherd from Paper where timeSubmitted>0 and shepherdContactId!=0{$bcq_manager} limit 1) c on (true)"; if ($row = Dbl::fetch_first_row($q)) { list($any_newpcrev, $any_lead, $any_shepherd) = $row; } $this->defsel("newpcrev", "PC reviewers with new review assignments"); $this->defsel("extrev", "External reviewers"); $this->defsel("uncextrev", "External reviewers with incomplete reviews"); $this->sel["rev_group_end"] = array("optgroup"); } $this->defsel_nm("myextrev", "Your requested reviewers"); $this->defsel_nm("uncmyextrev", "Your requested reviewers with incomplete reviews"); $this->sel["pc_group"] = array("optgroup", "Program committee"); if ($contact->is_manager()) { if ($any_lead || $type == "lead") { $this->defsel("lead", "Discussion leads"); } if ($any_shepherd || $type == "shepherd") { $this->defsel("shepherd", "Shepherds"); } } $this->defsel_nm("pc", "Program committee"); foreach (pcTags() as $t) { if ($t != "pc") { $this->defsel_nm("pc:{$t}", "PC members tagged “{$t}”"); } } $this->sel["pc_group_end"] = array("optgroup"); if ($contact->privChair) { $this->defsel("all", "All users"); } if (isset($this->sel[$type])) { $this->type = $type; } else { if ($type == "myuncextrev" && isset($this->sel["uncmyextrev"])) { $this->type = "uncmyextrev"; } else { $this->type = key($this->sel); } } $this->papersel = $papersel; if ($this->type == "newpcrev") { $t = @trim($newrev_since); if (preg_match(',\\A(?:|n/a|[(]?all[)]?|0)\\z,i', $t)) { $this->newrev_since = 0; } else { if (($this->newrev_since = $Conf->parse_time($t)) !== false) { if ($this->newrev_since > $Now) { $Conf->warnMsg("That time is in the future."); } } else { Conf::msg_error("Invalid date."); $this->error = true; } } } }
$ids = array(); $accts = $_REQUEST["acct"]; while ($word = PaperSearch::pop_word($accts)) { $flags = ContactSearch::F_TAG; if (substr($word, 0, 1) === "\"") { $flags |= ContactSearch::F_QUOTED; $word = preg_replace(',(?:\\A"|"\\z),', "", $word); } $Search = new ContactSearch($flags, $word, $Me); foreach ($Search->ids as $id) { $ids[$id] = $id; } } $where = array(); if (count($ids)) { $result = Dbl::qe("select contactId, email from ContactInfo where contactId ?a", $ids); while ($row = edb_row($result)) { $where[] = "contactId={$row['0']}"; $where[] = "action like " . Dbl::utf8ci("'% " . sqlq_for_like($row[1]) . "%'"); } } if (count($where)) { $wheres[] = "(" . join(" or ", $where) . ")"; } else { $Conf->infoMsg("No accounts match “" . htmlspecialchars($_REQUEST["acct"]) . "”."); $wheres[] = "false"; } } if ($str = $_REQUEST["q"]) { $where = array(); while (($str = ltrim($str)) != "") {
function load_pset_info() { global $ConfSitePATH, $Conf, $PsetInfo, $PsetOverrides, $Opt; // read initial messages Messages::$main = new Messages(); $x = json_decode(file_get_contents("{$ConfSitePATH}/src/messages.json")); foreach ($x as $j) { Messages::$main->add($j); } // read psets $PsetInfo = load_psets_json(false); // parse psets foreach ($PsetInfo as $pk => $p) { if (!is_object($p) || !isset($p->psetid)) { continue; } object_merge_recursive($p, $PsetInfo->_defaults); try { $pset = new Pset($pk, $p); Pset::register($pset); } catch (Exception $exception) { // Want to give a good error message, so discover where the error is. // - create pset landmark object $locinfo = (object) array(); foreach (psets_json_data(false) as $fname => $data) { $x = Json::decode_landmarks($data, $fname); object_replace_recursive($locinfo, $x); } $locp = $locinfo->{$pk}; if (isset($locinfo->_defaults)) { object_merge_recursive($locp, $locinfo->_defaults); } // - lookup exception path in landmark object $path = $exception instanceof PsetConfigException ? $exception->path : array(); for ($pathpos = 0; $pathpos < count($path) && $locp && !is_string($locp); ++$pathpos) { $component = $path[$pathpos]; $locp = is_array($locp) ? $locp[$component] : $locp->{$component}; } // - report error if (is_object($locp) && @$locp->__LANDMARK__) { $locp = $locp->__LANDMARK__; } else { if (!is_string($locp)) { $locp = $locinfo->{$pk}->__LANDMARK__; } } Multiconference::fail_message($locp . ": Configuration error: " . $exception->getMessage()); } } // read message data if (!@$PsetInfo->_messagedefs) { $PsetInfo->_messagedefs = (object) array(); } if (!@$PsetInfo->_messagedefs->SYSTEAM) { $PsetInfo->_messagedefs->SYSTEAM = "cs61-staff"; } foreach ($PsetInfo->_messagedefs as $k => $v) { Messages::$main->define($k, $v); } // also create log/ and repo/ directories foreach (array("{$ConfSitePATH}/log", "{$ConfSitePATH}/repo") as $d) { if (!is_dir($d) && !mkdir($d, 02770, true)) { $e = error_get_last(); Multiconference::fail_message("`{$d}` missing and cannot be created (" . $e["message"] . ")."); } if (!file_exists("{$d}/.htaccess") && ($x = file_get_contents("{$ConfSitePATH}/src/.htaccess")) !== false && file_put_contents("{$d}/.htaccess", $x) != strlen($x)) { Multiconference::fail_message("Error creating `{$d}/.htaccess`"); } } // if any anonymous problem sets, create anonymous usernames foreach (Pset::$all as $p) { if (!$p->disabled && $p->anonymous) { while ($row = Dbl::fetch_first_row(Dbl::qe("select contactId from ContactInfo where anon_username is null limit 1"))) { Dbl::q("update ContactInfo set anon_username='******' where contactId=?", $row[0]); } } } }
function execute($verbose = false) { global $Conf, $Now, $Opt; if (count($this->errors_) || !count($this->assigners)) { if ($verbose && count($this->errors_)) { $this->report_errors(); } else { if ($verbose) { $Conf->warnMsg("Nothing to assign."); } } return count($this->errors_) == 0; // true means no errors } // mark activity now to avoid DB errors later $this->contact->mark_activity(); // create new contacts outside the lock $locks = array("ContactInfo" => "read", "Paper" => "read", "PaperConflict" => "read"); $Conf->save_logs(true); foreach ($this->assigners as $assigner) { if ($assigner->contact && $assigner->contact->contactId < 0) { $assigner->contact = $this->cmap->register_contact($assigner->contact); $assigner->cid = $assigner->contact->contactId; } $assigner->add_locks($locks); } // execute assignments $tables = array(); foreach ($locks as $t => $type) { $tables[] = "{$t} {$type}"; } Dbl::qe("lock tables " . join(", ", $tables)); foreach ($this->assigners as $assigner) { $assigner->execute($this); } Dbl::qe("unlock tables"); $Conf->save_logs(false); // confirmation message if ($verbose) { if ($Conf->setting("pcrev_assigntime") == $Now) { $Conf->confirmMsg("Assignments saved! You may want to <a href=\"" . hoturl("mail", "template=newpcrev") . "\">send mail about the new assignments</a>."); } else { $Conf->confirmMsg("Assignments saved!"); } } // clean up $Conf->update_rev_tokens_setting(false); $Conf->update_paperlead_setting(); $pids = array(); foreach ($this->assigners as $assigner) { $assigner->cleanup($this); if ($assigner->pid > 0 && $assigner->notify_tracker()) { $pids[$assigner->pid] = true; } } if (count($pids) && opt("trackerCometSite")) { MeetingTracker::contact_tracker_comet(array_keys($pids)); } return true; }
function createAnonymousReview() { global $Conf, $Me, $Now, $prow, $rrows; Dbl::qe_raw("lock tables PaperReview write, PaperReviewRefused write, ContactInfo write, PaperConflict read, ActionLog write"); // find an unassigned anonymous review contact $contactemail = unassignedAnonymousContact(); $result = Dbl::qe_raw("select contactId from ContactInfo where email='" . sqlq($contactemail) . "'"); if (edb_nrows($result) == 1) { $row = edb_row($result); $reqId = $row[0]; } else { $result = Dbl::qe("insert into ContactInfo set firstName='Jane Q.', lastName='Public', unaccentedName='Jane Q. Public', email=?, affiliation='Unaffiliated', password='', disabled=1, creationTime={$Now}", $contactemail); if (!$result) { return $result; } $reqId = $result->insert_id; } // store the review request $reviewId = $Me->assign_review($prow->paperId, $reqId, REVIEW_EXTERNAL, array("mark_notify" => true, "token" => true)); if ($reviewId) { $result = Dbl::ql("select reviewToken from PaperReview where reviewId={$reviewId}"); $row = edb_row($result); $Conf->confirmMsg("Created a new anonymous review for paper #{$prow->paperId}. The review token is " . encode_token((int) $row[0]) . "."); } Dbl::qx_raw("unlock tables"); $Conf->update_rev_tokens_setting(true); return true; }
function do_setting_update($sv) { global $Conf, $Group, $Me, $Now, $Opt, $OptOverride; // parse settings foreach (Si::$all as $si) { account_value($sv, $si); } // check date relationships foreach (array("sub_reg" => "sub_sub", "final_soft" => "final_done") as $dn1 => $dn2) { list($dv1, $dv2) = [$sv->savedv($dn1), $sv->savedv($dn2)]; } if (!$dv1 && $dv2) { $sv->save($dn1, $dv2); } else { if ($dv2 && $dv1 > $dv2) { $sv->set_error($dn1, unparse_setting_error(Si::get($dn1), "Must come before " . Si::get($dn2, "short_description") . ".")); $sv->set_error($dn2); } } if ($sv->has_savedv("sub_sub")) { $sv->save("sub_update", $sv->savedv("sub_sub")); } if (get($Opt, "defaultSiteContact")) { if ($sv->has_savedv("opt.contactName") && get($Opt, "contactName") === $sv->savedv("opt.contactName")) { $sv->save("opt.contactName", null); } if ($sv->has_savedv("opt.contactEmail") && get($Opt, "contactEmail") === $sv->savedv("opt.contactEmail")) { $sv->save("opt.contactEmail", null); } } if ($sv->has_savedv("resp_active") && $sv->savedv("resp_active")) { foreach (explode(" ", $sv->newv("resp_rounds")) as $i => $rname) { $isuf = $i ? "_{$i}" : ""; if ($sv->newv("resp_open{$isuf}") > $sv->newv("resp_done{$isuf}")) { $sv->set_error("resp_open{$isuf}", unparse_setting_error(Si::get("resp_open"), "Must come before " . Si::get("resp_done", "short_description") . ".")); $sv->set_error("resp_done{$isuf}"); } } } // update 'papersub' if ($sv->has_savedv("pc_seeall")) { // see also conference.php if ($sv->savedv("pc_seeall") <= 0) { $x = "timeSubmitted>0"; } else { $x = "timeWithdrawn<=0"; } $num = Dbl::fetch_ivalue("select paperId from Paper where {$x} limit 1") ? 1 : 0; if ($num != $Conf->setting("papersub")) { $sv->save("papersub", $num); } } // Setting relationships if ($sv->has_savedv("sub_open") && $sv->newv("sub_open", 1) <= 0 && $sv->oldv("sub_open") > 0 && $sv->newv("sub_sub") <= 0) { $sv->save("sub_close", $Now); } if ($sv->has_savedv("msg.clickthrough_submit")) { $sv->save("clickthrough_submit", null); } // make settings $changedn = []; if (!$sv->has_errors() && (count($sv->savedv) || count($sv->save_callbacks))) { $tables = "Settings write"; foreach ($sv->need_lock as $t => $need) { if ($need) { $tables .= ", {$t} write"; } } $Conf->qe("lock tables {$tables}"); // load db settings, pre-crosscheck $dbsettings = array(); $result = Dbl::qe("select name, value, data from Settings"); while ($row = edb_row($result)) { $dbsettings[$row[0]] = $row; } Dbl::free($result); // apply settings foreach ($sv->save_callbacks as $si) { $p = $sv->parser($si); $p->save($sv, $si); } $dv = $aq = $av = array(); foreach ($sv->savedv as $n => $v) { if (substr($n, 0, 4) === "opt." && $v !== null) { $okey = substr($n, 4); $oldv = array_key_exists($okey, $OptOverride) ? $OptOverride[$okey] : get($Opt, $okey); $Opt[$okey] = $v[1] === null ? $v[0] : $v[1]; if ($oldv === $Opt[$okey]) { $v = null; } else { if (!array_key_exists($okey, $OptOverride)) { $OptOverride[$okey] = $oldv; } } } if ($v === null ? !isset($dbsettings[$n]) : isset($dbsettings[$n]) && (int) $dbsettings[$n][1] === $v[0] && $dbsettings[$n][2] === $v[1]) { continue; } $changedn[] = $n; if ($v !== null) { $aq[] = "(?, ?, ?)"; array_push($av, $n, $v[0], $v[1]); } else { $dv[] = $n; } } if (count($dv)) { Dbl::qe_apply("delete from Settings where name?a", array($dv)); //Conf::msg_info(Ht::pre_text_wrap(Dbl::format_query_apply("delete from Settings where name?a", array($dv)))); } if (count($aq)) { Dbl::qe_apply("insert into Settings (name, value, data) values\n\t" . join(",\n\t", $aq) . "\n\ton duplicate key update value=values(value), data=values(data)", $av); //Conf::msg_info(Ht::pre_text_wrap(Dbl::format_query_apply("insert into Settings (name, value, data) values\n\t" . join(",\n\t", $aq) . "\n\ton duplicate key update value=values(value), data=values(data)", $av))); } $Conf->qe("unlock tables"); if (count($changedn)) { $Me->log_activity("Updated settings " . join(", ", $changedn)); } $Conf->load_settings(); // contactdb may need to hear about changes to shortName if ($sv->has_savedv("opt.shortName") && get($Opt, "contactdb_dsn") && ($cdb = Contact::contactdb())) { Dbl::ql($cdb, "update Conferences set shortName=? where dbName=?", $Opt["shortName"], $Opt["dbName"]); } } // update the review form in case it's changed ReviewForm::clear_cache(); if (!$sv->has_errors()) { $Conf->save_session("settings_highlight", $sv->error_fields()); if (count($changedn)) { $Conf->confirmMsg("Changes saved."); } else { $Conf->warnMsg("No changes."); } $sv->report(); redirectSelf(); } else { SettingGroup::crosscheck($sv, $Group); $sv->report(); } }
if (!$zlib_output_compression) { header("Content-Length: 43"); } print "GIF89a€!ù,D;"; } exit; } if (!$Me->isPC) { $Me->escape(); } function output($User) { global $Me; $u = $Me->user_linkpart($User); echo '<div class="facebook61">', '<a href="', hoturl("index", ["u" => $u]), '">', '<img class="bigface61" src="' . hoturl("face", ["u" => $u, "imageid" => $User->contactImageId ?: 0]) . '" border="0" />', '</a>', '<h2 class="infacebook61"><a class="q" href="', hoturl("index", ["u" => $u]), '">', htmlspecialchars($u), '</a>'; if ($Me->privChair) { echo " ", become_user_link($User); } echo '</h2>'; if ($User !== $Me) { echo '<h3 class="infacebook61">', Text::user_html($User), '</h3>'; } echo '</div>'; } $Conf->header("Thefacebook", "face"); $u = Dbl::qe("select contactId, email, firstName, lastName, seascode_username, contactImageId from ContactInfo where roles=0"); while ($user = edb_orow($u)) { output($user); } echo "<div class='clear'></div>\n"; $Conf->footer();
xassert(!$Conf->check_tracks($paper17, $user_jon, Track::ASSREV)); xassert(!$user_jon->can_accept_review_assignment_ignore_conflict($paper17)); xassert(!$user_jon->can_accept_review_assignment($paper17)); // check shepherd search visibility $paper11 = $Conf->paperRow(11, $user_chair); $paper12 = $Conf->paperRow(12, $user_chair); $j = call_api("setshepherd", $user_chair, ["shepherd" => $user_estrin->email], $paper11); xassert_eqq($j->ok, true); $j = call_api("setshepherd", $user_chair, ["shepherd" => $user_estrin->email], $paper12); xassert_eqq($j->ok, true); assert_search_papers($user_chair, "shep:any", "11 12"); assert_search_papers($user_chair, "shep:estrin", "11 12"); assert_search_papers($user_shenker, "shep:any", "11 12"); // tag searches assert_search_papers($user_chair, "#green", "3 9 13 17"); Dbl::qe("insert into PaperTag (paperId,tag,tagIndex) values (1,?,10), (1,?,5), (2,?,3)", $user_jon->cid . "~vote", $user_marina->cid . "~vote", $user_marina->cid . "~vote"); assert_search_papers($user_jon, "#~vote", "1"); assert_search_papers($user_jon, "#~vote≥10", "1"); assert_search_papers($user_jon, "#~vote>10", ""); assert_search_papers($user_jon, "#~vote=10", "1"); assert_search_papers($user_jon, "#~vote<10", ""); assert_search_papers($user_marina, "#~vote", "1 2"); assert_search_papers($user_marina, "#~vote≥5", "1"); assert_search_papers($user_marina, "#~vote>5", ""); assert_search_papers($user_marina, "#~vote=5", "1"); assert_search_papers($user_marina, "#~vote<5", "2"); assert_search_papers($user_chair, "#marina~vote", "1 2"); assert_search_papers($user_chair, "#red~vote", "1"); // assign some tags using AssignmentSet interface $assignset = new AssignmentSet($Admin, true); $assignset->parse("paper,action,tag,index\n1-9,tag,g*#clear\n2,tag,green,1\n");
function check_repo_open() { global $Now; // Recheck repository openness after a day for closed repositories, // and after 30 seconds for open or failed-check repositories. if (!$this->repo || !$this->repo->open && $Now - $this->repo->opencheckat <= 86400) { return 0; } else { if ($this->repo->open && $Now - $this->repo->opencheckat <= 30) { return (int) $this->repo->open; } } $r = $this->is_repo_open(); if ($r != $this->repo->open || $Now != $this->repo->opencheckat) { Dbl::qe("update Repository set `open`=?, opencheckat=? where repoid=?", $r, $Now, $this->repo->repoid); $this->repo->open = $r; $this->repo->opencheckat = $Now; } return $r; }
static function check_repo($repo, $delta, $foreground = false) { global $ConfSitePATH, $Now; assert(isset($repo->repoid) && isset($repo->cacheid) && isset($repo->url) && property_exists($repo, "snapcheckat")); if ($repo->repoid && (!$repo->snapcheckat || $repo->snapcheckat + $delta <= $Now)) { Dbl::qe("update Repository set snapcheckat={$Now} where repoid={$repo->repoid}"); $repo->snapcheckat = $Now; if ($foreground) { set_time_limit(30); } // see also handout_repo $command = "{$ConfSitePATH}/src/gitfetch {$repo->repoid} {$repo->cacheid} " . escapeshellarg($repo->ssh_url()) . " 1>&2" . ($foreground ? "" : " &"); shell_exec($command); } }
$data = stream_get_contents($handle); $status = pclose($handle); $content_type = ""; if ($data && ($nl = strpos($data, "\n")) !== false) { $content_type = substr($data, 0, $nl); $data = substr($data, $nl + 1); } $worked = false; if (pcntl_wifexitedsuccess($status) && preg_match(',\\Aimage/,', $content_type)) { $sresult = Dbl::fetch_first_object(Dbl::qe("select ContactImage.* from ContactImage join ContactInfo using (contactImageId) where ContactInfo.contactId=?", $row[0])); if ($sresult && $sresult->mimetype === $content_type && $sresult->data === $data) { $worked = "unchanged"; } else { $iresult = Dbl::qe("insert into ContactImage set contactId=?, mimetype=?, data=?", $row[0], $content_type, $data); if ($iresult) { Dbl::qe("update ContactInfo set contactImageId=? where contactId=?", $iresult->insert_id, $row[0]); $worked = true; } } } if ($worked === "unchanged") { fwrite(STDERR, strlen($data) . "B " . $content_type . " (unchanged)\n"); } else { if ($worked) { fwrite(STDERR, strlen($data) . "B " . $content_type . "\n"); } else { fwrite(STDERR, "failed\n"); } } $nworked += $worked ? 1 : 0; ++$n;
function show_pset_table($pset) { global $Conf, $Me, $Now, $Opt, $Profile, $LastPsetFix; echo '<div id="', $pset->urlkey, '">'; echo "<h3>", htmlspecialchars($pset->title), "</h3>"; if ($Me->privChair) { show_pset_actions($pset); } if ($pset->disabled) { return; } $t0 = $Profile ? microtime(true) : 0; // load students if (@$Opt["restrictRepoView"]) { $view = "l2.link repoviewable"; $viewjoin = "left join ContactLink l2 on (l2.cid=c.contactId and l2.type=" . LINK_REPOVIEW . " and l2.link=l.link)\n"; } else { $view = "4 repoviewable"; $viewjoin = ""; } $result = Dbl::qe("select c.contactId, c.firstName, c.lastName, c.email,\n\tc.huid, c.seascode_username, c.anon_username, c.extension, c.disabled, c.dropped, c.roles, c.contactTags,\n\tpl.link pcid, group_concat(rpl.link) rpcid,\n\tr.repoid, r.cacheid, r.heads, r.url, r.open, r.working, r.lastpset, r.snapcheckat, {$view},\n\trg.gradehash, rg.gradercid, rg.placeholder, rg.placeholder_at\n\tfrom ContactInfo c\n\tleft join ContactLink l on (l.cid=c.contactId and l.type=" . LINK_REPO . " and l.pset={$pset->id})\n\t{$viewjoin}\n\tleft join Repository r on (r.repoid=l.link)\n\tleft join ContactLink pl on (pl.cid=c.contactId and pl.type=" . LINK_PARTNER . " and pl.pset={$pset->id})\n\tleft join ContactLink rpl on (rpl.cid=c.contactId and rpl.type=" . LINK_BACKPARTNER . " and rpl.pset={$pset->id})\n\tleft join RepositoryGrade rg on (rg.repoid=r.repoid and rg.pset={$pset->id})\n\twhere (c.roles&" . Contact::ROLE_PCLIKE . ")=0\n\tand (rg.repoid is not null or not c.dropped)\n\tgroup by c.contactId"); $t1 = $Profile ? microtime(true) : 0; $students = array(); while ($result && ($s = $result->fetch_object("Contact"))) { $s->is_anonymous = $pset->anonymous; Contact::set_sorter($s, @$_REQUEST["sort"]); $students[$s->contactId] = $s; // maybe lastpset links are out of order if ($s->lastpset < $pset) { $LastPsetFix = true; } } uasort($students, "Contact::compare"); $checkbox = $Me->privChair || !$pset->gitless && $pset->runners; $rows = array(); $max_ncol = 0; $incomplete = array(); $pcmembers = pcMembers(); foreach ($students as $s) { if (!isset($s->printed)) { $row = (object) array("student" => $s); $row->text = render_pset_row($pset, $students, $s, $row, $pcmembers); if ($s->pcid && isset($students[$s->pcid])) { $row->ptext = render_pset_row($pset, $students, $students[$s->pcid], $row, $pcmembers); } $rows[$row->sortprefix . $s->sorter] = $row; $max_ncol = max($max_ncol, $row->ncol); if (@$s->incomplete) { $u = $Me->user_linkpart($s); $incomplete[] = '<a href="' . hoturl("pset", array("pset" => $pset->urlkey, "u" => $u, "sort" => @$_REQUEST["sort"])) . '">' . htmlspecialchars($u) . '</a>'; } } } ksort($rows, SORT_NATURAL | SORT_FLAG_CASE); if (count($incomplete)) { echo '<div id="incomplete_pset', $pset->id, '" style="display:none" class="merror">', '<strong>', htmlspecialchars($pset->title), '</strong>: ', 'Your grading is incomplete. Missing grades: ', join(", ", $incomplete), '</div>', '<script>jQuery("#incomplete_pset', $pset->id, '").remove().show().appendTo("#incomplete_notices")</script>'; } if ($checkbox) { echo Ht::form_div(hoturl_post("index", array("pset" => $pset->urlkey, "save" => 1))); } echo '<table class="s61"><tbody>'; $trn = 0; $sprefix = ""; foreach ($rows as $row) { ++$trn; if ($row->sortprefix !== $sprefix && $row->sortprefix[0] == "~") { echo "\n", '<tr><td colspan="' . ($max_ncol + ($checkbox ? 2 : 1)) . '"><hr></td></tr>', "\n"; } $sprefix = $row->sortprefix; echo '<tr class="k', $trn % 2, '">'; if ($checkbox) { echo '<td class="s61rownumber">', Ht::checkbox("s61_" . $Me->user_idpart($row->student), 1, array("class" => "s61check")), '</td>'; } echo '<td class="s61rownumber">', $trn, '.</td>', $row->text, "</tr>\n"; if (@$row->ptext) { echo '<tr class="k', $trn % 2, ' s61partner">'; if ($checkbox) { echo '<td></td>'; } echo '<td></td>', $row->ptext, "</tr>\n"; } } echo "</tbody></table>\n"; if ($Me->privChair && !$pset->gitless_grades) { echo "<div class='g'></div>"; $sel = array("none" => "N/A"); foreach (pcMembers() as $pcm) { $sel[$pcm->email] = Text::name_html($pcm); } $sel["__random__"] = "Random"; echo '<span class="nowrap" style="padding-right:2em">', Ht::select("grader", $sel, "none"), Ht::submit("setgrader", "Set grader"), '</span>'; } if (!$pset->gitless) { $sel = array(); foreach ($pset->runners as $r) { if ($Me->can_run($pset, $r)) { $sel[$r->name] = htmlspecialchars($r->title); } } if (count($sel)) { echo '<span class="nowrap" style="padding-right:2em">', Ht::select("runner", $sel), Ht::submit("runmany", "Run all"), '</span>'; } } if ($checkbox) { echo "</div></form>\n"; } if ($Profile) { $t2 = microtime(true); echo sprintf("<div>Δt %.06f DB, %.06f total</div>", $t1 - $t0, $t2 - $t0); } echo "</div>\n"; }