function normalize($pj, $old_pj) { // Errors prevent saving global $Conf, $Now; // Title, abstract $this->normalize_string($pj, "title", true); $this->normalize_string($pj, "abstract", false); $this->normalize_string($pj, "collaborators", false); if (isset($pj->collaborators)) { $collab = []; foreach (preg_split('/[\\r\\n]+/', $pj->collaborators) as $line) { $collab[] = preg_replace('/[,;\\s]+\\z/', '', $line); } while (!empty($collab) && $collab[count($collab) - 1] === "") { array_pop($collab); } if (!empty($collab)) { $pj->collaborators = join("\n", $collab) . "\n"; } else { $pj->collaborators = ""; } } // Authors $au_by_email = array(); $pj->bad_authors = array(); if (isset($pj->authors)) { if (!is_array($pj->authors)) { $this->set_error_html("author", "Format error [authors]"); } // old author information $old_au_by_email = []; if ($old_pj && isset($old_pj->authors)) { foreach ($old_pj->authors as $au) { if (isset($au->email)) { $old_au_by_email[strtolower($au->email)] = $au; } } } // new author information $curau = is_array($pj->authors) ? $pj->authors : array(); $pj->authors = array(); foreach ($curau as $k => $au) { if (is_string($au) || is_object($au)) { $aux = Text::analyze_name($au); $aux->first = simplify_whitespace($aux->firstName); $aux->last = simplify_whitespace($aux->lastName); $aux->email = simplify_whitespace($aux->email); $aux->affiliation = simplify_whitespace($aux->affiliation); // borrow from old author information if ($aux->email && $aux->first === "" && $aux->last === "" && ($old_au = get($old_au_by_email, strtolower($aux->email)))) { $aux->first = get($old_au, "first", ""); $aux->last = get($old_au, "last", ""); if ($aux->affiliation === "") { $aux->affiliation = get($old_au, "affiliation", ""); } } if ($aux->first !== "" || $aux->last !== "" || $aux->email !== "" || $aux->affiliation !== "") { $pj->authors[] = $aux; } else { $pj->bad_authors[] = $aux; } $aux->index = count($pj->authors) + count($pj->bad_authors); if (is_object($au) && isset($au->contact)) { $aux->contact = !!$au->contact; } if (get($aux, "email")) { $au_by_email[strtolower($aux->email)] = $aux; } } else { $this->set_error_html("author", "Format error [authors]"); } } } // Status foreach (array("withdrawn_at", "submitted_at", "final_submitted_at") as $k) { if (isset($pj->{$k})) { if (is_numeric($pj->{$k})) { $pj->{$k} = (int) $pj->{$k}; } else { if (is_string($pj->{$k})) { $pj->{$k} = $Conf->parse_time($pj->{$k}, $Now); } else { $pj->{$k} = false; } } if ($pj->{$k} === false || $pj->{$k} < 0) { $pj->{$k} = $Now; } } } // Blindness if (isset($pj->nonblind)) { if (($x = friendly_boolean($pj->nonblind)) !== null) { $pj->nonblind = $x; } else { $this->set_error_html("nonblind", "Format error [nonblind]"); } } // Topics $pj->bad_topics = array(); if (get($pj, "topics") !== null) { $this->normalize_topics($pj); } // Options $pj->bad_options = array(); if (get($pj, "options") && is_object($pj->options)) { $this->normalize_options($pj); } else { if (get($pj, "options") === false) { $pj->options = (object) array(); } else { if (get($pj, "options") !== null) { $this->set_error_html("options", "Format error [options]"); } } } // PC conflicts $pj->bad_pc_conflicts = (object) array(); if (get($pj, "pc_conflicts") && (is_object($pj->pc_conflicts) || is_array($pj->pc_conflicts))) { $this->normalize_pc_conflicts($pj); } else { if (get($pj, "pc_conflicts") === false) { $pj->pc_conflicts = (object) array(); } else { if (get($pj, "pc_conflicts") !== null) { $this->set_error_html("pc_conflicts", "Format error [PC conflicts]"); } } } // Old contacts (to avoid validate_email errors on unchanged contacts) $old_contacts = array(); if ($old_pj && get($old_pj, "authors")) { foreach ($old_pj->authors as $au) { if (get($au, "contact")) { $old_contacts[strtolower($au->email)] = true; } } } if ($old_pj && get($old_pj, "contacts")) { foreach ($old_pj->contacts as $conf) { $old_contacts[strtolower($conf->email)] = true; } } // verify emails on authors marked as contacts $pj->bad_contacts = array(); foreach (get($pj, "authors") ?: array() as $au) { if (get($au, "contact") && (!get($au, "email") || !$this->valid_contact(strtolower($au->email), $old_contacts))) { $pj->bad_contacts[] = $au; } } // Contacts $contacts = get($pj, "contacts"); if ($contacts !== null) { if (is_object($contacts) || is_array($contacts)) { $contacts = (array) $contacts; } else { $this->set_error_html("contacts", "Format error [contacts]"); $contacts = array(); } $pj->contacts = array(); // verify emails on explicitly named contacts foreach ($contacts as $k => $v) { if (!$v) { continue; } if ($v === true) { $v = (object) array(); } else { if (is_string($v) && is_int($k)) { $v = trim($v); if ($this->valid_contact(strtolower($v), $old_contacts)) { $v = (object) array("email" => $v); } else { $v = Text::analyze_name($v); } } } if (is_object($v) && !get($v, "email") && is_string($k)) { $v->email = $k; } if (is_object($v) && get($v, "email")) { $lemail = strtolower($v->email); if ($this->valid_contact($lemail, $old_contacts)) { $pj->contacts[] = (object) array_merge((array) get($au_by_email, $lemail), (array) $v); } else { $pj->bad_contacts[] = $v; } } else { $this->set_error_html("contacts", "Format error [contacts]"); } } } // Inherit contactness if (isset($pj->authors) && $old_pj && isset($old_pj->authors)) { foreach ($old_pj->authors as $au) { if (get($au, "contact") && $au->email && ($aux = get($au_by_email, strtolower($au->email))) && !isset($aux->contact)) { $aux->contact = true; } } } if (isset($pj->authors) && $old_pj && isset($old_pj->contacts)) { foreach ($old_pj->contacts as $au) { if (($aux = get($au_by_email, strtolower($au->email))) && !isset($aux->contact)) { $aux->contact = true; } } } }
private function normalize($cj, $old_user) { // Errors prevent saving global $Conf, $Me, $Now; // Canonicalize keys foreach (array("preferredEmail" => "preferred_email", "institution" => "affiliation", "voicePhoneNumber" => "phone", "addressLine1" => "address", "zipCode" => "zip", "postal_code" => "zip") as $x => $y) { if (isset($cj->{$x}) && !isset($cj->{$y})) { $cj->{$y} = $cj->{$x}; } } // Stringiness foreach (array("firstName", "lastName", "email", "preferred_email", "affiliation", "phone", "old_password", "new_password", "city", "state", "zip", "country") as $k) { if (isset($cj->{$k}) && !is_string($cj->{$k})) { $this->set_error($k, "Format error [{$k}]"); unset($cj->{$k}); } } // Email if (!get($cj, "email") && $old_user) { $cj->email = $old_user->email; } else { if (!get($cj, "email")) { $this->set_error("email", "Email is required."); } else { if (!isset($this->errf["email"]) && !validate_email($cj->email) && (!$old_user || $old_user->email !== $cj->email)) { $this->set_error("email", "Invalid email address “" . htmlspecialchars($cj->email) . "”."); } } } // ID if (get($cj, "id") === "new") { if (get($cj, "email") && Contact::id_by_email($cj->email)) { $this->set_error("email", "Email address “" . htmlspecialchars($cj->email) . "” is already in use."); $this->errf["email_inuse"] = true; } } else { if (!get($cj, "id") && $old_user && $old_user->contactId) { $cj->id = $old_user->contactId; } if (get($cj, "id") && !is_int($cj->id)) { $this->set_error("id", "Format error [id]"); } if ($old_user && get($cj, "email") && strtolower($old_user->email) !== strtolower($cj->email) && Contact::id_by_email($cj->email)) { $this->set_error("email", "Email address “" . htmlspecialchars($cj->email) . "” is already in use. You may want to <a href=\"" . hoturl("mergeaccounts") . "\">merge these accounts</a>."); } } // Contactdb information if ($old_user && !$old_user->contactId) { if (!isset($cj->firstName) && !isset($cj->lastName)) { $cj->firstName = $old_user->firstName; $cj->lastName = $old_user->lastName; } if (!isset($cj->affiliation)) { $cj->affiliation = $old_user->affiliation; } if (!isset($cj->collaborators)) { $cj->collaborators = $old_user->collaborators; } } // Preferred email if (get($cj, "preferred_email") && !isset($this->errf["preferred_email"]) && !validate_email($cj->preferred_email) && (!$old_user || $old_user->preferredEmail !== $cj->preferred_email)) { $this->set_error("preferred_email", "Invalid email address “" . htmlspecialchars($cj->preferred_email) . "”"); } // Address $address = array(); if (is_array(get($cj, "address"))) { $address = $cj->address; } else { if (is_string(get($cj, "address"))) { $address[] = $cj->address; } else { if (get($cj, "address")) { $this->set_error("address", "Format error [address]"); } } if (is_string(get($cj, "address2"))) { $address[] = $cj->address2; } else { if (is_string(get($cj, "addressLine2"))) { $address[] = $cj->addressLine2; } else { if (get($cj, "address2") || get($cj, "addressLine2")) { $this->set_error("address2", "Format error [address2]"); } } } } foreach ($address as $a) { if (!is_string($a)) { $this->set_error("address", "Format error [address]"); } } if (count($address)) { $cj->address = $address; } // Collaborators if (is_array(get($cj, "collaborators"))) { foreach ($cj->collaborators as $c) { if (!is_string($c)) { $this->set_error("collaborators", "Format error [collaborators]"); } } } if (is_array(get($cj, "collaborators")) && !isset($this->errf["collaborators"])) { $cj->collaborators = join("\n", $cj->collaborators); } if (get($cj, "collaborators") && !is_string($cj->collaborators) && !isset($this->errf["collaborators"])) { $this->set_error("collaborators", "Format error [collaborators]"); } // Disabled if (isset($cj->disabled)) { if (($x = friendly_boolean($cj->disabled)) !== null) { $cj->disabled = $x; } else { $this->set_error("disabled", "Format error [disabled]"); } } // Follow if (isset($cj->follow)) { $cj->follow = $this->make_keyed_object($cj->follow, "follow"); $cj->bad_follow = array(); foreach ((array) $cj->follow as $k => $v) { if ($v && $k !== "reviews" && $k !== "allreviews" && $k !== "allfinal") { $cj->bad_follow[] = $k; } } } // Roles if (isset($cj->roles)) { $cj->roles = $this->make_keyed_object($cj->roles, "roles"); $cj->bad_roles = array(); foreach ((array) $cj->roles as $k => $v) { if ($v && $k !== "pc" && $k !== "chair" && $k !== "sysadmin" && $k !== "no") { $cj->bad_roles[] = $k; } } if ($this->no_deprivilege_self && $Me && $old_user && $old_user->contactId == $Me->contactId && Contact::parse_roles_json($cj->roles) < $Me->roles) { unset($cj->roles); $this->set_warning("roles", "Ignoring request to drop your privileges."); } } // Tags if (isset($cj->tags)) { $cj->tags = $this->make_tags_array($cj->tags, "tags"); } if (isset($cj->add_tags) || isset($cj->remove_tags)) { // collect old tags as map by base if (!isset($cj->tags) && $old_user) { $cj->tags = preg_split("/[\\s,]+/", $old_user->contactTags); } else { if (!isset($cj->tags)) { $cj->tags = array(); } } $old_tags = array(); foreach ($cj->tags as $t) { if ($t !== "") { list($tag, $index) = TagInfo::split_index($t); $old_tags[$tag] = $index; } } // process removals, then additions foreach ($this->make_tags_array(get($cj, "remove_tags"), "remove_tags") as $t) { list($tag, $index) = TagInfo::split_index($t); if ($index === false || get($old_tags, $tag) == $index) { unset($old_tags[$tag]); } } foreach ($this->make_tags_array($cj->add_tags, "add_tags") as $t) { list($tag, $index) = TagInfo::split_index($t); $old_tags[$tag] = $index; } // collect results $cj->tags = array(); foreach ($old_tags as $tag => $index) { $cj->tags[] = $tag . "#" . (double) $index; } } // Topics if (isset($cj->topics)) { $topics = $this->make_keyed_object($cj->topics, "topics"); $topic_map = $Conf->topic_map(); $cj->topics = (object) array(); $cj->bad_topics = array(); foreach ((array) $topics as $k => $v) { if (get($topic_map, $k)) { /* OK */ } else { if (($x = array_search($k, $topic_map, true)) !== false) { $k = $x; } else { $cj->bad_topics[] = $k; continue; } } if ($v === "mlow" || $v === "medium-low") { $v = -1; } else { if ($v === true || $v === "mhigh" || $v === "medium-high") { $v = 2; } else { if ($v === "low") { $v = -2; } else { if ($v === "high") { $v = 4; } else { if ($v === "medium" || $v === "none" || $v === false) { $v = 0; } else { if (is_numeric($v)) { $v = (int) $v; } else { $this->set_error("topics", "Topic interest format error"); continue; } } } } } } $k = (string) $k; $cj->topics->{$k} = $v; } } }