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 &ldquo;order:{$tag}&rdquo;</a>.");
        }
    }
}