function upload_grades($pset, $text, $fname) { global $Conf; assert($pset->gitless_grades); $csv = new CsvParser($text); $csv->set_header($csv->next()); while ($line = $csv->next()) { if (($who = get($line, "github_username")) && $who !== "-") { $user = $Conf->user_by_query("github_username=?", [$who]); } else { if (($who = get($line, "seascode_username")) && $who !== "-") { $user = $Conf->user_by_query("seascode_username=?", [$who]); } else { if (($who = get($line, "huid")) && $who !== "-") { $user = $Conf->user_by_query("huid=?", [$who]); } else { if (($who = get($line, "username")) && $who !== "-") { $user = $Conf->user_by_query("github_username=? or seascode_username=? order by github_username=? desc limit 1", [$who, $who, $who]); } else { if (($who = get($line, "email")) && $who !== "-") { $user = $Conf->user_by_email($who); } else { if ($who = get($line, "name")) { list($first, $last) = Text::split_name($who); $user = $Conf->user_by_query("firstName like '?s%' and lastName=?", [$first, $last]); if ($user && $user->firstName != $first && !str_starts_with($user->firstName, "{$first} ")) { $user = null; } } else { continue; } } } } } } if ($user) { if (!save_grades($user, $pset, null, $line, true)) { $Conf->errorMsg("no grades set for “" . htmlspecialchars($who) . "”"); } } else { $Conf->errorMsg(htmlspecialchars($fname) . ":" . $csv->lineno() . ": unknown user “" . htmlspecialchars($who) . "”"); } } return true; }
function upload_grades($pset, $text, $fname) { global $Conf; assert($pset->gitless_grades); $csv = new CsvParser($text); $csv->set_header($csv->next()); while ($line = $csv->next()) { if (@$line["seascode_username"]) { $who = $line["seascode_username"]; $user = Contact::find_by_username($who); } else { if (@$line["email"]) { $who = $line["email"]; $user = Contact::find_by_email($who); } else { if (@$line["name"]) { $who = $line["name"]; list($first, $last) = Text::split_name($who); $user = Contact::find_by_query("firstName like '" . sqlqtrim($first) . "%' and lastName='" . sqlqtrim($last) . "'"); if ($user && $user->firstName != $first && !str_starts_with($user->firstName, "{$first} ")) { $user = null; } } else { continue; } } } if ($user) { if (!save_grades($user, $pset, null, $line, true)) { $Conf->errorMsg("no grades set for “" . htmlspecialchars($who) . "”"); } } else { $Conf->errorMsg(htmlspecialchars($fname) . ":" . $csv->lineno() . ": unknown user “" . htmlspecialchars($who) . "”"); } } return true; }
static function normalize_name($cj) { $cj_user = isset($cj->user) ? Text::split_name($cj->user, true) : null; $cj_name = Text::analyze_name($cj); foreach (array("firstName", "lastName", "email") as $i => $k) { if ($cj_name->{$k} !== "" && $cj_name->{$k} !== false) { $cj->{$k} = $cj_name->{$k}; } else { if ($cj_user && $cj_user[$i]) { $cj->{$k} = $cj_user[$i]; } } } }
private function lookup_users(&$req, $assigner) { // move all usable identification data to email, firstName, lastName if (isset($req["name"])) { self::apply_user_parts($req, Text::split_name($req["name"])); } if (isset($req["user"]) && strpos($req["user"], " ") === false) { if (!get($req, "email")) { $req["email"] = $req["user"]; } } else { if (isset($req["user"])) { self::apply_user_parts($req, Text::split_name($req["user"], true)); } } // extract email, first, last $first = get($req, "firstName"); $last = get($req, "lastName"); $email = trim((string) get($req, "email")); $lemail = strtolower($email); $special = null; if ($lemail) { $special = $lemail; } else { if (!$first && $last && strpos(trim($last), " ") === false) { $special = trim(strtolower($last)); } } $xspecial = $special; if ($special === "all") { $special = "any"; } // check missing contact if (!$first && !$last && !$lemail) { if ($assigner->allow_special_contact("missing", $req, $this->astate)) { return array(null); } else { return $this->error("User missing."); } } // check special: "none", "any", "pc", "me", PC tag, "external" if ($special === "none" || $special === "any") { if (!$assigner->allow_special_contact($special, $req, $this->astate)) { return $this->error("User “{$xspecial}” not allowed here."); } return array((object) array("roles" => 0, "contactId" => null, "email" => $special, "sorter" => "")); } if ($special && !$first && (!$lemail || !$last)) { $ret = ContactSearch::make_special($special, $this->contact->contactId); if ($ret->ids !== false) { return $ret->contacts(); } } if (($special === "ext" || $special === "external") && $assigner->contact_set($req, $this->astate) === "reviewers") { $ret = array(); foreach ($this->reviewer_set() as $u) { if (!$u->is_pc_member()) { $ret[] = $u; } } return $ret; } // check for precise email match on existing contact (common case) if ($lemail && ($contact = $this->cmap->lookup_lemail($lemail))) { return array($contact); } // check PC list $cset = $assigner->contact_set($req, $this->astate); if ($cset === "pc") { $cset = pcMembers(); } else { if ($cset === "reviewers") { $cset = $this->reviewer_set(); } } if ($cset) { $text = ""; if ($first && $last) { $text = "{$last}, {$first}"; } else { if ($first || $last) { $text = "{$last}{$first}"; } } if ($email) { $text .= " <{$email}>"; } $ret = ContactSearch::make_cset($text, $this->contact->cid, $cset); if (count($ret->ids) == 1) { return $ret->contacts(); } else { if (count($ret->ids) == 0) { $this->error("No user matches “" . self::req_user_html($req) . "”."); } else { $this->error("“" . self::req_user_html($req) . "” matches more than one user, use a full email address to disambiguate."); } } return false; } // create contact if (!$email) { return $this->error("Missing email address"); } $contact = $this->cmap->make_email($email); if ($contact->contactId < 0) { if (!validate_email($email)) { return $this->error("Email address “" . htmlspecialchars($email) . "” is invalid."); } if (!isset($contact->firstName) && get($req, "firstName")) { $contact->firstName = $req["firstName"]; } if (!isset($contact->lastName) && get($req, "lastName")) { $contact->lastName = $req["lastName"]; } } return array($contact); }
function cleanAuthor($row) { if (!$row || isset($row->authorTable)) { return; } $row->authorTable = array(); if (strpos($row->authorInformation, "\t") === false) { foreach (explode("\n", $row->authorInformation) as $line) { if ($line != "") { $email = $aff = ""; if (($p1 = strpos($line, '<')) !== false) { $p2 = strpos($line, '>', $p1); if ($p2 === false) { $p2 = strlen($line); } $email = substr($line, $p1 + 1, $p2 - ($p1 + 1)); $line = substr($line, 0, $p1) . substr($line, $p2 + 1); } if (($p1 = strpos($line, '(')) !== false) { $p2 = strpos($line, ')', $p1); if ($p2 === false) { $p2 = strlen($line); } $aff = substr($line, $p1 + 1, $p2 - ($p1 + 1)); $line = substr($line, 0, $p1) . substr($line, $p2 + 1); if (!$email && strpos($aff, '@') !== false && preg_match('_^\\S+@\\S+\\.\\S+$_', $aff)) { $email = $aff; $aff = ''; } } $a = Text::split_name($line); $a[2] = $email; $a[3] = $aff; $row->authorTable[] = $a; } } } else { $info = ""; foreach (explode("\n", $row->authorInformation) as $line) { if ($line != "") { $row->authorTable[] = $a = explode("\t", $line); if ($a[0] && $a[1]) { $info .= "{$a['0']} {$a['1']}"; } else { $info .= $a[0] . $a[1]; } if ($a[3]) { $info .= " (" . $a[3] . ")"; } else { if ($a[2]) { $info .= " <" . $a[2] . ">"; } } $info .= "\n"; } } $row->authorInformation = $info; } }
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; }
private function check_user() { if (strcasecmp($this->text, "anonymous") == 0 && !$this->cset && !($this->type & self::F_PC)) { $result = Dbl::qe_raw("select contactId from ContactInfo where email regexp '^anonymous[0-9]*\$'"); return Dbl::fetch_first_columns($result); } // split name components list($f, $l, $e) = Text::split_name($this->text, true); if ($f === "" && $l === "" && strpos($e, "@") === false) { $n = $e; } else { $n = trim($f . " " . $l); } // generalize email $estar = $e && strpos($e, "*") !== false; if ($e && !$estar) { if (preg_match('/\\A(.*)@(.*?)((?:[.](?:com|net|edu|org|us|uk|fr|be|jp|cn))?)\\z/', $e, $m)) { $e = ($m[1] === "" ? "*" : $m[1]) . "@*" . $m[2] . ($m[3] ?: "*"); } else { $e = "*{$e}*"; } } // contact database if not restricted to PC or cset $result = null; if ($this->cset) { $cs = $this->cset; } else { if ($this->type & self::F_PC) { $cs = pcMembers(); } else { $q = array(); if ($n !== "") { $x = sqlq_for_like(UnicodeHelper::deaccent($n)); $q[] = "unaccentedName like '%" . preg_replace('/[\\s*]+/', "%", $x) . "%'"; } if ($e !== "") { $x = sqlq_for_like($e); $q[] = "email like '" . preg_replace('/[\\s*]+/', "%", $x) . "'"; } $result = Dbl::qe_raw("select firstName, lastName, unaccentedName, email, contactId, roles from ContactInfo where " . join(" or ", $q)); $cs = array(); while ($result && ($row = Contact::fetch($result))) { $cs[$row->contactId] = $row; } } } // filter results $nreg = $ereg = null; if ($n !== "") { $nreg = PaperSearch::analyze_field_preg($n); } if ($e !== "" && $estar) { $ereg = '{\\A' . str_replace('\\*', '.*', preg_quote($e)) . '\\z}i'; } else { if ($e !== "") { $ereg = str_replace('@\\*', '@(?:|.*[.])', preg_quote($e)); $ereg = preg_replace('/\\A\\\\\\*/', '(?:.*[@.]|)', $ereg); $ereg = '{\\A' . preg_replace('/\\\\\\*$/', '(?:[@.].*|)', $ereg) . '\\z}i'; } } $ids = array(); foreach ($cs as $id => $acct) { if ($ereg && preg_match($ereg, $acct->email)) { // exact email match trumps all else if (strcasecmp($e, $acct->email) == 0) { $ids = array($id); break; } $ids[] = $id; } else { if ($nreg) { $n = $acct->firstName === "" || $acct->lastName === "" ? "" : " "; $n = $acct->firstName . $n . $acct->lastName; if (PaperSearch::match_field_preg($nreg, $n, $acct->unaccentedName)) { $ids[] = $id; } } } } Dbl::free($result); return $ids; }
function ldapLoginAction() { global $Conf, $Opt; if (!preg_match('/\\A\\s*(\\S+)\\s+(\\d+\\s+)?([^*]+)\\*(.*?)\\s*\\z/s', $Opt["ldapLogin"], $m)) { return Conf::msg_error("Internal error: <code>\$Opt[\"ldapLogin\"]</code> syntax error; expected “<code><i>LDAP-URL</i> <i>distinguished-name</i></code>”, where <code><i>distinguished-name</i></code> contains a <code>*</code> character to be replaced by the user's email address. Logins will fail until this error is fixed."); } // connect to the LDAP server if ($m[2] == "") { $ldapc = @ldap_connect($m[1]); } else { $ldapc = @ldap_connect($m[1], (int) $m[2]); } if (!$ldapc) { return Conf::msg_error("Internal error: ldap_connect. Logins disabled until this error is fixed."); } @ldap_set_option($ldapc, LDAP_OPT_PROTOCOL_VERSION, 3); $qemail = addcslashes(req_s("email"), ',=+<>#;\\"'); $dn = $m[3] . $qemail . $m[4]; $success = @ldap_bind($ldapc, $dn, req_s("password")); if (!$success && @ldap_errno($ldapc) == 2) { @ldap_set_option($ldapc, LDAP_OPT_PROTOCOL_VERSION, 2); $success = @ldap_bind($ldapc, $dn, req_s("password")); } if (!$success) { return ldapLoginBindFailure($ldapc); } // use LDAP information to prepopulate the database with names // add the additional filter key if set if (isset($Opt["ldap_addlFilterKey"])) { $sr = @ldap_search($ldapc, $dn, "(cn=*)", array("sn", "givenname", "cn", "mail", "telephonenumber", $Opt["ldap_addlFilterKey"])); } else { $sr = @ldap_search($ldapc, $dn, "(cn=*)", array("sn", "givenname", "cn", "mail", "telephonenumber")); } if ($sr) { $e = @ldap_get_entries($ldapc, $sr); $e = $e["count"] == 1 ? $e[0] : array(); if (isset($e["cn"]) && $e["cn"]["count"] == 1) { list($_REQUEST["firstName"], $_REQUEST["lastName"]) = Text::split_name($e["cn"][0]); } if (isset($e["sn"]) && $e["sn"]["count"] == 1) { $_REQUEST["lastName"] = $e["sn"][0]; } if (isset($e["givenname"]) && $e["givenname"]["count"] == 1) { $_REQUEST["firstName"] = $e["givenname"][0]; } if (isset($e["mail"]) && $e["mail"]["count"] == 1) { $_REQUEST["preferredEmail"] = $e["mail"][0]; } if (isset($e["telephonenumber"]) && $e["telephonenumber"]["count"] == 1) { $_REQUEST["voicePhoneNumber"] = $e["telephonenumber"][0]; } } // additional filter key set? if (isset($Opt["ldap_addlFilterKey"])) { // only pass, if key exists in LDAP query, has one value, and the value matches //if (!(isset($e[$Opt["ldap_addlFilterKey"]]))) { // return $Conf->errorMsg(" Filter key : '".$Opt["ldap_addlFilterKey"]."' not found in ldap search. " . var_dump(array_keys($e))); //} //if (!($e[$Opt["ldap_addlFilterKey"]]["count"] == 1)) { // return $Conf->errorMsg("Found wrong number of entries for key: " . $e[$Opt["ldap_addlFilterKey"]]["count"]); //} if (!(isset($e[$Opt["ldap_addlFilterKey"]]) && $e[$Opt["ldap_addlFilterKey"]]["count"] == 1 && $e[$Opt["ldap_addlFilterKey"]][0] == $Opt["ldap_addlFilterValue"])) { return $Conf->errorMsg($Opt["ldap_addlFilterErrMsg"]); } } // set default affiliation if (isset($Opt["ldap_def_affiliation"])) { $_REQUEST["affiliation"] = $Opt["ldap_def_affiliation"]; } // stick in no collaborators by default (avoids setting popping up all the time) if (isset($Opt["ldap_def_collab"])) { $_REQUEST["collaborators"] = $Opt["ldap_def_collab"]; } ldap_close($ldapc); return true; }