private function check_options($sv, $fid, $fj) { global $Conf; if (!isset($sv->req["options_{$fid}"])) { $fj->options = array(); return get($fj, "position") ? false : true; } $text = cleannl($sv->req["options_{$fid}"]); $letters = $text && ord($text[0]) >= 65 && ord($text[0]) <= 90; $expect = $letters ? "[A-Z]" : "[1-9]"; $opts = array(); $lowonum = 10000; $allow_empty = false; foreach (explode("\n", $text) as $line) { $line = trim($line); if ($line != "") { if ((preg_match("/^({$expect})\\.\\s*(\\S.*)/", $line, $m) || preg_match("/^({$expect})\\s+(\\S.*)/", $line, $m)) && !isset($opts[$m[1]])) { $onum = $letters ? ord($m[1]) : (int) $m[1]; $lowonum = min($lowonum, $onum); $opts[$onum] = $m[2]; } else { if (preg_match('/^No entry$/i', $line)) { $allow_empty = true; } else { return false; } } } } // numeric options must start from 1 if (!$letters && count($opts) > 0 && $lowonum != 1) { return false; } // must have at least 2 options, but off-form fields don't count if (count($opts) < 2 && get($fj, "position")) { return false; } $text = ""; $seqopts = array(); for ($onum = $lowonum; $onum < $lowonum + count($opts); ++$onum) { if (!isset($opts[$onum])) { // options out of order return false; } $seqopts[] = $opts[$onum]; } if ($letters) { $seqopts = array_reverse($seqopts, true); $fj->option_letter = chr($lowonum); } $fj->options = array_values($seqopts); if ($allow_empty) { $fj->allow_empty = true; } return true; }
function parse_value($sv, $name, $info) { global $Conf, $Me, $Now, $Opt; if (!isset($sv->req[$name])) { $xname = str_replace(".", "_", $name); if (isset($sv->req[$xname])) { $sv->req[$name] = $sv->req[$xname]; } else { if ($info->type === "checkbox" || $info->type === "cdate") { return 0; } else { return null; } } } $v = trim($sv->req[$name]); if ($info->placeholder && $info->placeholder === $v || $info->invalid_value && $info->invalid_value === $v) { $v = ""; } if ($info->type === "checkbox") { return $v != "" ? 1 : 0; } else { if ($info->type === "cdate" && $v == "1") { return 1; } else { if ($info->type === "date" || $info->type === "cdate" || $info->type === "ndate") { if ($v == "" || !strcasecmp($v, "N/A") || !strcasecmp($v, "same as PC") || $v == "0" || $info->type !== "ndate" && !strcasecmp($v, "none")) { return -1; } else { if (!strcasecmp($v, "none")) { return 0; } else { if (($v = $Conf->parse_time($v)) !== false) { return $v; } else { $err = unparse_setting_error($info, "Invalid date."); } } } } else { if ($info->type === "grace") { if (($v = parseGrace($v)) !== null) { return intval($v); } else { $err = unparse_setting_error($info, "Invalid grace period."); } } else { if ($info->type === "int" || $info->type === "zint") { if (preg_match("/\\A[-+]?[0-9]+\\z/", $v)) { return intval($v); } else { $err = unparse_setting_error($info, "Should be a number."); } } else { if ($info->type === "string") { // Avoid storing the default message in the database if (substr($name, 0, 9) == "mailbody_") { $t = expandMailTemplate(substr($name, 9), true); $v = cleannl($v); if ($t["body"] == $v) { return ""; } } return $v; } else { if ($info->type === "simplestring") { return simplify_whitespace($v); } else { if ($info->type === "tag" || $info->type === "tagbase") { $tagger = new Tagger($Me); $v = trim($v); if ($v === "" && $info->optional) { return $v; } $v = $tagger->check($v, $info->type === "tagbase" ? Tagger::NOVALUE : 0); if ($v) { return $v; } $err = unparse_setting_error($info, $tagger->error_html); } else { if ($info->type === "emailheader") { $v = MimeText::encode_email_header("", $v); if ($v !== false) { return $v == "" ? "" : MimeText::decode_header($v); } $err = unparse_setting_error($info, "Invalid email header."); } else { if ($info->type === "emailstring") { $v = trim($v); if ($v === "" && $info->optional) { return ""; } else { if (validate_email($v) || $v === $v_active) { return $v; } else { $err = unparse_setting_error($info, "Invalid email."); } } } else { if ($info->type === "urlstring") { $v = trim($v); if ($v === "" && $info->optional || preg_match(',\\A(?:https?|ftp)://\\S+\\z,', $v)) { return $v; } else { $err = unparse_setting_error($info, "Invalid URL."); } } else { if ($info->type === "htmlstring") { if (($v = CleanHTML::basic_clean($v, $err)) === false) { $err = unparse_setting_error($info, $err); } else { if ($info->message_default && $v === $Conf->message_default_html($info->message_default)) { return ""; } else { return $v; } } } else { if ($info->type === "radio") { foreach ($info->values as $allowedv) { if ((string) $allowedv === $v) { return $allowedv; } } $err = unparse_setting_error($info, "Parse error (unexpected value)."); } else { return $v; } } } } } } } } } } } } } $sv->set_error($name, $err); return null; }
function option_request_to_json($sv, &$new_opts, $id, $current_opts) { global $Conf; $name = simplify_whitespace(defval($sv->req, "optn{$id}", "")); if (!isset($sv->req["optn{$id}"]) && $id[0] !== "n") { if (get($current_opts, $id)) { $new_opts[$id] = $current_opts[$id]; } return; } else { if ($name === "" || $sv->req["optfp{$id}"] === "delete" || $id[0] === "n" && ($name === "New option" || $name === "(Enter new option)")) { return; } } $oarg = ["name" => $name, "id" => (int) $id, "final" => false]; if ($id[0] === "n") { $nextid = max($Conf->setting("next_optionid", 1), 1); foreach ($new_opts as $haveid => $o) { $nextid = max($nextid, $haveid + 1); } foreach ($current_opts as $haveid => $o) { $nextid = max($nextid, $haveid + 1); } $oarg["id"] = $nextid; } if (get($sv->req, "optd{$id}") && trim($sv->req["optd{$id}"]) != "") { $t = CleanHTML::basic_clean($sv->req["optd{$id}"], $err); if ($t !== false) { $oarg["description"] = $t; } else { $sv->set_error("optd{$id}", $err); } } if ($optvt = get($sv->req, "optvt{$id}")) { if (($pos = strpos($optvt, ":")) !== false) { $oarg["type"] = substr($optvt, 0, $pos); if (preg_match('/:final/', $optvt)) { $oarg["final"] = true; } if (preg_match('/:ds_(\\d+)/', $optvt, $m)) { $oarg["display_space"] = (int) $m[1]; } } else { $oarg["type"] = $optvt; } } else { $oarg["type"] = "checkbox"; } if (PaperOption::type_has_selector($oarg["type"])) { $oarg["selector"] = array(); $seltext = trim(cleannl(defval($sv->req, "optv{$id}", ""))); if ($seltext != "") { foreach (explode("\n", $seltext) as $t) { $oarg["selector"][] = $t; } } else { $sv->set_error("optv{$id}", "Enter selectors one per line."); } } $oarg["visibility"] = defval($sv->req, "optp{$id}", "rev"); if ($oarg["final"]) { $oarg["visibility"] = "rev"; } $oarg["position"] = (int) defval($sv->req, "optfp{$id}", 1); $oarg["display"] = defval($sv->req, "optdt{$id}"); if ($oarg["type"] === "pdf" && $oarg["final"]) { $oarg["display"] = "submission"; } $new_opts[$oarg["id"]] = $o = PaperOption::make($oarg); $o->req_id = $id; $o->is_new = $id[0] === "n"; }
function expand($text, $field = null) { if (is_array($text)) { $a = array(); foreach ($text as $k => $t) { $a[$k] = $this->expand($t, $k); } return $a; } // leave early on empty string if ($text == "") { return ""; } // width, expansion type based on field $oldExpansionType = $this->expansionType; $width = 100000; if ($field == "to" || $field == "cc" || $field == "bcc" || $field == "reply-to") { $this->expansionType = self::EXPAND_EMAIL; } else { if ($field != "body" && $field != "") { $this->expansionType = self::EXPAND_HEADER; } else { $this->expansionType = self::EXPAND_BODY; $width = $this->width; } } // expand out %IF% and %ELSE% and %ENDIF%. Need to do this first, // or we get confused with wordwrapping. $text = $this->_expandConditionals(cleannl($text)); // separate text into lines $lines = explode("\n", $text); if (count($lines) && $lines[count($lines) - 1] === "") { array_pop($lines); } $text = ""; $textstart = 0; for ($i = 0; $i < count($lines); ++$i) { $line = rtrim($lines[$i]); if ($line == "") { $text .= "\n"; } else { if (preg_match('/^%(?:REVIEWS|COMMENTS)(?:[(].*[)])?%$/', $line)) { if (($m = $this->expandvar($line, false)) != "") { $text .= $m . "\n"; } } else { if (preg_match('/^([ \\t][ \\t]*.*?: )(%OPT\\([\\w()]+\\)%)$/', $line, $m)) { if ($yes = $this->expandvar($m[2], true)) { $text .= prefix_word_wrap($m[1], $this->expandvar($m[2]), tabLength($m[1], true), $width); } else { if ($yes === null) { $text .= $line . "\n"; } } } else { if (preg_match('/^([ \\t][ \\t]*.*?: )(%\\w+(?:|\\([^\\)]*\\))%|\\S+)\\s*$/', $line, $m)) { $text .= $this->_lineexpand($m[2], $m[1], tabLength($m[1], true), $width); } else { if (strpos($line, '%') !== false) { $text .= $this->_lineexpand($line, "", 0, $width); } else { $text .= prefix_word_wrap("", $line, 0, $width); } } } } } } // lose newlines on header expansion if ($this->expansionType != self::EXPAND_BODY) { $text = rtrim(preg_replace('/[\\r\\n\\f\\x0B]+/', ' ', $text)); } $this->expansionType = $oldExpansionType; return $text; }
function parseBulkFile($text, $filename) { global $Conf; $text = cleannl($text); if (!is_valid_utf8($text)) { $text = windows_1252_to_utf8($text); } $filename = $filename ? "{$filename}:" : "line "; $success = array(); if (!preg_match('/\\A[^\\r\\n]*(?:,|\\A)(?:user|email)(?:[,\\r\\n]|\\z)/', $text) && !preg_match('/\\A[^\\r\\n]*,[^\\r\\n]*,/', $text)) { $tarr = CsvParser::split_lines($text); foreach ($tarr as &$t) { if (($t = trim($t)) && $t[0] !== "#" && $t[0] !== "%") { $t = CsvGenerator::quote($t); } $t .= "\n"; } unset($t); $text = join("", $tarr); } $csv = new CsvParser($text); $csv->set_comment_chars("#%"); $line = $csv->next(); if ($line && (array_search("email", $line) !== false || array_search("user", $line) !== false)) { $csv->set_header($line); } else { $csv->set_header(array("user")); $csv->unshift($line); } $cj_template = (object) array(); $topic_revmap = array(); foreach ($Conf->topic_map() as $id => $name) { $topic_revmap[strtolower($name)] = $id; } $unknown_topics = array(); $errors = array(); while (($line = $csv->next()) !== false) { $cj = clone $cj_template; foreach ($line as $k => $v) { $cj->{$k} = $v; } foreach (array("firstname" => "firstName", "first" => "firstName", "lastname" => "lastName", "last" => "lastName", "fullname" => "name", "fullName" => "name", "voice" => "voicePhoneNumber", "phone" => "voicePhoneNumber", "address1" => "addressLine1", "province" => "state", "region" => "state", "address2" => "addressLine2", "postalcode" => "zipCode", "zip" => "zipCode", "tags" => "contactTags") as $k => $x) { if (isset($cj->{$k}) && !isset($cj->{$x})) { $cj->{$x} = $cj->{$k}; } } // thou shalt not set passwords by bulk update unset($cj->password, $cj->password_plaintext, $cj->new_password); if (isset($cj->name) && !isset($cj->firstName) && !isset($cj->lastName)) { list($cj->firstName, $cj->lastName) = Text::split_name($cj->name); } if (count($topic_revmap)) { foreach (array_keys($line) as $k) { if (preg_match('/^topic:\\s*(.*?)\\s*$/i', $k, $m)) { if (($ti = @$topic_revmap[strtolower($m[1])]) !== null) { $x = $line[$k]; if (strtolower($x) === "low") { $x = -2; } else { if (strtolower($x) === "high") { $x = 4; } else { if (!is_numeric($x)) { $x = 0; } } } if (!@$cj->topics) { $cj->topics = (object) array(); } $cj->topics->{$ti} = $x; } else { $unknown_topics[$m[1]] = true; } } } } $cj->id = "new"; $ustatus = new UserStatus(array("send_email" => true, "no_deprivilege_self" => true)); if ($saved_user = save_user($cj, $ustatus, null, true)) { $success[] = "<a href=\"" . hoturl("profile", "u=" . urlencode($saved_user->email)) . "\">" . Text::user_html_nolink($saved_user) . "</a>"; } foreach ($ustatus->error_messages() as $e) { $errors[] = "<span class='lineno'>" . $filename . $csv->lineno() . ":</span> " . $e; } } if (count($unknown_topics)) { $errors[] = "There were unrecognized topics (" . htmlspecialchars(commajoin($unknown_topics)) . ")."; } if (count($success) == 1) { $successMsg = "Saved account " . $success[0] . "."; } else { if (count($success)) { $successMsg = "Saved " . plural($success, "account") . ": " . commajoin($success) . "."; } } if (count($errors)) { $errorMsg = "<div class='parseerr'><p>" . join("</p>\n<p>", $errors) . "</p></div>"; } if (count($success) && count($errors)) { $Conf->confirmMsg($successMsg . "<br />{$errorMsg}"); } else { if (count($success)) { $Conf->confirmMsg($successMsg); } else { if (count($errors)) { Conf::msg_error($errorMsg); } else { $Conf->warnMsg("Nothing to do."); } } } return count($errors) == 0; }
function parseUploadedPreferences($filename, $printFilename, $reviewer) { global $Conf; if (($text = file_get_contents($filename)) === false) { return Conf::msg_error("Cannot read uploaded file."); } $printFilename = htmlspecialchars($printFilename); $text = cleannl($text); $lineno = 0; $successes = 0; $errors = array(); $new_qreq = new Qobject(); foreach (explode("\n", $text) as $line) { $line = trim($line); $lineno++; if ($line == "" || $line[0] == "#" || substr($line, 0, 6) == "==-== ") { /* do nothing */ } else { if (preg_match('/^(\\d+)\\s*[\\t,]\\s*([^\\s,]+)\\s*([\\t,]|$)/', $line, $m)) { if (parse_preference($m[2])) { $new_qreq["revpref{$m['1']}"] = $m[2]; $successes++; } else { if (strcasecmp($m[2], "conflict") != 0) { $errors[] = "<span class='lineno'>{$printFilename}:{$lineno}:</span> bad review preference, should be integer"; } } } else { if (preg_match('/^\\s*paper(?:id)?\\s*[\\t,]\\s*preference/i', $line)) { /* header; no error */ } else { if (count($errors) < 20) { $errors[] = "<span class='lineno'>{$printFilename}:{$lineno}:</span> syntax error, expected <code>paper,preference[,title]</code>"; } else { $errors[] = "<span class='lineno'>{$printFilename}:{$lineno}:</span> too many syntax errors, giving up"; break; } } } } } if (count($errors) > 0) { Conf::msg_error("There were some errors while parsing the uploaded preferences file. <div class='parseerr'><p>" . join("</p>\n<p>", $errors) . "</p></div>"); } if ($successes > 0) { savePreferences($new_qreq); } }
function beginTextForm($filename, $printFilename) { if (($contents = file_get_contents($filename)) === false) { return null; } return array('text' => cleannl($contents), 'filename' => $printFilename, 'lineno' => 0, 'err' => array(), 'confirm' => array()); }
function setTagIndexes() { global $Conf, $Me, $Error; $filename = null; if (isset($_REQUEST["upload"]) && fileUploaded($_FILES["file"])) { if (($text = file_get_contents($_FILES["file"]["tmp_name"])) === false) { Conf::msg_error("Internal error: cannot read file."); return; } $filename = @$_FILES["file"]["name"]; } else { if (!($text = defval($_REQUEST, "data"))) { Conf::msg_error("Choose a file first."); return; } } $RealMe = $Me; $tagger = new Tagger(); if ($tag = defval($_REQUEST, "tag")) { $tag = $tagger->check($tag, Tagger::NOVALUE); } $curIndex = 0; $lineno = 1; $settings = $titles = $linenos = $errors = array(); foreach (explode("\n", rtrim(cleannl($text))) as $l) { if (substr($l, 0, 4) == "Tag:" || substr($l, 0, 6) == "# Tag:") { if (!$tag) { $tag = $tagger->check(trim(substr($l, $l[0] == "#" ? 6 : 4)), Tagger::NOVALUE); } ++$lineno; continue; } else { if ($l == "" || $l[0] == "#") { ++$lineno; continue; } } if (preg_match('/\\A\\s*?([Xx=]|>*|\\([-\\d]+\\))\\s+(\\d+)\\s*(.*?)\\s*\\z/', $l, $m)) { if (isset($settings[$m[2]])) { $errors[$lineno] = "Paper #{$m['2']} already given on line " . $linenos[$m[2]]; } if ($m[1] == "X" || $m[1] == "x") { $settings[$m[2]] = null; } else { if ($m[1] == "" || $m[1] == ">") { $settings[$m[2]] = $curIndex = $curIndex + 1; } else { if ($m[1][0] == "(") { $settings[$m[2]] = $curIndex = substr($m[1], 1, -1); } else { if ($m[1] == "=") { $settings[$m[2]] = $curIndex; } else { $settings[$m[2]] = $curIndex = $curIndex + strlen($m[1]); } } } } $titles[$m[2]] = $m[3]; $linenos[$m[2]] = $lineno; } else { if ($RealMe->privChair && preg_match('/\\A\\s*<\\s*([^<>]*?(|<[^<>]*>))\\s*>\\s*\\z/', $l, $m)) { if (count($settings) && $Me) { saveTagIndexes($tag, $filename, $settings, $titles, $linenos, $errors); } $ret = ContactSearch::make_pc($m[1], $RealMe); $Me = null; if (count($ret->ids) == 1) { $Me = $ret->contact(0); } else { if (count($ret->ids) == 0) { $errors[$lineno] = htmlspecialchars($m[1]) . " matches no PC member"; } else { $errors[$lineno] = htmlspecialchars($m[1]) . " matches more than one PC member, give a full email address to disambiguate"; } } } else { if (trim($l) !== "") { $errors[$lineno] = "Syntax error"; } } } ++$lineno; } if (count($settings) && $Me) { saveTagIndexes($tag, $filename, $settings, $titles, $linenos, $errors); } $Me = $RealMe; if (count($errors)) { ksort($errors); if ($filename) { foreach ($errors as $lineno => &$error) { $error = '<span class="lineno">' . htmlspecialchars($filename) . ':' . $lineno . ':</span> ' . $error; } } $Error["tags"] = '<div class="parseerr"><p>' . join("</p>\n<p>", $errors) . '</p></div>'; } if (isset($Error["tags"])) { Conf::msg_error($Error["tags"]); } else { if (isset($_REQUEST["setvote"])) { $Conf->confirmMsg("Votes saved."); } else { $Conf->confirmMsg("Ranking saved. To view it, <a href='" . hoturl("search", "q=order:" . urlencode($tag)) . "'>search for “order:{$tag}”</a>."); } } }