1<?php 2// init.php -- HotCRP initialization (test or site) 3// Copyright (c) 2006-2018 Eddie Kohler; see LICENSE. 4 5define("HOTCRP_VERSION", "2.102"); 6 7// All review types must be 1 digit 8define("REVIEW_META", 5); 9define("REVIEW_PRIMARY", 4); 10define("REVIEW_SECONDARY", 3); 11define("REVIEW_PC", 2); 12define("REVIEW_EXTERNAL", 1); 13 14define("CONFLICT_NONE", 0); 15define("CONFLICT_PCMARK", 1); /* unused */ 16define("CONFLICT_AUTHORMARK", 2); 17define("CONFLICT_MAXAUTHORMARK", 7); 18define("CONFLICT_CHAIRMARK", 8); 19define("CONFLICT_AUTHOR", 9); 20define("CONFLICT_CONTACTAUTHOR", 10); 21 22define("REV_RATINGS_PC", 0); 23define("REV_RATINGS_PC_EXTERNAL", 1); 24define("REV_RATINGS_NONE", 2); 25 26define("DTYPE_SUBMISSION", 0); 27define("DTYPE_FINAL", -1); 28define("DTYPE_COMMENT", -2); 29 30define("VIEWSCORE_FALSE", -3); 31define("VIEWSCORE_ADMINONLY", -2); 32define("VIEWSCORE_REVIEWERONLY", -1); 33define("VIEWSCORE_PC", 0); 34define("VIEWSCORE_AUTHORDEC", 1); 35define("VIEWSCORE_AUTHOR", 2); 36define("VIEWSCORE_MAX", 3); 37 38define("COMMENTTYPE_DRAFT", 1); 39define("COMMENTTYPE_BLIND", 2); 40define("COMMENTTYPE_RESPONSE", 4); 41define("COMMENTTYPE_BYAUTHOR", 8); 42define("COMMENTTYPE_BYSHEPHERD", 16); 43define("COMMENTTYPE_ADMINONLY", 0x00000); 44define("COMMENTTYPE_PCONLY", 0x10000); 45define("COMMENTTYPE_REVIEWER", 0x20000); 46define("COMMENTTYPE_AUTHOR", 0x30000); 47define("COMMENTTYPE_VISIBILITY", 0xFFF0000); 48 49define("TAG_REGEX_NOTWIDDLE", '[a-zA-Z@*_:.][-a-zA-Z0-9!@*_:.\/]*'); 50define("TAG_REGEX", '~?~?' . TAG_REGEX_NOTWIDDLE); 51define("TAG_MAXLEN", 80); 52define("TAG_INDEXBOUND", 2147483646); 53 54define("CAPTYPE_RESETPASSWORD", 1); 55define("CAPTYPE_CHANGEEMAIL", 2); 56 57global $Now, $ConfSitePATH; 58$Now = time(); 59$ConfSitePATH = null; 60 61 62// set $ConfSitePATH (path to conference site) 63function set_path_variables() { 64 global $ConfSitePATH; 65 if (!isset($ConfSitePATH)) { 66 $ConfSitePATH = substr(__FILE__, 0, strrpos(__FILE__, "/")); 67 while ($ConfSitePATH !== "" && !file_exists("$ConfSitePATH/src/init.php")) 68 $ConfSitePATH = substr($ConfSitePATH, 0, strrpos($ConfSitePATH, "/")); 69 if ($ConfSitePATH === "") 70 $ConfSitePATH = "/var/www/html"; 71 } 72 require_once("$ConfSitePATH/lib/navigation.php"); 73} 74set_path_variables(); 75 76 77// Load code 78class SiteLoader { 79 static $map = [ 80 "AbbreviationClass" => "lib/abbreviationmatcher.php", 81 "AssignmentCountSet" => "src/assignmentset.php", 82 "AutoassignerCosts" => "src/autoassigner.php", 83 "BanalSettings" => "src/settings/s_subform.php", 84 "CapabilityManager" => "src/capability.php", 85 "ContactCountMatcher" => "src/papersearch.php", 86 "CsvGenerator" => "lib/csv.php", 87 "CsvParser" => "lib/csv.php", 88 "FormatChecker" => "src/formatspec.php", 89 "JsonSerializable" => "lib/json.php", 90 "LoginHelper" => "lib/login.php", 91 "MailPreparation" => "lib/mailer.php", 92 "MimeText" => "lib/mailer.php", 93 "NameInfo" => "lib/text.php", 94 "NumericOrderPaperColumn" => "src/papercolumn.php", 95 "Option_SearchTerm" => "src/search/st_option.php", 96 "PaperInfoSet" => "src/paperinfo.php", 97 "PaperOptionList" => "src/paperoption.php", 98 "Review_Assigner" => "src/assignmentset.php", 99 "ReviewField" => "src/review.php", 100 "ReviewFieldInfo" => "src/review.php", 101 "ReviewForm" => "src/review.php", 102 "ReviewSearchMatcher" => "src/search/st_review.php", 103 "ReviewValues" => "src/review.php", 104 "SearchSplitter" => "src/papersearch.php", 105 "SearchTerm" => "src/papersearch.php", 106 "TagAnno" => "lib/tagger.php", 107 "TagInfo" => "lib/tagger.php", 108 "TagMap" => "lib/tagger.php", 109 "TextPaperOption" => "src/paperoption.php", 110 "XlsxGenerator" => "lib/xlsx.php" 111 ]; 112 113 static $suffix_map = [ 114 "_api.php" => ["api_", "api"], 115 "_assignmentparser.php" => ["a_", "assigners"], 116 "_helptopic.php" => ["h_", "help"], 117 "_listaction.php" => ["la_", "listactions"], 118 "_papercolumn.php" => ["pc_", "papercolumns"], 119 "_papercolumnfactory.php" => ["pc_", "papercolumns"], 120 "_searchterm.php" => ["st_", "search"], 121 "_settingrenderer.php" => ["s_", "settings"], 122 "_settingparser.php" => ["s_", "settings"], 123 "_userinfo.php" => ["u_", "userinfo"] 124 ]; 125 126 static function read_main_options() { 127 global $ConfSitePATH, $Opt; 128 if (defined("HOTCRP_OPTIONS")) 129 $files = [HOTCRP_OPTIONS]; 130 else 131 $files = ["$ConfSitePATH/conf/options.php", "$ConfSitePATH/conf/options.inc", "$ConfSitePATH/Code/options.inc"]; 132 foreach ($files as $f) 133 if ((@include $f) !== false) { 134 $Opt["loaded"][] = $f; 135 break; 136 } 137 } 138} 139 140spl_autoload_register(function ($class_name) { 141 global $ConfSitePATH; 142 $f = null; 143 if (isset(SiteLoader::$map[$class_name])) 144 $f = SiteLoader::$map[$class_name]; 145 if (!$f) 146 $f = strtolower($class_name) . ".php"; 147 foreach (expand_includes($f, ["autoload" => true]) as $fx) 148 require_once($fx); 149}); 150 151require_once("$ConfSitePATH/lib/base.php"); 152require_once("$ConfSitePATH/lib/redirect.php"); 153require_once("$ConfSitePATH/lib/dbl.php"); 154require_once("$ConfSitePATH/src/helpers.php"); 155require_once("$ConfSitePATH/src/conference.php"); 156require_once("$ConfSitePATH/src/contact.php"); 157 158 159// Set locale to C (so that, e.g., strtolower() on UTF-8 data doesn't explode) 160setlocale(LC_COLLATE, "C"); 161setlocale(LC_CTYPE, "C"); 162 163// Don't want external entities parsed by default 164if (function_exists("libxml_disable_entity_loader")) 165 libxml_disable_entity_loader(true); 166 167 168// Set up conference options (also used in mailer.php) 169function expand_includes_once($file, $includepath, $globby) { 170 foreach ($file[0] === "/" ? [""] : $includepath as $idir) { 171 $try = $idir . $file; 172 if (!$globby && is_readable($try)) 173 return [$try]; 174 else if ($globby && ($m = glob($try, GLOB_BRACE))) 175 return $m; 176 } 177 return []; 178} 179 180function expand_includes($files, $expansions = array()) { 181 global $Opt, $ConfSitePATH; 182 if (!is_array($files)) 183 $files = array($files); 184 $confname = get($Opt, "confid") ? : get($Opt, "dbName"); 185 $expansions["confid"] = $expansions["confname"] = $confname; 186 $expansions["siteclass"] = get($Opt, "siteclass"); 187 188 if (isset($expansions["autoload"]) && strpos($files[0], "/") === false) 189 $includepath = [$ConfSitePATH . "/src/", $ConfSitePATH . "/lib/"]; 190 else 191 $includepath = [$ConfSitePATH . "/"]; 192 if (isset($Opt["includepath"]) && is_array($Opt["includepath"])) { 193 foreach ($Opt["includepath"] as $i) 194 if ($i) 195 $includepath[] = str_ends_with($i, "/") ? $i : $i . "/"; 196 } 197 198 $results = array(); 199 foreach ($files as $f) { 200 if (strpos((string) $f, '$') !== false) { 201 foreach ($expansions as $k => $v) 202 if ($v !== false && $v !== null) 203 $f = preg_replace(',\$\{' . $k . '\}|\$' . $k . '\b,', $v, $f); 204 else if (preg_match(',\$\{' . $k . '\}|\$' . $k . '\b,', $f)) { 205 $f = ""; 206 break; 207 } 208 } 209 if ((string) $f === "") 210 continue; 211 $matches = []; 212 $ignore_not_found = $globby = false; 213 if (str_starts_with($f, "?")) { 214 $ignore_not_found = true; 215 $f = substr($f, 1); 216 } 217 if (preg_match(',[\[\]\*\?\{\}],', $f)) 218 $ignore_not_found = $globby = true; 219 $matches = expand_includes_once($f, $includepath, $globby); 220 if (empty($matches) 221 && isset($expansions["autoload"]) 222 && ($underscore = strpos($f, "_")) 223 && ($f2 = get(SiteLoader::$suffix_map, substr($f, $underscore)))) { 224 $xincludepath = array_merge($f2[1] ? ["{$ConfSitePATH}/src/{$f2[1]}/"] : [], $includepath); 225 $matches = expand_includes_once($f2[0] . substr($f, 0, $underscore) . ".php", $xincludepath, $globby); 226 } 227 $results = array_merge($results, $matches); 228 if (empty($matches) && !$ignore_not_found) 229 $results[] = $f[0] === "/" ? $f : $includepath[0] . $f; 230 } 231 return $results; 232} 233 234function read_included_options(&$files) { 235 global $Opt; 236 if (is_string($files)) 237 $files = [$files]; 238 for ($i = 0; $i != count($files); ++$i) 239 foreach (expand_includes($files[$i]) as $f) { 240 $key = "missing"; 241 if ((@include $f) !== false) 242 $key = "loaded"; 243 $Opt[$key][] = $f; 244 } 245} 246 247function expand_json_includes_callback($includelist, $callback) { 248 $includes = []; 249 foreach (is_array($includelist) ? $includelist : [$includelist] as $k => $str) { 250 $expandable = null; 251 if (is_string($str)) { 252 if (str_starts_with($str, "@")) 253 $expandable = substr($str, 1); 254 else if (!preg_match('/\A[\s\[\{]/', $str) 255 || ($str[0] === "[" && !preg_match('/\]\s*\z/', $str))) 256 $expandable = $str; 257 } 258 if ($expandable) { 259 foreach (expand_includes($expandable) as $f) 260 if (($x = file_get_contents($f))) 261 $includes[] = [$x, $f]; 262 } else 263 $includes[] = [$str, "entry $k"]; 264 } 265 foreach ($includes as $xentry) { 266 list($entry, $landmark) = $xentry; 267 if (is_string($entry)) { 268 $x = json_decode($entry); 269 if ($x === null && json_last_error()) { 270 $x = Json::decode($entry); 271 if ($x === null) 272 error_log("$landmark: Invalid JSON: " . Json::last_error_msg()); 273 } 274 if ($x === null) 275 continue; 276 $entry = $x; 277 } 278 foreach (is_array($entry) ? $entry : [$entry] as $k => $v) { 279 if (is_object($v)) 280 $v->__subposition = ++Conf::$next_xt_subposition; 281 if (!call_user_func($callback, $v, $k, $landmark)) 282 error_log("$landmark: Invalid expansion " . json_encode($v) . "."); 283 } 284 } 285} 286 287global $Opt; 288if (!$Opt) 289 $Opt = array(); 290if (!get($Opt, "loaded")) { 291 SiteLoader::read_main_options(); 292 if (get($Opt, "multiconference")) 293 Multiconference::init(); 294 if (get($Opt, "include")) 295 read_included_options($Opt["include"]); 296} 297if (!get($Opt, "loaded") || get($Opt, "missing")) 298 Multiconference::fail_bad_options(); 299if (get($Opt, "dbLogQueries")) 300 Dbl::log_queries($Opt["dbLogQueries"], get($Opt, "dbLogQueryFile")); 301 302 303// Allow lots of memory 304if (!get($Opt, "memoryLimit") && ini_get_bytes("memory_limit") < (128 << 20)) 305 $Opt["memoryLimit"] = "128M"; 306if (get($Opt, "memoryLimit")) 307 ini_set("memory_limit", $Opt["memoryLimit"]); 308 309 310// Create the conference 311global $Conf; 312if (!$Conf) 313 $Conf = Conf::$g = new Conf($Opt, true); 314if (!$Conf->dblink) 315 Multiconference::fail_bad_database(); 316