1<?php 2$_SERVER['STATIC_ROOT'] = $MYSITE; 3$_SERVER['MYSITE'] = $MYSITE; 4 5// Use class names instead of colors 6ini_set('highlight.comment', 'comment'); 7ini_set('highlight.default', 'default'); 8ini_set('highlight.keyword', 'keyword'); 9ini_set('highlight.string', 'string'); 10ini_set('highlight.html', 'html'); 11 12// Highlight PHP code 13function highlight_php($code, $return = false) 14{ 15 $highlighted = highlight_string($code, true); 16 17 // Use this ugly hack for now to avoid code snippets with bad syntax screwing up the highlighter 18 if (strstr($highlighted, "include/layout.inc</b>")) { 19 $highlighted = '<span class="html">' . nl2br(htmlentities($code, ENT_HTML5), false) . "</span>"; 20 } 21 22 // Fix output to use CSS classes and wrap well 23 $highlighted = '<div class="phpcode">' . strtr( 24 $highlighted, 25 [ 26 ' ' => ' ', 27 "\n" => '', 28 29 '<span style="color: ' => '<span class="', 30 ], 31 ) . '</div>'; 32 33 if ($return) { return $highlighted; } 34 echo $highlighted; 35 return null; 36} 37 38// Same as highlight_php() but does not require '<?php' in $code 39function highlight_php_trimmed($code, $return = false) 40{ 41 $code = "<?php\n" . $code; 42 $highlighted_code = highlight_php($code, true); 43 $highlighted_code = preg_replace("!<\?php(<br />)+!", '', $highlighted_code, 1); 44 45 if ($return) { return $highlighted_code; } 46 echo $highlighted_code; 47 return null; 48} 49 50// Resize the image using the output of make_image() 51function resize_image($img, $width = 1, $height = 1) 52{ 53 // Drop width and height values from image if available 54 $str = preg_replace('!width=\"([0-9]+?)\"!i', '', $img); 55 $str = preg_replace('!height=\"([0-9]+?)\"!i', '', $str); 56 57 // Return image with new width and height added 58 return preg_replace( 59 '!/?>$!', 60 sprintf(' height="%s" width="%s">', $height, $width), 61 $str, 62 ); 63} 64 65// Return an <img> tag for a given image file available on the server 66function make_image($file, $alt = false, $align = false, $extras = false, 67 $dir = '/images', $addsize = false) 68{ 69 // If no / was provided at the start of $dir, add it 70 $webdir = $_SERVER['MYSITE'] . ($dir[0] == '/' ? '' : '/') . $dir; 71 72 // Get width and height values if possible 73 if ($addsize && ($size = @getimagesize($_SERVER['DOCUMENT_ROOT'] . "$dir/$file"))) { 74 $sizeparams = ' ' . trim($size[3]); 75 } else { 76 $sizeparams = ''; 77 } 78 79 // Convert right or left alignment to CSS float, 80 // but leave other alignments intact (for now) 81 if (in_array($align, ["right", "left"], true)) { 82 $align = ' style="float: ' . $align . ';"'; 83 } elseif ($align) { 84 $align = ' align="' . $align . '"'; 85 } else { 86 $align = ''; 87 } 88 89 // Return with image built up 90 return sprintf('<img src="%s/%s" alt="%s"%s%s%s>', 91 $webdir, 92 $file, 93 ($alt ?: ''), 94 $sizeparams, 95 $align, 96 ($extras ? ' ' . $extras : ''), 97 ); 98} 99 100// Print an <img> tag out for a given file 101function print_image($file, $alt = false, $align = false, $extras = false, 102 $dir = '/images'): void 103{ 104 echo make_image($file, $alt, $align, $extras, $dir); 105} 106 107// Shortcut to usual news image printing (right floating 108// image from the news dir with an alt and an URL) 109function news_image($URL, $image, $alt, $print = true) 110{ 111 $str = "<a href=\"$URL\">" . make_image("news/$image", $alt, "right") . "</a>"; 112 if ($print) { 113 echo $str; 114 } 115 return $str; 116} 117 118// Return HTML code for a submit button image 119function make_submit($file, $alt = false, $align = false, $extras = false, 120 $dir = '/images', $border = 0) 121{ 122 // Get an image without size info and convert the 123 // border attribute to use CSS, as border="" is not 124 // supported on <input> elements in [X]HTML 125 $img = make_image($file, $alt, $align, $extras, $dir, false); 126 $img = str_replace( 127 "border=\"$border\"", 128 "style=\"border: {$border}px;\"", 129 $img, 130 ); 131 132 // Return with ready input image 133 return '<input type="image"' . substr($img, 4); 134} 135 136// Return a hiperlink to something within the site 137function make_link(string $url, string $linktext = ''): string 138{ 139 return sprintf("<a href=\"%s\">%s</a>", $url, $linktext ?: $url); 140} 141 142// make_popup_link() 143// return a hyperlink to something, within the site, that pops up a new window 144// 145function make_popup_link($url, $linktext = false, $target = false, $windowprops = "", $extras = false) { 146 return sprintf("<a href=\"%s\" target=\"%s\" onclick=\"window.open('%s','%s','%s');return false;\"%s>%s</a>", 147 htmlspecialchars($url, ENT_QUOTES | ENT_IGNORE), 148 ($target ?: "_new"), 149 htmlspecialchars($url, ENT_QUOTES | ENT_IGNORE), 150 ($target ?: "_new"), 151 $windowprops, 152 ($extras ? ' ' . $extras : ''), 153 ($linktext ?: $url), 154 ); 155} 156 157// Print a link for a downloadable file (including filesize) 158function download_link($file, $title): void 159{ 160 $download_link = "/distributions/" . $file; 161 162 // Print out the download link 163 echo make_link($download_link, $title); 164 165 // We have a full path or a relative to the distributions dir 166 if ($tmp = strrchr($file, "/")) { 167 $local_file = substr($tmp, 1, strlen($tmp)); 168 } else { 169 $local_file = "distributions/$file"; 170 } 171 172 if (@file_exists($local_file . ".asc")) { 173 echo " "; 174 $sig_link = "/distributions/$file.asc"; 175 echo make_link($sig_link, "(sig)"); 176 } 177 178 // Try to get the size of the file 179 $size = @filesize($local_file); 180 181 // Print out size in bytes (if size is 182 // less then 1Kb, or else in Kb) 183 if ($size) { 184 echo ' ['; 185 if ($size < 1024) { 186 echo number_format($size) . 'b'; 187 } else { 188 echo number_format($size / 1024) . 'Kb'; 189 } 190 echo ']'; 191 } 192} 193 194function clean($var) { 195 return htmlspecialchars($var, ENT_QUOTES); 196} 197 198// Clean out the content of one user note for printing to HTML 199function clean_note($text) 200{ 201 // Highlight PHP source 202 $text = highlight_php(trim($text), true); 203 204 // Turn urls into links 205 return preg_replace( 206 '!((mailto:|(https?|ftp|nntp|news)://).*?)(\s|<|\)|"|\\\\|\'|$)!', 207 '<a href="\1" rel="nofollow" target="_blank">\1</a>\4', 208 $text, 209 ); 210} 211 212function display_errors($errors): void 213{ 214 echo '<div class="errors">'; 215 if (count($errors) > 1) { 216 echo "You need to do the following before your submission will be accepted:<ul>"; 217 foreach ($errors as $error) { 218 echo "<li>$error</li>\n"; 219 } 220 echo "</ul>"; 221 } 222 else { 223 echo $errors[0]; 224 } 225 echo '</div>'; 226} 227 228// Displays an event. Used in event submission 229// previews and event information displays 230function display_event($event, $include_date = 1): void 231{ 232 global $COUNTRIES; 233 // Current month (int)($_GET['cm'] ?: 0) 234 global $cm; 235 // Current year (int)($_GET['cy'] ?: 0) 236 global $cy; 237 238 // Weekday names array 239 for ($i = 1; $i <= 7; $i++) { 240 $days[$i] = date('l', mktime(12, 0, 0, 4, $i, 2012)); 241 } 242 243 // Recurring possibilities 244 $re = [ 245 1 => 'First', 246 2 => 'Second', 247 3 => 'Third', 248 4 => 'Fourth', 249 -1 => 'Last', 250 -2 => '2nd Last', 251 -3 => '3rd Last', 252 ]; 253 254 if (!isset($event['start']) && isset($event['sday'])) { 255 $sday = mktime(12,0,0,$event['smonth'],$event['sday'],$event['syear']); 256 } else { 257 $sday = (isset($event['start']) && !empty($event['start'])) ? strtotime($event['start']) : 0; 258 } 259 260 if (!isset($event['end']) && isset($event['eday'])) { 261 $eday = mktime(12,0,0,$event['emonth'],$event['eday'],$event['eyear']); 262 } else { 263 $eday = (isset($event['end']) && !empty($event['end'])) ? strtotime($event['end']) : 0; 264 } 265?> 266<table border="0" cellspacing="0" cellpadding="3" width="100%" class="vevent"> 267 <tr bgcolor="#dddddd"><td> 268<?php 269 270 // Print out date if needed 271 if ($include_date && (isset($event['start']))) { 272 echo "<b>", date("F j, Y", $sday), "</b>\n"; 273 } 274 275 // Print link in case we have one 276 if ($event['url']) { echo '<a href="', htmlentities($event['url'], ENT_QUOTES | ENT_IGNORE, 'UTF-8'),'" class="url">'; } 277 // Print event description 278 echo "<b class='summary'>", stripslashes(htmlentities($event['sdesc'], ENT_QUOTES | ENT_IGNORE, 'UTF-8')), "</b>"; 279 // End link 280 if ($event['url']) { echo "</a>"; } 281 282 // Print extra date info for recurring and multiday events 283 switch ($event['type']) { 284 case 2: 285 case 'multi': 286 $dtend = date("Y-m-d", strtotime("+1 day", $eday)); 287 echo " (<abbr class='dtstart'>", date("Y-m-d",$sday), "</abbr> to <abbr class='dtend' title='$dtend'>", date("Y-m-d",$eday), "</abbr>)"; 288 break; 289 case 3: 290 case 'recur': 291 $days = $re[$event['recur']] . " " . $days[$event['recur_day']]; 292 if (!$cm || $cy) { 293 $cm = date("m"); 294 $cy = date("Y"); 295 } 296 $month = date("M", mktime(0, 0, 0, $cm, 1, $cy)); 297 $dtstart = date("Y-m-d", strtotime($days . ' 0st' . $month . ' ' . $cy)); 298 echo ' (Every <abbr class="dtstart" title="' . $dtstart . '">', $days, "</abbr> of the month)"; 299 break; 300 } 301 302 // Event category 303 if (isset($event['category']) && $event['category']) { 304 $cat = ["unknown", "User Group Event", "Conference", "Training"]; 305 echo ' [' . $cat[$event['category']] . '] '; 306 } 307 308 // Print out country information 309 echo ' (<span class="location">' , $COUNTRIES[$event['country']] , '</span>)'; 310?> 311 </td></tr> 312 <tr bgcolor="#eeeeee" class="description"><td> 313<?php 314 315 // Print long description 316 echo preg_replace("/\r?\n\r?\n/", "<br><br>", trim(htmlentities($event['ldesc'],ENT_QUOTES | ENT_IGNORE, 'UTF-8'))); 317 // If we have an URL, print it out 318 if ($event['url']) { 319 echo '<br><br><b>URL:</b> ', 320 '<a href="', htmlentities($event['url'], ENT_QUOTES | ENT_IGNORE, 'UTF-8'), '">', 321 htmlentities($event['url'], ENT_QUOTES | ENT_IGNORE, 'UTF-8'), '</a>'; 322 } 323?> 324 </td></tr> 325</table> 326<?php 327} 328 329// Print news links for archives 330function news_archive_sidebar(): void 331{ 332 global $SIDEBAR_DATA; 333 $SIDEBAR_DATA = ' 334<h3 class="announcements">Archives by year</h3> 335 336'; 337 for ($i = date("Y"); $i >= 1998; $i--) { 338 $pagename = "archive/$i.php"; 339 $classname = ($pagename == $_SERVER['BASE_PAGE'] ? " active" : ''); 340 $SIDEBAR_DATA .= "<p class='panel{$classname}'><a href=\"/{$pagename}\">{$i}</a></p>\n"; 341 } 342} 343 344// Print news 345function print_news($news, $dog, $max = 5, $onlyyear = null, $return = false) { 346 $retval = []; 347 $count = 0; 348 $news = $news ?: []; // default to empty array (if no news) 349 foreach ($news as $item) { 350 $ok = false; 351 352 // Only print entries in the provided s/dog/cat/ egory 353 // If $dog is null, everything matches 354 foreach ($item["category"] as $category) { 355 if (null === $dog || in_array($category["term"], (array)$dog, true)) { 356 $ok = true; 357 $count++; 358 break; 359 } 360 } 361 if ($count > $max) { 362 break; 363 } 364 if ($ok === false) { 365 continue; 366 } 367 368 $image = ""; 369 if (isset($item["newsImage"])) { 370 $image = news_image($item["newsImage"]["link"], $item["newsImage"]["content"], $item["newsImage"]["title"], false); 371 } 372 373 $id = parse_url($item["id"]); 374 $id = $id["fragment"]; 375 376 // Find the permlink 377 foreach ($item["link"] as $link) { 378 if ($link["rel"] === "via") { 379 $permlink = $link["href"]; 380 break; 381 } 382 } 383 if (!isset($permlink)) { 384 $permlink = "#" . $id; 385 } 386 387 $published = substr($item["published"], 0, 10); 388 $nixtimestamp = strtotime($published); 389 $newsdate = date("d M Y", $nixtimestamp); 390 if ($onlyyear && date("Y", $nixtimestamp) != $onlyyear) { 391 $count--; 392 continue; 393 } 394 395 if ($return) { 396 $retval[] = [ 397 "title" => $item["title"], 398 "id" => $id, 399 "permlink" => $permlink, 400 "date" => $newsdate, 401 ]; 402 continue; 403 } 404 405 echo <<<EOT 406<article class="newsItem"> 407 <header> 408 <div class="newsImage">{$image}</div> 409 <h2 class="newstitle"><a id="{$id}" href="{$permlink}" rel="bookmark" class="bookmark">{$item["title"]}</a></h2> 410 </header> 411 <time class="newsdate" datetime="{$item["published"]}">{$newsdate}</time> 412 <div class="newscontent"> 413 {$item["content"]} 414 </div> 415</article> 416 417EOT; 418 } 419 420 return $retval; 421} 422 423function site_header(string $title = 'Hypertext Preprocessor', array $config = []): void 424{ 425 global $MYSITE; 426 427 $meta_image_path = $MYSITE . 'images/meta-image.png'; 428 $meta_description = "PHP is a popular general-purpose scripting language that powers everything from your blog to the most popular websites in the world."; 429 430 $defaults = [ 431 "lang" => myphpnet_language(), 432 "current" => "", 433 "meta-navigation" => [], 434 'classes' => '', 435 'layout_span' => 9, 436 "cache" => false, 437 "headsup" => "", 438 'meta_tags' => <<<META 439<meta name="Description" content="{$meta_description}" /> 440 441<meta name="twitter:card" content="summary_large_image" /> 442<meta name="twitter:site" content="@official_php" /> 443<meta name="twitter:title" content="PHP: Hypertext Preprocessor" /> 444<meta name="twitter:description" content="{$meta_description}" /> 445<meta name="twitter:creator" content="@official_php" /> 446<meta name="twitter:image:src" content="{$meta_image_path}" /> 447 448<meta itemprop="name" content="PHP: Hypertext Preprocessor" /> 449<meta itemprop="description" content="$meta_description" /> 450<meta itemprop="image" content="{$meta_image_path}" /> 451 452<meta property="og:image" content="{$meta_image_path}" /> 453<meta property="og:description" content="$meta_description" /> 454 455<link href="https://fosstodon.org/@php" rel="me" /> 456META 457 ]; 458 459 $config = array_merge($defaults, $config); 460 461 $config["headsup"] = get_news_changes(); 462 463 $lang = language_convert($config["lang"]); 464 $curr = $config["current"]; 465 $classes = $config['classes']; 466 467 if (isset($_COOKIE["MD"]) || isset($_GET["MD"])) { 468 $classes .= "markdown-content"; 469 $config["css_overwrite"] = ["/styles/i-love-markdown.css"]; 470 } 471 472 // shorturl; http://wiki.snaplog.com/short_url 473 if (isset($_SERVER['BASE_PAGE']) && $shortname = get_shortname($_SERVER["BASE_PAGE"])) { 474 $shorturl = "https://www.php.net/" . $shortname; 475 } 476 477 require __DIR__ . "/header.inc"; 478} 479function site_footer(array $config = []): void 480{ 481 require __DIR__ . "/footer.inc"; 482} 483 484function get_news_changes() 485{ 486 include __DIR__ . "/pregen-news.inc"; 487 $date = date_create($NEWS_ENTRIES[0]["updated"]); 488 if (isset($_COOKIE["LAST_NEWS"]) && $_COOKIE["LAST_NEWS"] >= $date->getTimestamp()) { 489 return false; 490 } 491 492 /* It is a bug when this happens.. but I don't know where it is coming from */ 493 if (!isset($_SERVER["BASE_PAGE"])) { 494 return false; 495 } 496 if ($_SERVER["BASE_PAGE"] == "index.php") { 497 return false; 498 } 499 500 $date->modify("+1 week"); 501 if ($date->getTimestamp() > $_SERVER["REQUEST_TIME"]) { 502 $link = preg_replace('~^(http://php.net/|https://www.php.net/)~', '/', $NEWS_ENTRIES[0]["link"][0]["href"]); 503 $title = $NEWS_ENTRIES[0]["title"]; 504 return "<a href='{$link}'>{$title}</a>"; 505 } 506 return false; 507} 508 509function doc_toc($lang): void { 510 $file = __DIR__ . "/../manual/$lang/toc/index.inc"; 511 if (!file_exists($file)) { 512 $lang = "en"; // Fallback on english if the translation doesn't exist 513 $file = __DIR__ . "/../manual/en/toc/index.inc"; 514 } 515 require __DIR__ . "/../manual/$lang/toc/index.inc"; 516 517 echo "<dl>\n"; 518 doc_toc_list($lang, $TOC, "getting-started"); 519 doc_toc_list($lang, $TOC, "langref"); 520 echo "</dl>\n"; 521 522 echo "<dl>\n"; 523 doc_toc_list($lang, $TOC, "security"); 524 doc_toc_list($lang, $TOC, "features"); 525 echo "</dl>\n"; 526 527 echo "<dl>\n"; 528 doc_toc_list($lang, $TOC, "funcref"); 529 echo "</dl>\n"; 530 531 echo "<dl>\n"; 532 echo "<dt>Keyboard Shortcuts</dt>"; 533 echo "<dt>?</dt>\n"; 534 echo "<dd>This help</dd>\n"; 535 echo "<dt>j</dt>\n"; 536 echo "<dd>Next menu item</dd>\n"; 537 echo "<dt>k</dt>\n"; 538 echo "<dd>Previous menu item</dd>\n"; 539 echo "<dt>g p</dt>\n"; 540 echo "<dd>Previous man page</dd>\n"; 541 echo "<dt>g n</dt>\n"; 542 echo "<dd>Next man page</dd>\n"; 543 echo "<dt>G</dt>\n"; 544 echo "<dd>Scroll to bottom</dd>\n"; 545 echo "<dt>g g</dt>\n"; 546 echo "<dd>Scroll to top</dd>\n"; 547 echo "<dt>g h</dt>\n"; 548 echo "<dd>Goto homepage</dd>\n"; 549 echo "<dt>g s</dt>\n"; 550 echo "<dd>Goto search<br>(current page)</dd>\n"; 551 echo "<dt>/</dt>\n"; 552 echo "<dd>Focus search box</dd>\n"; 553 echo "</dl>"; 554 555} 556function doc_toc_list($lang, $index, $file): void { 557 include __DIR__ . "/../manual/$lang/toc/$file.inc"; 558 559 doc_toc_title($lang, $index, $file); 560 foreach ($TOC as $entry) { 561 echo "\t<dd><a href='/manual/$lang/{$entry[0]}'>{$entry[1]}</a></dd>\n"; 562 } 563} 564function doc_toc_title($lang, $index, $file, $elm = "dt"): void { 565 foreach ($index as $entry) { 566 if ($entry[0] == "$file.php") { 567 $link = $entry[0]; 568 $title = $entry[1]; 569 break; 570 } 571 } 572 echo "<$elm><a href='/manual/$lang/$link'>$title</a></$elm>\n"; 573} 574