1<?php 2/* 3 This script provides functions to print out 4 error messages for users in case something is 5 not available. 6*/ 7 8// A 'good looking' 404 error message page 9function error_404(): void 10{ 11 global $MYSITE; 12 status_header(404); 13 site_header('404 Not Found', ["noindex"]); 14 echo "<h1>Not Found</h1>\n<p><strong>" . 15 htmlspecialchars(substr($MYSITE, 0, -1) . $_SERVER['REQUEST_URI']) . 16 "</strong> not found on this server.</p>\n"; 17 site_footer(); 18 exit; 19} 20 21// A 'good looking' 404 error message page for manual pages 22function error_404_manual(): void 23{ 24 global $MYSITE; 25 status_header(404); 26 site_header('404 Not Found', ["noindex"]); 27 echo "<h1>Not Found</h1>\n" . 28 "<p>The manual page you are looking for (<strong>" . 29 htmlspecialchars(substr($MYSITE, 0, -1) . $_SERVER['REQUEST_URI']) . 30 "</strong>) is not available on this server right now. " . 31 "Please check back later, or if the problem persists, " . 32 "<a href=\"/contact.php\">contact the webmasters</a>.</p>\n"; 33 site_footer(); 34 exit; 35} 36 37// An error message page for manual pages from inactive languages 38function error_inactive_manual_page($lang_name, $en_page): void 39{ 40 global $MYSITE, $ACTIVE_ONLINE_LANGUAGES; 41 status_header(404); 42 site_header('Page gone', ["noindex"]); 43 echo "<h1>Page gone</h1>\n" . 44 "<p>The " . htmlspecialchars($lang_name) . " manual page you are looking for (<strong>" . 45 htmlspecialchars(substr($MYSITE, 0, -1) . $_SERVER['REQUEST_URI']) . 46 "</strong>) is no longer available.</p>\n"; 47 $en_url = htmlspecialchars(substr($MYSITE, 0, -1) . $en_page); 48 echo "<p>The English page is available at <a href=\"{$en_url}\">{$en_url}</a></p>\n"; 49 echo "<p>Several other languages are also available:</p>\n"; 50 echo "<ul>\n"; 51 foreach ($ACTIVE_ONLINE_LANGUAGES as $alt_lang => $alt_lang_name) { 52 if ($alt_lang === "en") { 53 continue; 54 } 55 $alt_url = htmlspecialchars(substr($MYSITE, 0, -1) . str_replace("/en/", "/{$alt_lang}/", $en_page)); 56 echo "<li><a href=\"{$alt_url}\">" . htmlspecialchars($alt_lang_name) . "</a></li>\n"; 57 } 58 echo "</ul>\n"; 59 site_footer(); 60 exit; 61} 62 63// This service is not working right now 64function error_noservice(): void 65{ 66 global $MYSITE; 67 site_header('Service not working', ["noindex"]); 68 echo "<h1>Service not working</h1>\n" . 69 "<p>The service you tried to access with <strong>" . 70 htmlspecialchars(substr($MYSITE, 0, -1) . $_SERVER['REQUEST_URI']) . 71 "</strong> is not available on this server right now. " . 72 "Please check back later, or if the problem persists, " . 73 "<a href=\"/contact.php\">contact the webmasters</a>.</p>\n"; 74 site_footer(); 75 exit; 76} 77 78// There is no such mirror 79function error_nomirror($mirror): void { 80 site_header("No such mirror", ["noindex"]); 81 echo "<h1>No such mirror</h1>\n<p>The mirror you tried to access (" . 82 htmlspecialchars($mirror) . 83 ") is not registered php.net mirror. Please check back later," . 84 " or if the problem persists, " . 85 "<a href=\"/contact.php\">contact the webmasters</a>.</p>\n"; 86 site_footer(); 87 exit; 88} 89 90// Send out a proper status header 91function status_header(int $status): bool 92{ 93 $text = [ 94 200 => 'OK', 95 301 => 'Moved Permanently', 96 302 => 'Found', 97 404 => 'Not Found', 98 ]; 99 if (!isset($text[$status])) { 100 return false; 101 } 102 103 // Only respond with HTTP/1.0 for a 1.0 request specifically. 104 // Respond with 1.1 for anything else. 105 $proto = strcasecmp($_SERVER['SERVER_PROTOCOL'], 'HTTP/1.0') ? '1.1' : '1.0'; 106 107 @header("HTTP/$proto $status {$text[$status]}"); 108 @header("Status: $status {$text[$status]}", true, $status); 109 110 return true; 111} 112 113/****************************************************************************** 114In the future every mirror will have SQLite instead of hacks like this. Or, some 115other means like a ginormous array! But the point is we'll end up storing 116everything like functions, variables, constants, common search terms, etc. 117 118This exists today because as of PHP 5.3.0 there are over 200 links within the 119php.ini files so these create nicer urls and allow language detection to work. 120 121The most commonly searched terms have also been added. 122 123TODO: Determine if we want to continue 301 -OR- make these official URLs. 124******************************************************************************/ 125 126function is_known_ini(string $ini): ?string { 127 $inis = [ 128 'engine' => 'apache.configuration.php#ini.engine', 129 'short-open-tag' => 'ini.core.php#ini.short-open-tag', 130 'asp-tags' => 'ini.core.php#ini.asp-tags', 131 'precision' => 'ini.core.php#ini.precision', 132 'y2k-compliance' => 'ini.core.php#ini.y2k-compliance', 133 'output-buffering' => 'outcontrol.configuration.php#ini.output-buffering', 134 'output-handler' => 'outcontrol.configuration.php#ini.output-handler', 135 'zlib.output-compression' => 'zlib.configuration.php#ini.zlib.output-compression', 136 'zlib.output-compression-level' => 'zlib.configuration.php#ini.zlib.output-compression-level', 137 'zlib.output-handler' => 'zlib.configuration.php#ini.zlib.output-handler', 138 'implicit-flush' => 'outcontrol.configuration.php#ini.implicit-flush', 139 'allow-call-time-pass-reference' => 'ini.core.php#ini.allow-call-time-pass-reference', 140 'open-basedir' => 'ini.core.php#ini.open-basedir', 141 'disable-functions' => 'ini.core.php#ini.disable-functions', 142 'disable-classes' => 'ini.core.php#ini.disable-classes', 143 'zend.assertions' => 'ini.core.php#ini.zend.assertions', 144 'syntax-highlighting' => 'misc.configuration.php#ini.syntax-highlighting', 145 'ignore-user-abort' => 'misc.configuration.php#ini.ignore-user-abort', 146 'realpath-cache-size' => 'ini.core.php#ini.realpath-cache-size', 147 'realpath-cache-ttl' => 'ini.core.php#ini.realpath-cache-ttl', 148 'expose-php' => 'ini.core.php#ini.expose-php', 149 'max-execution-time' => 'info.configuration.php#ini.max-execution-time', 150 'max-input-time' => 'info.configuration.php#ini.max-input-time', 151 'max-input-vars' => 'info.configuration.php#ini.max-input-vars', 152 'max-input-nesting-level' => 'info.configuration.php#ini.max-input-nesting-level', 153 'memory-limit' => 'ini.core.php#ini.memory-limit', 154 'error-reporting' => 'errorfunc.configuration.php#ini.error-reporting', 155 'display-errors' => 'errorfunc.configuration.php#ini.display-errors', 156 'display-startup-errors' => 'errorfunc.configuration.php#ini.display-startup-errors', 157 'log-errors' => 'errorfunc.configuration.php#ini.log-errors', 158 'log-errors-max-len' => 'errorfunc.configuration.php#ini.log-errors-max-len', 159 'ignore-repeated-errors' => 'errorfunc.configuration.php#ini.ignore-repeated-errors', 160 'ignore-repeated-source' => 'errorfunc.configuration.php#ini.ignore-repeated-source', 161 'report-memleaks' => 'errorfunc.configuration.php#ini.report-memleaks', 162 'track-errors' => 'errorfunc.configuration.php#ini.track-errors', 163 'xmlrpc-errors' => 'errorfunc.configuration.php#ini.xmlrpc-errors', 164 'html-errors' => 'errorfunc.configuration.php#ini.html-errors', 165 'docref-root' => 'errorfunc.configuration.php#ini.docref-root', 166 'docref-ext' => 'errorfunc.configuration.php#ini.docref-ext', 167 'error-prepend-string' => 'errorfunc.configuration.php#ini.error-prepend-string', 168 'error-append-string' => 'errorfunc.configuration.php#ini.error-append-string', 169 'error-log' => 'errorfunc.configuration.php#ini.error-log', 170 'syslog.facility' => 'errorfunc.configuration.php#ini.syslog.facility', 171 'syslog.filter' => 'errorfunc.configuration.php#ini.syslog.filter', 172 'syslog.ident' => 'errorfunc.configuration.php#ini.syslog.ident', 173 'arg-separator.output' => 'ini.core.php#ini.arg-separator.output', 174 'arg-separator.input' => 'ini.core.php#ini.arg-separator.input', 175 'variables-order' => 'ini.core.php#ini.variables-order', 176 'request-order' => 'ini.core.php#ini.request-order', 177 'register-globals' => 'ini.core.php#ini.register-globals', 178 'register-long-arrays' => 'ini.core.php#ini.register-long-arrays', 179 'register-argc-argv' => 'ini.core.php#ini.register-argc-argv', 180 'auto-globals-jit' => 'ini.core.php#ini.auto-globals-jit', 181 'post-max-size' => 'ini.core.php#ini.post-max-size', 182 'magic-quotes-gpc' => 'info.configuration.php#ini.magic-quotes-gpc', 183 'magic-quotes-runtime' => 'info.configuration.php#ini.magic-quotes-runtime', 184 'auto-prepend-file' => 'ini.core.php#ini.auto-prepend-file', 185 'auto-append-file' => 'ini.core.php#ini.auto-append-file', 186 'default-mimetype' => 'ini.core.php#ini.default-mimetype', 187 'default-charset' => 'ini.core.php#ini.default-charset', 188 'always-populate-raw-post-data' => 'ini.core.php#ini.always-populate-raw-post-data', 189 'include-path' => 'ini.core.php#ini.include-path', 190 'doc-root' => 'ini.core.php#ini.doc-root', 191 'user-dir' => 'ini.core.php#ini.user-dir', 192 'extension-dir' => 'ini.core.php#ini.extension-dir', 193 'enable-dl' => 'info.configuration.php#ini.enable-dl', 194 'cgi.force-redirect' => 'ini.core.php#ini.cgi.force-redirect', 195 'cgi.redirect-status-env' => 'ini.core.php#ini.cgi.redirect-status-env', 196 'cgi.fix-pathinfo' => 'ini.core.php#ini.cgi.fix-pathinfo', 197 'fastcgi.impersonate' => 'ini.core.php#ini.fastcgi.impersonate', 198 'cgi.rfc2616-headers' => 'ini.core.php#ini.cgi.rfc2616-headers', 199 'file-uploads' => 'ini.core.php#ini.file-uploads', 200 'upload-tmp-dir' => 'ini.core.php#ini.upload-tmp-dir', 201 'upload-max-filesize' => 'ini.core.php#ini.upload-max-filesize', 202 'allow-url-fopen' => 'filesystem.configuration.php#ini.allow-url-fopen', 203 'allow-url-include' => 'filesystem.configuration.php#ini.allow-url-include', 204 'from' => 'filesystem.configuration.php#ini.from', 205 'user-agent' => 'filesystem.configuration.php#ini.user-agent', 206 'default-socket-timeout' => 'filesystem.configuration.php#ini.default-socket-timeout', 207 'auto-detect-line-endings' => 'filesystem.configuration.php#ini.auto-detect-line-endings', 208 'date.timezone' => 'datetime.configuration.php#ini.date.timezone', 209 'date.default-latitude' => 'datetime.configuration.php#ini.date.default-latitude', 210 'date.default-longitude' => 'datetime.configuration.php#ini.date.default-longitude', 211 'date.sunrise-zenith' => 'datetime.configuration.php#ini.date.sunrise-zenith', 212 'date.sunset-zenith' => 'datetime.configuration.php#ini.date.sunset-zenith', 213 'filter.default' => 'filter.configuration.php#ini.filter.default', 214 'filter.default-flags' => 'filter.configuration.php#ini.filter.default-flags', 215 'pcre.backtrack-limit' => 'pcre.configuration.php#ini.pcre.backtrack-limit', 216 'pcre.recursion-limit' => 'pcre.configuration.php#ini.pcre.recursion-limit', 217 'pdo-odbc.connection-pooling' => 'ref.pdo-odbc.php#ini.pdo-odbc.connection-pooling', 218 'phar.readonly' => 'phar.configuration.php#ini.phar.readonly', 219 'phar.require-hash' => 'phar.configuration.php#ini.phar.require-hash', 220 'define-syslog-variables' => 'network.configuration.php#ini.define-syslog-variables', 221 'smtp' => 'mail.configuration.php#ini.smtp', 222 'smtp-port' => 'mail.configuration.php#ini.smtp-port', 223 'sendmail-from' => 'mail.configuration.php#ini.sendmail-from', 224 'sendmail-path' => 'mail.configuration.php#ini.sendmail-path', 225 'sql.safe-mode' => 'ini.core.php#ini.sql.safe-mode', 226 'odbc.default-db' => 'odbc.configuration.php#ini.uodbc.default-db', 227 'odbc.default-user' => 'odbc.configuration.php#ini.uodbc.default-user', 228 'odbc.default-pw' => 'odbc.configuration.php#ini.uodbc.default-pw', 229 'odbc.allow-persistent' => 'odbc.configuration.php#ini.uodbc.allow-persistent', 230 'odbc.check-persistent' => 'odbc.configuration.php#ini.uodbc.check-persistent', 231 'odbc.max-persistent' => 'odbc.configuration.php#ini.uodbc.max-persistent', 232 'odbc.max-links' => 'odbc.configuration.php#ini.uodbc.max-links', 233 'odbc.defaultlrl' => 'odbc.configuration.php#ini.uodbc.defaultlrl', 234 'odbc.defaultbinmode' => 'odbc.configuration.php#ini.uodbc.defaultbinmode', 235 'mysql.allow-local-infile' => 'mysql.configuration.php#ini.mysql.allow-local-infile', 236 'mysql.allow-persistent' => 'mysql.configuration.php#ini.mysql.allow-persistent', 237 'mysql.max-persistent' => 'mysql.configuration.php#ini.mysql.max-persistent', 238 'mysql.max-links' => 'mysql.configuration.php#ini.mysql.max-links', 239 'mysql.default-port' => 'mysql.configuration.php#ini.mysql.default-port', 240 'mysql.default-socket' => 'mysql.configuration.php#ini.mysql.default-socket', 241 'mysql.default-host' => 'mysql.configuration.php#ini.mysql.default-host', 242 'mysql.default-user' => 'mysql.configuration.php#ini.mysql.default-user', 243 'mysql.default-password' => 'mysql.configuration.php#ini.mysql.default-password', 244 'mysql.connect-timeout' => 'mysql.configuration.php#ini.mysql.connect-timeout', 245 'mysql.trace-mode' => 'mysql.configuration.php#ini.mysql.trace-mode', 246 'mysqli.allow-local-infile' => 'mysqli.configuration.php#ini.mysqli.allow-local-infile', 247 'mysqli.max-links' => 'mysqli.configuration.php#ini.mysqli.max-links', 248 'mysqli.allow-persistent' => 'mysqli.configuration.php#ini.mysqli.allow-persistent', 249 'mysqli.default-port' => 'mysqli.configuration.php#ini.mysqli.default-port', 250 'mysqli.default-socket' => 'mysqli.configuration.php#ini.mysqli.default-socket', 251 'mysqli.default-host' => 'mysqli.configuration.php#ini.mysqli.default-host', 252 'mysqli.default-user' => 'mysqli.configuration.php#ini.mysqli.default-user', 253 'mysqli.default-pw' => 'mysqli.configuration.php#ini.mysqli.default-pw', 254 'oci8.privileged-connect' => 'oci8.configuration.php#ini.oci8.privileged-connect', 255 'oci8.max-persistent' => 'oci8.configuration.php#ini.oci8.max-persistent', 256 'oci8.persistent-timeout' => 'oci8.configuration.php#ini.oci8.persistent-timeout', 257 'oci8.ping-interval' => 'oci8.configuration.php#ini.oci8.ping-interval', 258 'oci8.statement-cache-size' => 'oci8.configuration.php#ini.oci8.statement-cache-size', 259 'oci8.default-prefetch' => 'oci8.configuration.php#ini.oci8.default-prefetch', 260 'oci8.old-oci-close-semantics' => 'oci8.configuration.php#ini.oci8.old-oci-close-semantics', 261 'opcache.preload' => 'opcache.configuration.php#ini.opcache.preload', 262 'pgsql.allow-persistent' => 'pgsql.configuration.php#ini.pgsql.allow-persistent', 263 'pgsql.auto-reset-persistent' => 'pgsql.configuration.php#ini.pgsql.auto-reset-persistent', 264 'pgsql.max-persistent' => 'pgsql.configuration.php#ini.pgsql.max-persistent', 265 'pgsql.max-links' => 'pgsql.configuration.php#ini.pgsql.max-links', 266 'pgsql.ignore-notice' => 'pgsql.configuration.php#ini.pgsql.ignore-notice', 267 'pgsql.log-notice' => 'pgsql.configuration.php#ini.pgsql.log-notice', 268 'sqlite3.extension-dir' => 'sqlite3.configuration.php#ini.sqlite3.extension-dir', 269 'bcmath.scale' => 'bc.configuration.php#ini.bcmath.scale', 270 'browscap' => 'misc.configuration.php#ini.browscap', 271 'session.save-handler' => 'session.configuration.php#ini.session.save-handler', 272 'session.save-path' => 'session.configuration.php#ini.session.save-path', 273 'session.use-cookies' => 'session.configuration.php#ini.session.use-cookies', 274 'session.cookie-secure' => 'session.configuration.php#ini.session.cookie-secure', 275 'session.use-only-cookies' => 'session.configuration.php#ini.session.use-only-cookies', 276 'session.name' => 'session.configuration.php#ini.session.name', 277 'session.auto-start' => 'session.configuration.php#ini.session.auto-start', 278 'session.cookie-lifetime' => 'session.configuration.php#ini.session.cookie-lifetime', 279 'session.cookie-path' => 'session.configuration.php#ini.session.cookie-path', 280 'session.cookie-domain' => 'session.configuration.php#ini.session.cookie-domain', 281 'session.cookie-httponly' => 'session.configuration.php#ini.session.cookie-httponly', 282 'session.serialize-handler' => 'session.configuration.php#ini.session.serialize-handler', 283 'session.gc-probability' => 'session.configuration.php#ini.session.gc-probability', 284 'session.gc-divisor' => 'session.configuration.php#ini.session.gc-divisor', 285 'session.gc-maxlifetime' => 'session.configuration.php#ini.session.gc-maxlifetime', 286 'session.bug-compat-42' => 'session.configuration.php#ini.session.bug-compat-42', 287 'session.bug-compat-warn' => 'session.configuration.php#ini.session.bug-compat-warn', 288 'session.referer-check' => 'session.configuration.php#ini.session.referer-check', 289 'session.entropy-length' => 'session.configuration.php#ini.session.entropy-length', 290 'session.entropy-file' => 'session.configuration.php#ini.session.entropy-file', 291 'session.cache-limiter' => 'session.configuration.php#ini.session.cache-limiter', 292 'session.cache-expire' => 'session.configuration.php#ini.session.cache-expire', 293 'session.sid-length' => 'session.configuration.php#ini.session.sid-length', 294 'session.use-trans-sid' => 'session.configuration.php#ini.session.use-trans-sid', 295 'session.hash-function' => 'session.configuration.php#ini.session.hash-function', 296 'session.hash-bits-per-character' => 'session.configuration.php#ini.session.hash-bits-per-character', 297 'session.upload-progress.enabled' => 'session.configuration.php#ini.session.upload-progress.enabled', 298 'session.upload-progress.cleanup' => 'session.configuration.php#ini.session.upload-progress.cleanup', 299 'session.upload-progress.prefix' => 'session.configuration.php#ini.session.upload-progress.prefix', 300 'session.upload-progress.name' => 'session.configuration.php#ini.session.upload-progress.name', 301 'session.upload-progress.freq' => 'session.configuration.php#ini.session.upload-progress.freq', 302 'session.upload-progress.min-freq' => 'session.configuration.php#ini.session.upload-progress.min-freq', 303 'url-rewriter.tags' => 'session.configuration.php#ini.url-rewriter.tags', 304 'assert.active' => 'info.configuration.php#ini.assert.active', 305 'assert.exception' => 'info.configuration.php#ini.assert.exception', 306 'assert.warning' => 'info.configuration.php#ini.assert.warning', 307 'assert.bail' => 'info.configuration.php#ini.assert.bail', 308 'assert.callback' => 'info.configuration.php#ini.assert.callback', 309 'assert.quiet-eval' => 'info.configuration.php#ini.assert.quiet-eval', 310 'zend.enable-gc' => 'info.configuration.php#ini.zend.enable-gc', 311 'com.typelib-file' => 'com.configuration.php#ini.com.typelib-file', 312 'com.allow-dcom' => 'com.configuration.php#ini.com.allow-dcom', 313 'com.autoregister-typelib' => 'com.configuration.php#ini.com.autoregister-typelib', 314 'com.autoregister-casesensitive' => 'com.configuration.php#ini.com.autoregister-casesensitive', 315 'com.autoregister-verbose' => 'com.configuration.php#ini.com.autoregister-verbose', 316 'mbstring.language' => 'mbstring.configuration.php#ini.mbstring.language', 317 'mbstring.internal-encoding' => 'mbstring.configuration.php#ini.mbstring.internal-encoding', 318 'mbstring.http-input' => 'mbstring.configuration.php#ini.mbstring.http-input', 319 'mbstring.http-output' => 'mbstring.configuration.php#ini.mbstring.http-output', 320 'mbstring.encoding-translation' => 'mbstring.configuration.php#ini.mbstring.encoding-translation', 321 'mbstring.detect-order' => 'mbstring.configuration.php#ini.mbstring.detect-order', 322 'mbstring.substitute-character' => 'mbstring.configuration.php#ini.mbstring.substitute-character', 323 'mbstring.func-overload' => 'mbstring.configuration.php#ini.mbstring.func-overload', 324 'gd.jpeg-ignore-warning' => 'image.configuration.php#ini.image.jpeg-ignore-warning', 325 'exif.encode-unicode' => 'exif.configuration.php#ini.exif.encode-unicode', 326 'exif.decode-unicode-motorola' => 'exif.configuration.php#ini.exif.decode-unicode-motorola', 327 'exif.decode-unicode-intel' => 'exif.configuration.php#ini.exif.decode-unicode-intel', 328 'exif.encode-jis' => 'exif.configuration.php#ini.exif.encode-jis', 329 'exif.decode-jis-motorola' => 'exif.configuration.php#ini.exif.decode-jis-motorola', 330 'exif.decode-jis-intel' => 'exif.configuration.php#ini.exif.decode-jis-intel', 331 'tidy.default-config' => 'tidy.configuration.php#ini.tidy.default-config', 332 'tidy.clean-output' => 'tidy.configuration.php#ini.tidy.clean-output', 333 'soap.wsdl-cache-enabled' => 'soap.configuration.php#ini.soap.wsdl-cache-enabled', 334 'soap.wsdl-cache-dir' => 'soap.configuration.php#ini.soap.wsdl-cache-dir', 335 'soap.wsdl-cache-ttl' => 'soap.configuration.php#ini.soap.wsdl-cache-ttl', 336 ]; 337 338 return $inis[$ini] ?? null; 339} 340 341function is_known_variable(string $variable): ?string { 342 $variables = [ 343 // Variables 344 'globals' => 'reserved.variables.globals.php', 345 '-server' => 'reserved.variables.server.php', 346 '-get' => 'reserved.variables.get.php', 347 '-post' => 'reserved.variables.post.php', 348 '-files' => 'reserved.variables.files.php', 349 '-request' => 'reserved.variables.request.php', 350 '-session' => 'reserved.variables.session.php', 351 '-cookie' => 'reserved.variables.cookies.php', 352 '-env' => 'reserved.variables.environment.php', 353 'this' => 'language.oop5.basic.php', 354 'php-errormsg' => 'reserved.variables.phperrormsg.php', 355 'argv' => 'reserved.variables.argv.php', 356 'argc' => 'reserved.variables.argc.php', 357 'http-response-header' => 'reserved.variables.httpresponseheader.php', 358 'http-server-vars' => 'reserved.variables.server.php', 359 'http-get-vars' => 'reserved.variables.get.php', 360 'http-post-vars' => 'reserved.variables.post.php', 361 'http-session-vars' => 'reserved.variables.session.php', 362 'http-post-files' => 'reserved.variables.files.php', 363 'http-cookie-vars' => 'reserved.variables.cookies.php', 364 ]; 365 366 return $variables[ltrim($variable, '$')] ?? null; 367} 368 369function is_known_term(string $term): ?string { 370 $terms = [ 371 '<>' => 'language.operators.comparison.php', 372 '<=>' => 'language.operators.comparison.php', 373 'spaceship' => 'language.operators.comparison.php', 374 '==' => 'language.operators.comparison.php', 375 '===' => 'language.operators.comparison.php', 376 '@' => 'language.operators.errorcontrol.php', 377 '__halt_compiler' => 'function.halt-compiler.php', 378 '__PHP_Incomplete_Class' => 'function.unserialize.php', 379 'and' => 'language.operators.logical.php', 380 'apache' => 'install.php', 381 'array' => 'language.types.array.php', 382 'arrays' => 'language.types.array.php', 383 'as' => 'control-structures.foreach.php', 384 'case' => 'control-structures.switch.php', 385 'catch' => 'language.exceptions.php', 386 'checkbox' => 'faq.html.php', 387 'class' => 'language.oop5.basic.php', 388 'classes' => 'language.oop5.basic.php', 389 'closures' => 'functions.anonymous.php', 390 'cookie' => 'features.cookies.php', 391 'date' => 'function.date.php', 392 'default' => 'control-structures.switch.php', 393 'do' => 'control-structures.do.while.php', 394 'enddeclare' => 'control-structures.declare.php', 395 'endfor' => 'control-structures.alternative-syntax.php', 396 'endforeach' => 'control-structures.alternative-syntax.php', 397 'endif' => 'control-structures.alternative-syntax.php', 398 'endswitch' => 'control-structures.alternative-syntax.php', 399 'endwhile' => 'control-structures.alternative-syntax.php', 400 'exception' => 'language.exceptions.php', 401 'extends' => 'language.oop5.basic.php#language.oop5.basic.extends', 402 'false' => 'language.types.boolean.php', 403 'file' => 'function.file.php', 404 'final' => 'language.oop5.final.php', 405 'finally' => 'language.exceptions.php', 406 'fopen' => 'function.fopen.php', 407 'for' => 'control-structures.for.php', 408 'foreach' => 'control-structures.foreach.php', 409 'form' => 'language.variables.external.php', 410 'forms' => 'language.variables.external.php', 411 'function' => 'language.functions.php', 412 'gd' => 'book.image.php', 413 'get' => 'reserved.variables.get.php', 414 'global' => 'language.variables.scope.php', 415 'globals' => 'language.variables.scope.php', 416 'header' => 'function.header.php', 417 'heredoc' => 'language.types.string.php#language.types.string.syntax.heredoc', 418 'htaccess' => 'configuration.file.php', 419 'if' => 'control-structures.if.php', 420 'implements' => 'language.oop5.interfaces.php', 421 'include' => 'function.include.php', 422 'insteadof' => 'language.oop5.traits.php#language.oop5.traits.conflict', 423 'int' => 'language.types.integer.php', 424 'ip' => 'reserved.variables.server.php', 425 'iterable' => 'language.types.iterable.php', 426 'juggling' => 'language.types.type-juggling.php', 427 'location' => 'function.header.php', 428 'mail' => 'function.mail.php', 429 'mixed' => 'language.types.mixed.php', 430 'modulo' => 'language.operators.arithmetic.php', 431 'mysql' => 'mysql.php', 432 'never' => 'language.types.never.php', 433 'new' => 'language.oop5.basic.php#language.oop5.basic.new', 434 'nowdoc' => 'language.types.string.php#language.types.string.syntax.nowdoc', 435 'null' => 'language.types.null.php', 436 'numeric' => 'reserved.other-reserved-words.php', 437 'object' => 'language.types.object.php', 438 'operator' => 'language.operators.php', 439 'operators' => 'language.operators.php', 440 'or' => 'language.operators.logical.php', 441 'parent' => 'reserved.classes.php#reserved.classes.special', 442 'php.ini' => 'configuration.file.php', 443 'php-mysql.dll' => 'book.mysql.php', 444 'php-self' => 'reserved.variables.server.php', 445 'query-string' => 'reserved.variables.server.php', 446 'readonly' => 'language.oop5.properties.php#language.oop5.properties.readonly-properties', 447 'redirect' => 'function.header.php', 448 'reference' => 'index.php', 449 'referer' => 'reserved.variables.server.php', 450 'referrer' => 'reserved.variables.server.php', 451 'remote-addr' => 'reserved.variables.server.php', 452 'request' => 'reserved.variables.request.php', 453 'self' => 'reserved.classes.php#reserved.classes.special', 454 'session' => 'features.sessions.php', 455 'smtp' => 'book.mail.php', 456 'ssl' => 'book.openssl.php', 457 'static' => 'language.oop5.static.php', 458 'stdin' => 'wrappers.php.php', 459 'string' => 'language.types.string.php', 460 'superglobal' => 'language.variables.superglobals.php', 461 'superglobals' => 'language.variables.superglobals.php', 462 'switch' => 'control-structures.switch.php', 463 'timestamp' => 'function.time.php', 464 'true' => 'language.types.boolean.php', 465 'try' => 'language.exceptions.php', 466 'upload' => 'features.file-upload.php', 467 'use' => 'language.namespaces.php', 468 'void' => 'language.types.void.php', 469 'xor' => 'language.operators.logical.php', 470 'yield from' => 'language.generators.syntax.php#control-structures.yield.from', 471 'yield' => 'language.generators.syntax.php#control-structures.yield', 472 473 '__COMPILER_HALT_OFFSET__' => 'function.halt-compiler.php', 474 'DEFAULT_INCLUDE_PATH' => 'reserved.constants.php', 475 'E_ALL' => 'errorfunc.constants.php', 476 'E_COMPILE_ERROR' => 'errorfunc.constants.php', 477 'E_COMPILE_WARNING' => 'errorfunc.constants.php', 478 'E_CORE_ERROR' => 'errorfunc.constants.php', 479 'E_CORE_WARNING' => 'errorfunc.constants.php', 480 'E_DEPRECATED' => 'errorfunc.constants.php', 481 'E_ERROR' => 'errorfunc.constants.php', 482 'E_NOTICE' => 'errorfunc.constants.php', 483 'E_PARSE' => 'errorfunc.constants.php', 484 'E_RECOVERABLE_ERROR' => 'errorfunc.constants.php', 485 'E_STRICT' => 'errorfunc.constants.php', 486 'E_USER_DEPRECATED' => 'errorfunc.constants.php', 487 'E_USER_ERROR' => 'errorfunc.constants.php', 488 'E_USER_NOTICE' => 'errorfunc.constants.php', 489 'E_USER_WARNING' => 'errorfunc.constants.php', 490 'E_WARNING' => 'errorfunc.constants.php', 491 'PEAR_EXTENSION_DIR' => 'reserved.constants.php', 492 'PEAR_INSTALL_DIR' => 'reserved.constants.php', 493 'PHP_BINARY' => 'reserved.constants.php', 494 'PHP_BINDIR' => 'reserved.constants.php', 495 'PHP_CONFIG_FILE_PATH' => 'reserved.constants.php', 496 'PHP_CONFIG_FILE_SCAN_DIR' => 'reserved.constants.php', 497 'PHP_DATADIR' => 'reserved.constants.php', 498 'PHP_DEBUG' => 'reserved.constants.php', 499 'PHP_EOL' => 'reserved.constants.php', 500 'PHP_EXTENSION_DIR' => 'reserved.constants.php', 501 'PHP_EXTRA_VERSION' => 'reserved.constants.php', 502 'PHP_FD_SETSIZE' => 'reserved.constants.php', 503 'PHP_FLOAT_DIG' => 'reserved.constants.php', 504 'PHP_FLOAT_EPSILON' => 'reserved.constants.php', 505 'PHP_FLOAT_MAX' => 'reserved.constants.php', 506 'PHP_FLOAT_MIN' => 'reserved.constants.php', 507 'PHP_INT_MAX' => 'reserved.constants.php', 508 'PHP_INT_MIN' => 'reserved.constants.php', 509 'PHP_INT_SIZE' => 'reserved.constants.php', 510 'PHP_LIBDIR' => 'reserved.constants.php', 511 'PHP_LOCALSTATEDIR' => 'reserved.constants.php', 512 'PHP_MAJOR_VERSION' => 'reserved.constants.php', 513 'PHP_MANDIR' => 'reserved.constants.php', 514 'PHP_MAXPATHLEN' => 'reserved.constants.php', 515 'PHP_MINOR_VERSION' => 'reserved.constants.php', 516 'PHP_OS_FAMILY' => 'reserved.constants.php', 517 'PHP_OS' => 'reserved.constants.php', 518 'PHP_PREFIX' => 'reserved.constants.php', 519 'PHP_RELEASE_VERSION' => 'reserved.constants.php', 520 'PHP_SAPI' => 'reserved.constants.php', 521 'PHP_SHLIB_SUFFIX' => 'reserved.constants.php', 522 'PHP_SYSCONFDIR' => 'reserved.constants.php', 523 'PHP_VERSION_ID' => 'reserved.constants.php', 524 'PHP_VERSION' => 'reserved.constants.php', 525 'PHP_WINDOWS_EVENT_CTRL_BREAK' => 'reserved.constants.php', 526 'PHP_WINDOWS_EVENT_CTRL_C' => 'reserved.constants.php', 527 'PHP_ZTS' => 'reserved.constants.php', 528 ]; 529 530 return $terms[$term] ?? null; 531} 532 533/* 534Search snippet provider: A dirty proof-of-concept: 535 This will probably live in sqlite one day, and be more intelligent (tagging?) 536 This is a 100% hack currently, and let's hope temporary does not become permanent (Hello year 2014!) 537 And this is English only today... we should add translation support via the manual, generated by PhD 538 539 This really is a proof-of-concept, where the choices below are the most popular searched terms at php.net 540 It should also take into account vague searches, such as 'global' and 'str'. The search works well enough for, 541 most terms, so something like $_SERVER isn't really needed but it's defined below anyways... 542*/ 543function is_known_snippet(string $term): ?string { 544 $snippets = [ 545 'global' => ' 546 The <b>global</b> keyword is used to manipulate <a href="/language.variables.scope">variable scope</a>, and 547 there is also the concept of <a href="/language.variables.superglobals">super globals</a> in PHP, 548 which are special variables with a global scope.', 549 'string' => ' 550 There is the <a href="/language.types.string">string type</a>, which is a scalar, 551 and also many <a href="/ref.strings">string functions.</a>', 552 'str' => ' 553 Many <a href="/ref.strings">string functions</a> begin with <b>str</b>, 554 and there is also the <a href="/language.types.string">string type</a>.', 555 '_server' => ' 556 <a href="/reserved.variables.server">$_SERVER</a> 557 is a <a href="/language.variables.superglobals">super global</a>, 558 and is home to many predefined variables that are typically provided by a web server', 559 'class' => ' 560 A <a href="/language.oop5">class</a> is an OOP (Object Oriented Programming) concept, 561 and PHP is both a procedural and OOP friendly language.', 562 'function' => ' 563 PHP contains thousands of functions. You might be interested in how a 564 <a href="/language.functions">function is defined</a>, or 565 <a href="/about.prototypes">how to read a function prototype</a>. 566 See also the list of <a href="/extensions">PHP extensions</a>', 567 ]; 568 569 $term = ltrim(strtolower(trim($term)), '$'); 570 return $snippets[$term] ?? null; 571} 572 573/** 574 * @param string $uri 575 * @return array<string, string> 576 */ 577function get_legacy_manual_urls(string $uri): array 578{ 579 $filename = $_SERVER["DOCUMENT_ROOT"] . "/manual/legacyurls.json"; 580 $pages_ids = json_decode(file_get_contents($filename), true); 581 $page_id = preg_replace_callback('/^manual\/.*\/(.*?)(\.php)?$/', function (array $matches): string { 582 if (count($matches) < 2) { 583 return ''; 584 } 585 return $matches[1]; 586 }, $uri); 587 588 if (!isset($pages_ids[$page_id])) { 589 return []; 590 } 591 592 $legacy_urls = []; 593 foreach ($pages_ids[$page_id] as $php_version) { 594 $legacy_urls[$php_version] = convert_manual_uri_to_legacy($uri, $php_version); 595 } 596 597 return $legacy_urls; 598} 599 600/** 601 * @param array<string, string> $legacy_urls URLs to legacy manuals, indexed by major PHP version 602 */ 603function fallback_to_legacy_manuals(array $legacy_urls): void 604{ 605 global $MYSITE; 606 status_header(404); 607 site_header('404 Not Found', ["noindex"]); 608 609 $original_url = htmlspecialchars(substr($MYSITE, 0, -1) . $_SERVER['REQUEST_URI']); 610 $legacy_links = ''; 611 foreach ($legacy_urls as $php_version => $url) { 612 $legacy_links .= '<li><a href="' . $url . '">PHP ' . $php_version . ' legacy manual</a></li>'; 613 } 614 615 echo <<<HTML 616<h1>Not Found</h1> 617<p>The manual page you are looking for (<strong>$original_url</strong>) is not available.</p> 618 619<p>However, this page exists in a legacy manual for the following PHP versions.</p> 620<ul id="legacy-links">$legacy_links</ul> 621<p>Please note that legacy manuals are maintained by Zend and not the PHP Documentation Group. Any questions about their content should be reported via the "Report a Bug" links on the appropriate pages.</p> 622 623<p>If you were looking for this page in the current PHP version and believe this to be a mistake, please check back later, or if the problem persists, <a href="/contact.php">contact the webmasters</a>.</p> 624HTML; 625 626 site_footer(); 627 exit; 628} 629 630function convert_manual_uri_to_legacy(string $uri, int $php_version): string 631{ 632 $parts = explode('/', $uri); 633 634 return sprintf('https://php-legacy-docs.zend.com/manual/php%s/%s/%s', $php_version, $parts[1], $parts[2]); 635} 636