Exemple #1
0
function initialize_user()
{
    global $Conf, $Opt, $Me;
    // backwards compat: set $_SESSION["user"] from $_SESSION["Me"]
    if (!isset($_SESSION["user"]) && isset($_SESSION["Me"])) {
        $x = $_SESSION["Me"];
        $_SESSION["user"] = "******";
        unset($_SESSION["Me"], $_SESSION["pcmembers"]);
    }
    if (!isset($_SESSION["trueuser"]) && isset($_SESSION["user"])) {
        $_SESSION["trueuser"] = $_SESSION["user"];
    }
    if (is_string(@$_SESSION["trueuser"])) {
        $userwords = explode(" ", $_SESSION["trueuser"]);
        $_SESSION["trueuser"] = (object) array("contactId" => $userwords[0], "dsn" => $userwords[1], "email" => @$userwords[2]);
    }
    // load current user
    $Me = null;
    $trueuser = @$_SESSION["trueuser"];
    if ($trueuser && $trueuser->dsn == $Conf->dsn) {
        $Me = Contact::find_by_id($trueuser->contactId);
    }
    if (!$Me && $trueuser && $trueuser->email) {
        $Me = Contact::find_by_email($trueuser->email);
    }
    if (!$Me) {
        $Me = new Contact($trueuser);
    }
    $Me = $Me->activate();
    // if bounced through login, add post data
    if (isset($_SESSION["login_bounce"]) && !$Me->is_empty()) {
        $lb = $_SESSION["login_bounce"];
        if ($lb[0] == $Conf->dsn && $lb[2] !== "index" && $lb[2] == Navigation::page()) {
            foreach ($lb[3] as $k => $v) {
                if (!isset($_REQUEST[$k])) {
                    $_REQUEST[$k] = $_GET[$k] = $v;
                }
            }
            $_REQUEST["after_login"] = 1;
        }
        unset($_SESSION["login_bounce"]);
    }
}
Exemple #2
0
 public function mail()
 {
     if (!(($id = OAInput::post('id')) && ($contact = Contact::find_by_id($id, array('select' => 'name, email, message'))))) {
         return false;
     }
     if (!(($admin_ids = array_unique(column_array(UserRole::find('all', array('select' => 'user_id', 'conditions' => array('name IN (?)', array('root', 'contact_manager')))), 'user_id'))) && ($admins = User::find('all', array('select' => 'name, email', 'conditions' => array('id IN (?)', $admin_ids)))))) {
         return false;
     }
     $this->load->library('OAMail');
     $email = $contact->email;
     $name = $contact->name;
     $message = $contact->message;
     $mail = OAMail::create()->setSubject('[系統通知] 官網有新的留言!')->setBody("<article style='font-size:15px;line-height:22px;color:rgb(85,85,85)'><p style='margin-bottom:0'>Hi 管理員,</p><section style='padding:5px 20px'><p>剛剛有一個訪客在您的「聯絡我們」留言囉,以下他所留下的聯絡資料:</p><table style='width:100%;border-collapse:collapse'><tbody><tr><th style='width:100px;text-align:right;padding:11px 5px 10px 0;border-bottom:1px dashed rgba(200,200,200,1)'>E-Mail:</th><td style='text-align:left;text-align:left;padding:11px 0 10px 5px;border-bottom:1px dashed rgba(200,200,200,1)'>" . $email . "</td></tr><tr><th style='width:100px;text-align:right;padding:11px 5px 10px 0;border-bottom:1px dashed rgba(200,200,200,1)'>稱 呼:</th><td style='text-align:left;text-align:left;padding:11px 0 10px 5px;border-bottom:1px dashed rgba(200,200,200,1)'>" . $name . "</td></tr><tr><th style='width:100px;text-align:right;padding:11px 5px 10px 0;border-bottom:1px dashed rgba(200,200,200,1)'>內容:</th><td style='text-align:left;text-align:left;padding:11px 0 10px 5px;border-bottom:1px dashed rgba(200,200,200,1)'>" . $message . "</td></tr></tbody></table><br/><p style='text-align:right'>如果需要詳細列表,可以置<a href='" . base_url('admin', 'contacts') . "' style='color:rgba(96,156,255,1);margin:0 2px'>管理後台</a>檢閱。</p></section></article>");
     foreach ($admins as $admin) {
         $mail->addTo($admin->email, $admin->name);
     }
     $mail->send();
     $mail = OAMail::create()->setSubject('[宙思設計] 留言成功通知!')->setBody("<article style='font-size:15px;line-height:22px;color:rgb(85, 85, 85)'><p style='margin-bottom:0'>Hi " . $name . ",</p><section style='padding:5px 20px'><p>您好,我們是<a href='http://www.zeusdesign.com.tw/' style='color:rgba(96, 156, 255, 1);margin:0 2px'>宙思設計</a>團隊,我們已經收到您的留言囉。</p><p>我們稍後會有專人主動與您聯絡或回信給您!</p><p>若是尚未得到回覆,您可以至<a href='https://www.facebook.com/ZeusDesignStudio/' style='color:rgba(96, 156, 255, 1);margin:0 2px'>宙思設計臉書粉絲專頁</a>留言,或來電(02-2941-6737)聯絡我們。</p><p style='text-align:right'>- <a href='http://www.zeusdesign.com.tw/' style='color:rgba(96, 156, 255, 1);margin:0 2px'>宙思設計</a>團隊感謝您。</p></section></article>")->addTo($email, $name);
     $mail->send();
 }
 function run(Contact $user, $qreq, $ssel)
 {
     global $Conf, $Opt;
     // maybe download preferences for someone else
     $Rev = $user;
     if (($cid = cvtint($qreq->reviewer)) > 0 && $user->privChair) {
         if (!($Rev = Contact::find_by_id($cid))) {
             return Conf::msg_error("No such reviewer");
         }
     }
     if (!$Rev->isPC) {
         return self::EPERM;
     }
     $q = $Conf->paperQuery($Rev, array("paperId" => $ssel->selection(), "topics" => 1, "reviewerPreference" => 1));
     $result = Dbl::qe_raw($q);
     $texts = array();
     while ($prow = PaperInfo::fetch($result, $Rev)) {
         $t = $prow->paperId . "," . CsvGenerator::quote($prow->title);
         if ($prow->conflictType > 0) {
             $t .= ",conflict";
         } else {
             $t .= "," . unparse_preference($prow);
         }
         $t .= "\n";
         if ($this->extended) {
             if ($Rev->can_view_authors($prow, false)) {
                 $t .= prefix_word_wrap("#  Authors: ", $prow->pretty_text_author_list(), "#           ");
             }
             $t .= prefix_word_wrap("# Abstract: ", rtrim($prow->abstract), "#           ");
             if ($prow->topicIds != "") {
                 $t .= prefix_word_wrap("#   Topics: ", $prow->unparse_topics_text(), "#           ");
             }
             $t .= "\n";
         }
         defappend($texts[$prow->paperId], $t);
     }
     downloadCSV(join("", $ssel->reorder($texts)), ["paper", "title", "preference"], "revprefs");
 }
Exemple #4
0
 public function is_replied($id = 0)
 {
     if (!($id && ($contact = Contact::find_by_id($id, array('select' => 'id, is_replied, updated_at'))))) {
         return $this->output_json(array('status' => false, 'message' => '當案不存在,或者您的權限不夠喔!'));
     }
     $posts = OAInput::post();
     if ($msg = $this->_validation_is_replied_posts($posts)) {
         return $this->output_json(array('status' => false, 'message' => $msg, 'content' => Contact::$replyNames[$contact->is_replied]));
     }
     if ($columns = array_intersect_key($posts, $contact->table()->columns)) {
         foreach ($columns as $column => $value) {
             $contact->{$column} = $value;
         }
     }
     $update = Contact::transaction(function () use($contact) {
         return $contact->save();
     });
     if ($update) {
         return $this->output_json(array('status' => true, 'message' => '更新成功!', 'content' => Contact::$replyNames[$contact->is_replied]));
     } else {
         return $this->output_json(array('status' => false, 'message' => '更新失敗!', 'content' => Contact::$replyNames[$contact->is_replied]));
     }
 }
function change_email_by_capability()
{
    global $Conf, $Me;
    $capmgr = $Conf->capability_manager();
    $capdata = $capmgr->check($_REQUEST["changeemail"]);
    if (!$capdata || $capdata->capabilityType != CAPTYPE_CHANGEEMAIL || !($capdata->data = json_decode($capdata->data)) || !@$capdata->data->uemail) {
        error_go(false, "That email change code has expired, or you didn’t enter it correctly.");
    }
    $Acct = Contact::find_by_id($capdata->contactId);
    if (!$Acct) {
        error_go(false, "No such account.");
    }
    $email = $capdata->data->uemail;
    if (Contact::id_by_email($email)) {
        error_go(false, "Email address “" . htmlspecialchars($email) . "” is already in use. You may want to <a href=\"" . hoturl("mergeaccounts") . "\">merge these accounts</a>.");
    }
    $Acct->change_email($email);
    $capmgr->delete($capdata);
    $Conf->confirmMsg("Your email address has been changed.");
    if (!$Me->has_database_account() || $Me->contactId == $Acct->contactId) {
        $Me = $Acct->activate();
    }
}
Exemple #6
0
if ($resetcap === null && preg_match(',\\A/(U?1[-\\w]+)(?:/|\\z),i', Navigation::path(), $m)) {
    $resetcap = $m[1];
}
if (!$resetcap) {
    error_go(false, "You didn’t enter the full password reset link into your browser. Make sure you include the reset code (the string of letters, numbers, and other characters at the end).");
}
$iscdb = substr($resetcap, 0, 1) === "U";
$capmgr = $Conf->capability_manager($resetcap);
$capdata = $capmgr->check($resetcap);
if (!$capdata || $capdata->capabilityType != CAPTYPE_RESETPASSWORD) {
    error_go(false, "That password reset code has expired, or you didn’t enter it correctly.");
}
if ($iscdb) {
    $Acct = Contact::contactdb_find_by_id($capdata->contactId);
} else {
    $Acct = Contact::find_by_id($capdata->contactId);
}
if (!$Acct) {
    error_go(false, "That password reset code refers to a user who no longer exists. Either create a new account or contact the conference administrator.");
}
// don't show information about the current user, if there is one
$Me = new Contact();
$password_class = "";
if (isset($_POST["go"]) && check_post()) {
    $_POST["password"] = trim(get_s($_POST, "password"));
    $_POST["password2"] = trim(get_s($_POST, "password2"));
    if ($_POST["password"] == "") {
        Conf::msg_error("You must enter a password.");
    } else {
        if ($_POST["password"] !== $_POST["password2"]) {
            Conf::msg_error("The two passwords you entered did not match.");
 function __construct($search, $args = array(), $qreq = null)
 {
     global $Conf;
     $this->search = $search;
     $this->contact = $this->search->contact;
     $this->qreq = $qreq ?: new Qobject();
     $this->sortable = isset($args["sort"]) && $args["sort"];
     if ($this->sortable && is_string($args["sort"])) {
         $this->sorters[] = ListSorter::parse_sorter($args["sort"]);
     } else {
         if ($this->sortable && $this->qreq->sort) {
             $this->sorters[] = ListSorter::parse_sorter($this->qreq->sort);
         } else {
             $this->sorters[] = ListSorter::parse_sorter("");
         }
     }
     $this->foldable = $this->sortable || !!get($args, "foldable") || $this->contact->privChair;
     $this->_paper_link_page = "";
     if (isset($qreq->linkto) && ($qreq->linkto == "paper" || $qreq->linkto == "review" || $qreq->linkto == "assign")) {
         $this->_paper_link_page = $qreq->linkto;
     }
     $this->listNumber = 0;
     if (get($args, "list")) {
         $this->listNumber = SessionList::allocate($search->listId($this->sortdef()));
     }
     if (is_string(get($args, "display"))) {
         $this->display = " " . $args["display"] . " ";
     } else {
         $svar = get($args, "foldtype", "pl") . "display";
         $this->display = $Conf->session($svar, "");
     }
     if (isset($args["reviewer"]) && ($r = $args["reviewer"])) {
         if (!is_object($r)) {
             error_log(caller_landmark() . ": warning: 'reviewer' not an object");
             $r = Contact::find_by_id($r);
         }
         $this->_reviewer = $r;
     }
     $this->atab = $this->qreq->atab;
     $this->_row_id_pattern = get($args, "row_id_pattern");
     $this->tagger = new Tagger($this->contact);
     $this->scoresOk = $this->contact->privChair || $this->contact->is_reviewer() || $Conf->timeAuthorViewReviews();
     $this->qopts = array("scores" => [], "options" => true);
     if ($this->search->complexSearch($this->qopts)) {
         $this->qopts["paperId"] = $this->search->paperList();
     }
     // NB that actually processed the search, setting PaperSearch::viewmap
     $this->viewmap = new Qobject($this->search->viewmap);
     if ($this->viewmap->compact || $this->viewmap->cc || $this->viewmap->compactcolumn || $this->viewmap->ccol || $this->viewmap->compactcolumns) {
         $this->viewmap->compactcolumns = $this->viewmap->columns = true;
     }
     if ($this->viewmap->column || $this->viewmap->col) {
         $this->viewmap->columns = true;
     }
     if ($this->viewmap->stat || $this->viewmap->stats || $this->viewmap->totals) {
         $this->viewmap->statistics = true;
     }
     if ($this->viewmap->authors && $this->viewmap->au === null) {
         $this->viewmap->au = true;
     }
     if ($Conf->submission_blindness() != Conf::BLIND_OPTIONAL && $this->viewmap->au && $this->viewmap->anonau === null) {
         $this->viewmap->anonau = true;
     }
     if ($this->viewmap->anonau && $this->viewmap->au === null) {
         $this->viewmap->au = true;
     }
     if ($this->viewmap->rownumbers) {
         $this->viewmap->rownum = true;
     }
 }
function refuseReview()
{
    global $Conf, $Opt, $Me, $prow, $paperTable;
    Dbl::qe_raw("lock tables PaperReview write, PaperReviewRefused write");
    $rrow = $paperTable->editrrow;
    $hadToken = defval($rrow, "reviewToken", 0) != 0;
    $result = Dbl::qe("delete from PaperReview where reviewId={$rrow->reviewId}");
    if (!$result) {
        return;
    }
    $reason = defval($_REQUEST, "reason", "");
    if ($reason == "Optional explanation") {
        $reason = "";
    }
    $result = Dbl::qe("insert into PaperReviewRefused set paperId={$rrow->paperId}, contactId={$rrow->contactId}, requestedBy={$rrow->requestedBy}, reason=?", trim($reason));
    if (!$result) {
        return;
    }
    // now the requester must potentially complete their review
    if ($rrow->reviewType < REVIEW_SECONDARY && $rrow->requestedBy > 0) {
        Contact::update_review_delegation($rrow->paperId, $rrow->requestedBy, -1);
    }
    Dbl::qe_raw("unlock tables");
    // send confirmation email
    $Requester = Contact::find_by_id($rrow->requestedBy);
    $reqprow = $Conf->paperRow($prow->paperId, $rrow->requestedBy);
    HotCRPMailer::send_to($Requester, "@refusereviewrequest", $reqprow, array("reviewer_contact" => $rrow, "reason" => $reason));
    // confirmation message
    $Conf->confirmMsg("The request that you review paper #{$prow->paperId} has been removed.  Mail was sent to the person who originally requested the review.");
    if ($hadToken) {
        $Conf->update_rev_tokens_setting(true);
    }
    $prow = null;
    confHeader();
    $Conf->footer();
    exit;
}
                    }
                    loadRows();
                }
            }
        }
    }
}
// deny review request
if (isset($_REQUEST["deny"]) && $Me->allow_administer($prow) && check_post() && ($email = trim(defval($_REQUEST, "email", "")))) {
    Dbl::qe_raw("lock tables ReviewRequest write, ContactInfo read, PaperConflict read, PaperReview read, PaperReviewRefused write");
    // Need to be careful and not expose inappropriate information:
    // this email comes from the chair, who can see all, but goes to a PC
    // member, who can see less.
    $result = Dbl::qe_raw("select requestedBy from ReviewRequest where paperId={$prow->paperId} and email='" . sqlq($email) . "'");
    if ($row = edb_row($result)) {
        $Requester = Contact::find_by_id($row[0]);
        Dbl::qe_raw("delete from ReviewRequest where paperId={$prow->paperId} and email='" . sqlq($email) . "'");
        if (($reqId = Contact::id_by_email($email)) > 0) {
            Dbl::qe_raw("insert into PaperReviewRefused (paperId, contactId, requestedBy, reason) values ({$prow->paperId}, {$reqId}, {$Requester->contactId}, 'request denied by chair')");
        }
        // send anticonfirmation email
        HotCRPMailer::send_to($Requester, "@denyreviewrequest", $prow, array("reviewer_contact" => (object) array("fullName" => trim(defval($_REQUEST, "name", "")), "email" => $email)));
        $Conf->confirmMsg("Proposed reviewer denied.");
    } else {
        Conf::msg_error("No one has proposed that " . htmlspecialchars($email) . " review this paper.");
    }
    Dbl::qx_raw("unlock tables");
    unset($_REQUEST["email"], $_GET["email"], $_POST["email"]);
    unset($_REQUEST["name"], $_GET["name"], $_POST["name"]);
}
// add primary or secondary reviewer
 function ksort_cid_array(&$a)
 {
     $pcm = pcMembers();
     uksort($a, function ($a, $b) use($pcm) {
         if (isset($pcm[$a]) && isset($pcm[$b])) {
             return $pcm[$a]->sort_position - $pcm[$b]->sort_position;
         }
         if (isset($pcm[$a])) {
             $as = $pcm[$a]->sorter;
         } else {
             if (isset($this->contact_sorter_map_[$a])) {
                 $as = $this->contact_sorter_map_[$a];
             } else {
                 $x = Contact::find_by_id($a);
                 $as = $this->contact_sorter_map_[$a] = $x->sorter;
             }
         }
         if (isset($pcm[$b])) {
             $bs = $pcm[$b]->sorter;
         } else {
             if (isset($this->contact_sorter_map_[$b])) {
                 $bs = $this->contact_sorter_map_[$b];
             } else {
                 $x = Contact::find_by_id($b);
                 $bs = $this->contact_sorter_map_[$b] = $x->sorter;
             }
         }
         return strcasecmp($as, $bs);
     });
 }
    exit($status);
}
if (!@$Opt["contactdb_dsn"]) {
    fwrite(STDERR, "Conference has no contactdb_dsn\n");
    exit(1);
}
$users = isset($arg["u"]) || isset($arg["users"]);
$papers = isset($arg["p"]) || isset($arg["papers"]);
$collaborators = isset($arg["collaborators"]);
if (!$users && !$papers && !$collaborators) {
    $users = $papers = true;
}
if ($users) {
    $result = Dbl::ql($Conf->dblink, "select ContactInfo.contactId, email from ContactInfo\n        left join PaperConflict on (PaperConflict.contactId=ContactInfo.contactId and PaperConflict.conflictType>=" . CONFLICT_AUTHOR . ")\n        left join PaperReview on (PaperReview.contactId=ContactInfo.contactId)\n        where roles!=0 or PaperConflict.conflictType is not null\n            or PaperReview.reviewId is not null\n        group by ContactInfo.contactId");
    while ($row = edb_row($result)) {
        $contact = Contact::find_by_id($row[0]);
        $contact->contactdb_update();
    }
    Dbl::free($result);
}
if ($papers) {
    $result = Dbl::ql(Contact::contactdb(), "select confid from Conferences where `dbname`=?", $Opt["dbName"]);
    $row = Dbl::fetch_first_row($result);
    if (!$row) {
        fwrite(STDERR, "Conference is not recored in contactdb\n");
        exit(1);
    }
    $confid = $row[0];
    $result = Dbl::ql($Conf->dblink, "select paperId, title from Paper");
    $q = array();
    while ($row = edb_row($result)) {
 function save($cj, $old_user = null, $actor = null)
 {
     global $Conf, $Me, $Now;
     assert(is_object($cj));
     self::normalize_name($cj);
     if (!$old_user && is_int(get($cj, "id")) && $cj->id) {
         $old_user = Contact::find_by_id($cj->id);
     } else {
         if (!$old_user && is_string(get($cj, "email")) && $cj->email) {
             $old_user = Contact::find_by_email($cj->email);
         }
     }
     if (!get($cj, "id")) {
         $cj->id = $old_user ? $old_user->contactId : "new";
     }
     if ($cj->id !== "new" && $old_user && $cj->id != $old_user->contactId) {
         $this->set_error("id", "Saving user with different ID");
         return false;
     }
     $no_old_db_account = !$old_user || !$old_user->has_database_account();
     $old_cdb_user = null;
     if ($old_user && $old_user->has_email()) {
         $old_cdb_user = Contact::contactdb_find_by_email($old_user->email);
     } else {
         if (is_string(get($cj, "email")) && $cj->email) {
             $old_cdb_user = Contact::contactdb_find_by_email($cj->email);
         }
     }
     $user = $old_user ?: $old_cdb_user;
     $this->normalize($cj, $user);
     if ($this->nerrors) {
         return false;
     }
     $this->check_invariants($cj);
     $user = $user ?: new Contact();
     if (($send = $this->send_email) === null) {
         $send = !$old_cdb_user;
     }
     if ($user->save_json($cj, $actor, $send)) {
         return $user;
     } else {
         return false;
     }
 }
function save_comment($text, $is_response, $roundnum)
{
    global $Me, $Conf, $prow, $crow;
    if ($crow) {
        $roundnum = (int) $crow->commentRound;
    }
    // If I have a review token for this paper, save under that anonymous user.
    $user = $Me;
    if ((!$crow || $crow->contactId != $Me->contactId) && ($cid = $Me->review_token_cid($prow)) && (!$crow || $crow->contactId == $cid)) {
        $user = Contact::find_by_id($cid);
    }
    $req = array("visibility" => @$_REQUEST["visibility"], "submit" => $is_response && @$_REQUEST["submitresponse"], "text" => $text, "tags" => @$_REQUEST["commenttags"], "blind" => @$_REQUEST["blind"]);
    if ($is_response && !$crow) {
        $cinfo = new CommentInfo((object) array("commentType" => COMMENTTYPE_RESPONSE, "commentRound" => $roundnum), $prow);
    } else {
        $cinfo = new CommentInfo($crow, $prow);
    }
    $ok = $cinfo->save($req, $user);
    $what = $is_response ? "Response" : "Comment";
    $confirm = false;
    if (!$ok && $is_response) {
        $crows = $Conf->comment_rows($Conf->comment_query("paperId={$prow->paperId} and (commentType&" . COMMENTTYPE_RESPONSE . ")!=0 and commentRound={$roundnum}"), $Me);
        reset($crows);
        $cur_response = @current($crows);
        if ($cur_response && $cur_response->comment == $text) {
            $cinfo = new CommentInfo($cur_response, $prow);
            $ok = true;
        } else {
            $confirm = Ht::xmsg("error", "A response was entered concurrently by another user. Reload to see it.");
        }
    }
    if (!$ok) {
        /* nada */
    } else {
        if ($is_response && (!$cinfo->commentId || $cinfo->commentType & COMMENTTYPE_DRAFT)) {
            if ($cinfo->commentId) {
                $confirm = 'Response saved. <strong>This draft response will not be shown to reviewers.</strong>';
            } else {
                $confirm = 'Response deleted.';
            }
            $isuf = $roundnum ? "_{$roundnum}" : "";
            if (($dl = $Conf->printableTimeSetting("resp_done{$isuf}")) != "N/A") {
                $confirm .= " You have until {$dl} to submit the response.";
            }
            $confirm = Ht::xmsg("warning", $confirm);
        } else {
            if ($is_response) {
                $rname = $Conf->resp_round_text($roundnum);
                $confirm = Ht::xmsg("confirm", ($rname ? "{$rname} response" : "Response") . ' submitted.');
            } else {
                if ($cinfo->commentId) {
                    $confirm = Ht::xmsg("confirm", "Comment saved.");
                } else {
                    $confirm = Ht::xmsg("confirm", "Comment deleted.");
                }
            }
        }
    }
    $j = array("ok" => $ok);
    if ($cinfo->commentId) {
        $j["cmt"] = $cinfo->unparse_json($Me);
    }
    if ($confirm) {
        $j["msg"] = $confirm;
    }
    $Conf->ajaxExit($j);
}
Exemple #14
0
 static function send_manager($template, $row, $rest = array())
 {
     if ($row && $row->managerContactId && ($c = Contact::find_by_id($row->managerContactId))) {
         self::send_to($c, $template, $row, $rest);
     } else {
         self::send_to(Contact::site_contact(), $template, $row, $rest);
     }
 }
 function cleanup(AssignmentSet $aset)
 {
     global $Conf;
     if ($this->notify) {
         $reviewer = Contact::find_by_id($this->cid);
         $prow = $Conf->paperRow(array("paperId" => $this->pid, "reviewer" => $this->cid), $reviewer);
         HotCRPMailer::send_to($reviewer, $this->notify, $prow);
     }
 }
function update_schema_transfer_address($Conf)
{
    $result = Dbl::ql("select * from ContactAddress");
    while ($row = edb_orow($result)) {
        if ($c = Contact::find_by_id($row->contactId)) {
            $x = (object) array();
            if ($row->addressLine1 || $row->addressLine2) {
                $x->address = array();
            }
            foreach (array("addressLine1", "addressLine2") as $k) {
                if ($row->{$k}) {
                    $x->address[] = $row->{$k};
                }
            }
            foreach (array("city" => "city", "state" => "state", "zipCode" => "zip", "country" => "country") as $k => $v) {
                if ($row->{$k}) {
                    $x->{$v} = $row->{$k};
                }
            }
            $c->merge_and_save_data($x);
        }
    }
    return true;
}
 function save_review($req, $rrow, $prow, $contact, &$tf = null)
 {
     global $Conf, $Opt;
     $newsubmit = @$req["ready"] && !@$req["unready"] && (!$rrow || !$rrow->reviewSubmitted);
     $submit = $newsubmit || $rrow && $rrow->reviewSubmitted;
     $admin = $contact->allow_administer($prow);
     if (!$contact->timeReview($prow, $rrow) && (!isset($req['override']) || !$admin)) {
         return Conf::msg_error("The <a href='" . hoturl("deadlines") . "'>deadline</a> for entering this review has passed." . ($admin ? "  Select the “Override deadlines” checkbox and try again if you really want to override the deadline." : ""));
     }
     $q = array();
     $diff_view_score = VIEWSCORE_FALSE;
     $wc = 0;
     foreach ($this->forder as $field => $f) {
         if (isset($req[$field]) && (!$f->round_mask || $f->is_round_visible($rrow))) {
             $fval = $req[$field];
             if ($f->has_options) {
                 if ($f->parse_is_empty($fval)) {
                     $fval = 0;
                 } else {
                     if (!($fval = $f->parse_value($fval, false))) {
                         continue;
                     }
                 }
             } else {
                 $fval = rtrim($fval);
                 if ($fval != "") {
                     $fval .= "\n";
                 }
                 // Check for valid UTF-8; re-encode from Windows-1252 or Mac OS
                 $fval = convert_to_utf8($fval);
                 if ($f->include_word_count()) {
                     $wc += count_words($fval);
                 }
             }
             if ($rrow && strcmp($rrow->{$field}, $fval) != 0 && strcmp(cleannl($rrow->{$field}), cleannl($fval)) != 0) {
                 $diff_view_score = max($diff_view_score, $f->view_score);
             }
             $q[] = "{$field}='" . sqlq($fval) . "'";
         }
     }
     // get the current time
     $now = time();
     if ($rrow && $rrow->reviewModified && $rrow->reviewModified > $now) {
         $now = $rrow->reviewModified + 1;
     }
     // potentially assign review ordinal (requires table locking since
     // mySQL is stupid)
     $locked = false;
     if ($newsubmit) {
         $diff_view_score = max($diff_view_score, VIEWSCORE_AUTHOR);
         $q[] = "reviewSubmitted={$now}, reviewNeedsSubmit=0";
         if (!$rrow || !$rrow->reviewOrdinal) {
             $result = $Conf->qe("lock tables PaperReview write");
             if (!$result) {
                 return $result;
             }
             $locked = true;
             $result = $Conf->qe("select coalesce(max(reviewOrdinal), 0) from PaperReview where paperId={$prow->paperId} group by paperId");
             if ($result) {
                 $crow = edb_row($result);
                 $q[] = "reviewOrdinal=coalesce(reviewOrdinal, " . ($crow[0] + 1) . ")";
             }
             Dbl::free($result);
             $q[] = "timeDisplayed={$now}";
         }
     }
     // check whether used a review token
     $usedReviewToken = $contact->review_token_cid($prow, $rrow);
     // blind? reviewer type? edit version?
     $reviewBlind = $Conf->is_review_blind(!!@$req["blind"]);
     if ($rrow && $reviewBlind != $rrow->reviewBlind) {
         $diff_view_score = max($diff_view_score, VIEWSCORE_ADMINONLY);
     }
     $q[] = "reviewBlind=" . ($reviewBlind ? 1 : 0);
     if ($rrow && $rrow->reviewType == REVIEW_EXTERNAL && $contact->contactId == $rrow->contactId && $contact->isPC && !$usedReviewToken) {
         $q[] = "reviewType=" . REVIEW_PC;
     }
     if ($rrow && $diff_view_score > VIEWSCORE_FALSE && isset($req["version"]) && ctype_digit($req["version"]) && $req["version"] > defval($rrow, "reviewEditVersion")) {
         $q[] = "reviewEditVersion=" . ($req["version"] + 0);
     }
     if ($diff_view_score > VIEWSCORE_FALSE && $Conf->sversion >= 98) {
         $q[] = "reviewWordCount=" . $wc;
     }
     if (isset($req["reviewFormat"]) && $Conf->sversion >= 104 && @$Opt["formatInfo"]) {
         $fmt = null;
         foreach ($Opt["formatInfo"] as $k => $f) {
             if (@$f["name"] && strcasecmp($f["name"], $req["reviewFormat"]) == 0) {
                 $fmt = (int) $k;
             }
         }
         if (!$fmt && $req["reviewFormat"] && preg_match('/\\A(?:plain\\s*)?(?:text)?\\z/i', $f["reviewFormat"])) {
             $fmt = 0;
         }
         $q[] = "reviewFormat=" . ($fmt === null ? "null" : $fmt);
     }
     // notification
     $notification_bound = $now - 10800;
     $notify = $notify_author = false;
     if (!$rrow || $diff_view_score > VIEWSCORE_FALSE) {
         $q[] = "reviewModified=" . $now;
         // do not notify on updates within 3 hours
         if ($submit && $diff_view_score > VIEWSCORE_ADMINONLY) {
             if (!$rrow || !$rrow->reviewNotified || $rrow->reviewNotified < $notification_bound) {
                 $q[] = $notify = "reviewNotified=" . $now;
             }
             if ((!$rrow || !$rrow->reviewAuthorNotified || $rrow->reviewAuthorNotified < $notification_bound) && $diff_view_score >= VIEWSCORE_AUTHOR && Contact::can_some_author_view_submitted_review($prow)) {
                 $q[] = $notify_author = "reviewAuthorNotified=" . $now;
             }
         }
     }
     // actually affect database
     if ($rrow) {
         $result = $Conf->qe("update PaperReview set " . join(", ", $q) . " where reviewId={$rrow->reviewId}");
         $reviewId = $rrow->reviewId;
         $contactId = $rrow->contactId;
     } else {
         $result = Dbl::qe_raw("insert into PaperReview set paperId={$prow->paperId}, contactId={$contact->contactId}, reviewType=" . REVIEW_PC . ", requestedBy={$contact->contactId}, reviewRound=" . $Conf->current_round() . ", " . join(", ", $q));
         $reviewId = $result ? $result->insert_id : null;
         $contactId = $contact->contactId;
     }
     // unlock tables even if problem
     if ($locked) {
         $Conf->qe("unlock tables");
     }
     if (!$result) {
         return $result;
     }
     // update caches
     Contact::update_rights();
     // look up review ID
     if (!$reviewId) {
         return $reviewId;
     }
     $req['reviewId'] = $reviewId;
     // log updates -- but not if review token is used
     if (!$usedReviewToken && $diff_view_score > VIEWSCORE_FALSE) {
         $text = "Review {$reviewId} ";
         if ($rrow && $contact->contactId != $rrow->contactId) {
             $text .= "by {$rrow->email} ";
         }
         $text .= $newsubmit ? "submitted" : ($submit ? "updated" : "saved draft");
         $contact->log_activity($text, $prow);
     }
     // potentially email chair, reviewers, and authors
     if ($submit) {
         $rrow = $Conf->reviewRow(["reviewId" => $reviewId]);
     }
     if ($submit && ($notify || $notify_author) && $rrow) {
         $tmpl = $newsubmit ? "@reviewsubmit" : "@reviewupdate";
         $submitter = $contact;
         if ($contactId != $submitter->contactId) {
             $submitter = Contact::find_by_id($contactId);
         }
         // construct mail
         $this->mailer_info = array("template" => $tmpl, "rrow" => $rrow, "reviewer_contact" => $submitter, "reviewNumber" => $prow->paperId . unparseReviewOrdinal($rrow->reviewOrdinal), "check_function" => "HotCRPMailer::check_can_view_review", "diff_view_score" => $diff_view_score);
         $this->mailer_preps = array();
         if ($Conf->timeEmailChairAboutReview()) {
             HotCRPMailer::send_manager($tmpl, $prow, $this->mailer_info);
         }
         $prow->notify(WATCHTYPE_REVIEW, array($this, "review_watch_callback"), $contact);
         if (count($this->mailer_preps)) {
             HotCRPMailer::send_combined_preparations($this->mailer_preps);
         }
         unset($this->mailer_info, $this->mailer_preps);
     }
     // if external, forgive the requestor from finishing their review
     if ($rrow && $rrow->reviewType < REVIEW_SECONDARY && $rrow->requestedBy && $submit) {
         $Conf->q("update PaperReview set reviewNeedsSubmit=0 where paperId={$prow->paperId} and contactId={$rrow->requestedBy} and reviewType=" . REVIEW_SECONDARY . " and reviewSubmitted is null");
     }
     if ($tf !== null) {
         $what = "#{$prow->paperId}" . ($rrow && $rrow->reviewSubmitted ? unparseReviewOrdinal($rrow->reviewOrdinal) : "");
         if ($newsubmit) {
             $tf["newlySubmitted"][] = $what;
         } else {
             if ($diff_view_score > VIEWSCORE_FALSE && $submit) {
                 $tf["updated"][] = $what;
             } else {
                 if ($diff_view_score > VIEWSCORE_FALSE) {
                     $tf["savedDraft"][] = $what;
                 } else {
                     $tf["unchanged"][] = $what;
                 }
             }
         }
         if ($notify_author) {
             $tf["authorNotified"][] = $what;
         }
     }
     return $result;
 }
 function reviewer()
 {
     if (is_object($this->_reviewer)) {
         return $this->_reviewer;
     } else {
         if ($this->_reviewer) {
             return Contact::find_by_id($this->_reviewer);
         } else {
             return null;
         }
     }
 }