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