1<?php 2/** 3 * MyBB 1.8 4 * Copyright 2014 MyBB Group, All Rights Reserved 5 * 6 * Website: http://www.mybb.com 7 * License: http://www.mybb.com/about/license 8 * 9 */ 10 11/* 12 * MyBB Admin CP Page Generation Class 13 */ 14class DefaultPage 15{ 16 17 /** 18 * @var string The current style in use. 19 */ 20 public $style; 21 22 /** 23 * @var array The primary menu items. 24 */ 25 public $menu = array(); 26 27 /** 28 * @var string The side bar menu items. 29 */ 30 public $submenu = ''; 31 32 /** 33 * @var string The module we're currently in. 34 */ 35 public $active_module; 36 37 /** 38 * @var string The action we're currently performing. 39 */ 40 public $active_action; 41 42 /** 43 * @var string Content for the side bar of the page if we have one. 44 */ 45 public $sidebar; 46 47 /** 48 * @var array The breadcrumb trail leading up to this page. 49 */ 50 public $_breadcrumb_trail = array(); 51 52 /** 53 * @var string Any additional information to add between the <head> tags. 54 */ 55 public $extra_header = ""; 56 57 /** 58 * @var string Any additional messages to add after the flash messages are shown. 59 */ 60 public $extra_messages = array(); 61 62 /** 63 * @var string Show a post verify error 64 */ 65 public $show_post_verify_error = ''; 66 67 /** 68 * Output the page header. 69 * 70 * @param string $title The title of the page. 71 */ 72 function output_header($title="") 73 { 74 global $mybb, $admin_session, $lang, $plugins; 75 76 $args = array( 77 'this' => &$this, 78 'title' => &$title, 79 ); 80 81 $plugins->run_hooks("admin_page_output_header", $args); 82 83 if(!$title) 84 { 85 $title = $lang->mybb_admin_panel; 86 } 87 88 $rtl = ""; 89 if($lang->settings['rtl'] == 1) 90 { 91 $rtl = " dir=\"rtl\""; 92 } 93 94 echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; 95 echo "<html xmlns=\"http://www.w3.org/1999/xhtml\"{$rtl}>\n"; 96 echo "<head profile=\"http://gmpg.org/xfn/1\">\n"; 97 echo " <title>".$title."</title>\n"; 98 echo " <meta name=\"author\" content=\"MyBB Group\" />\n"; 99 echo " <meta name=\"copyright\" content=\"Copyright ".COPY_YEAR." MyBB Group.\" />\n"; 100 echo " <link rel=\"stylesheet\" href=\"styles/".$this->style."/main.css?ver=1813\" type=\"text/css\" />\n"; 101 echo " <link rel=\"stylesheet\" href=\"styles/".$this->style."/modal.css?ver=1813\" type=\"text/css\" />\n"; 102 103 // Load stylesheet for this module if it has one 104 if(file_exists(MYBB_ADMIN_DIR."styles/{$this->style}/{$this->active_module}.css")) 105 { 106 echo " <link rel=\"stylesheet\" href=\"styles/{$this->style}/{$this->active_module}.css\" type=\"text/css\" />\n"; 107 } 108 109 echo " <script type=\"text/javascript\" src=\"../jscripts/jquery.js?ver=1823\"></script>\n"; 110 echo " <script type=\"text/javascript\" src=\"../jscripts/jquery.plugins.min.js?ver=1821\"></script>\n"; 111 echo " <script type=\"text/javascript\" src=\"../jscripts/general.js?ver=1821\"></script>\n"; 112 echo " <script type=\"text/javascript\" src=\"./jscripts/admincp.js?ver=1821\"></script>\n"; 113 echo " <script type=\"text/javascript\" src=\"./jscripts/tabs.js\"></script>\n"; 114 115 echo " <link rel=\"stylesheet\" href=\"jscripts/jqueryui/css/redmond/jquery-ui.min.css\" />\n"; 116 echo " <link rel=\"stylesheet\" href=\"jscripts/jqueryui/css/redmond/jquery-ui.structure.min.css\" />\n"; 117 echo " <link rel=\"stylesheet\" href=\"jscripts/jqueryui/css/redmond/jquery-ui.theme.min.css\" />\n"; 118 echo " <script src=\"jscripts/jqueryui/js/jquery-ui.min.js?ver=1813\"></script>\n"; 119 120 // Stop JS elements showing while page is loading (JS supported browsers only) 121 echo " <style type=\"text/css\">.popup_button { display: none; } </style>\n"; 122 echo " <script type=\"text/javascript\">\n". 123 "//<![CDATA[\n". 124 " document.write('<style type=\"text/css\">.popup_button { display: inline; } .popup_menu { display: none; }<\/style>');\n". 125 "//]]>\n". 126 "</script>\n"; 127 128 echo " <script type=\"text/javascript\"> 129//<![CDATA[ 130var loading_text = '{$lang->loading_text}'; 131var cookieDomain = '{$mybb->settings['cookiedomain']}'; 132var cookiePath = '{$mybb->settings['cookiepath']}'; 133var cookiePrefix = '{$mybb->settings['cookieprefix']}'; 134var cookieSecureFlag = '{$mybb->settings['cookiesecureflag']}'; 135var imagepath = '../images'; 136 137lang.unknown_error = \"{$lang->unknown_error}\"; 138lang.saved = \"{$lang->saved}\"; 139//]]> 140</script>\n"; 141 echo $this->extra_header; 142 echo "</head>\n"; 143 echo "<body>\n"; 144 echo "<div id=\"container\">\n"; 145 echo " <div id=\"logo\"><h1><span class=\"invisible\">{$lang->mybb_admin_cp}</span></h1></div>\n"; 146 $username = htmlspecialchars_uni($mybb->user['username']); 147 echo " <div id=\"welcome\"><span class=\"logged_in_as\">{$lang->logged_in_as} <a href=\"index.php?module=user-users&action=edit&uid={$mybb->user['uid']}\" class=\"username\">{$username}</a></span> | <a href=\"{$mybb->settings['bburl']}\" target=\"_blank\" class=\"forum\">{$lang->view_board}</a> | <a href=\"index.php?action=logout&my_post_key={$mybb->post_code}\" class=\"logout\">{$lang->logout}</a></div>\n"; 148 echo $this->_build_menu(); 149 echo " <div id=\"page\">\n"; 150 echo " <div id=\"left_menu\">\n"; 151 echo $this->submenu; 152 echo $this->sidebar; 153 echo " </div>\n"; 154 echo " <div id=\"content\">\n"; 155 echo " <div class=\"breadcrumb\">\n"; 156 echo $this->_generate_breadcrumb(); 157 echo " </div>\n"; 158 echo " <div id=\"inner\">\n"; 159 if(isset($admin_session['data']['flash_message']) && $admin_session['data']['flash_message']) 160 { 161 $message = $admin_session['data']['flash_message']['message']; 162 $type = $admin_session['data']['flash_message']['type']; 163 echo "<div id=\"flash_message\" class=\"{$type}\">\n"; 164 echo "{$message}\n"; 165 echo "</div>\n"; 166 update_admin_session('flash_message', ''); 167 } 168 169 if(!empty($this->extra_messages) && is_array($this->extra_messages)) 170 { 171 foreach($this->extra_messages as $message) 172 { 173 switch($message['type']) 174 { 175 case 'success': 176 case 'error': 177 echo "<div id=\"flash_message\" class=\"{$message['type']}\">\n"; 178 echo "{$message['message']}\n"; 179 echo "</div>\n"; 180 break; 181 default: 182 $this->output_error($message['message']); 183 break; 184 } 185 } 186 } 187 188 if($this->show_post_verify_error == true) 189 { 190 $this->output_error($lang->invalid_post_verify_key); 191 } 192 } 193 194 /** 195 * Output the page footer. 196 * 197 * @param bool $quit 198 */ 199 function output_footer($quit=true) 200 { 201 global $mybb, $maintimer, $db, $lang, $plugins; 202 203 $args = array( 204 'this' => &$this, 205 'quit' => &$quit, 206 ); 207 208 $plugins->run_hooks("admin_page_output_footer", $args); 209 210 $memory_usage = get_friendly_size(get_memory_usage()); 211 212 $totaltime = format_time_duration($maintimer->stop()); 213 $querycount = $db->query_count; 214 215 if(my_strpos(getenv("REQUEST_URI"), "?")) 216 { 217 $debuglink = htmlspecialchars_uni(getenv("REQUEST_URI")) . "&debug=1#footer"; 218 } 219 else 220 { 221 $debuglink = htmlspecialchars_uni(getenv("REQUEST_URI")) . "?debug=1#footer"; 222 } 223 224 echo " </div>\n"; 225 echo " </div>\n"; 226 echo " <br style=\"clear: both;\" />"; 227 echo " <br style=\"clear: both;\" />"; 228 echo " </div>\n"; 229 echo "<div id=\"footer\"><p class=\"generation\">".$lang->sprintf($lang->generated_in, $totaltime, $debuglink, $querycount, $memory_usage)."</p><p class=\"powered\">Powered By <a href=\"https://mybb.com/\" target=\"_blank\" rel=\"noopener\">MyBB</a>, © 2002-".COPY_YEAR." <a href=\"https://mybb.com/\" target=\"_blank\" rel=\"noopener\">MyBB Group</a>.</p></div>\n"; 230 if($mybb->debug_mode) 231 { 232 echo $db->explain; 233 } 234 echo "</div>\n"; 235 echo "</body>\n"; 236 echo "</html>\n"; 237 238 if($quit != false) 239 { 240 exit; 241 } 242 } 243 244 /** 245 * Add an item to the page breadcrumb trail. 246 * 247 * @param string $name The name of the item to add. 248 * @param string $url The URL to the item we're adding (if there is one) 249 */ 250 function add_breadcrumb_item($name, $url="") 251 { 252 $this->_breadcrumb_trail[] = array("name" => $name, "url" => $url); 253 } 254 255 /** 256 * Generate a breadcrumb trail. 257 * 258 * @return bool|string 259 */ 260 function _generate_breadcrumb() 261 { 262 if(!is_array($this->_breadcrumb_trail)) 263 { 264 return false; 265 } 266 $trail = ""; 267 foreach($this->_breadcrumb_trail as $key => $crumb) 268 { 269 if(isset($this->_breadcrumb_trail[$key+1])) 270 { 271 $trail .= "<a href=\"".$crumb['url']."\">".$crumb['name']."</a>"; 272 if(isset($this->_breadcrumb_trail[$key+2])) 273 { 274 $trail .= " » "; 275 } 276 } 277 else 278 { 279 $trail .= "<span class=\"active\">".$crumb['name']."</span>"; 280 } 281 } 282 return $trail; 283 } 284 285 /** 286 * Output a success message. 287 * 288 * @param string $message The message to output. 289 */ 290 function output_success($message) 291 { 292 echo "<div class=\"success\">{$message}</div>\n"; 293 } 294 295 /** 296 * Output an alert/warning message. 297 * 298 * @param string $message The message to output. 299 * @param string $id The ID of the alert/warning (optional) 300 */ 301 function output_alert($message, $id="") 302 { 303 if($id) 304 { 305 $id = " id=\"{$id}\""; 306 } 307 echo "<div class=\"alert\"{$id}>{$message}</div>\n"; 308 } 309 310 /** 311 * Output an inline message. 312 * 313 * @param string $message The message to output. 314 */ 315 function output_inline_message($message) 316 { 317 echo "<div class=\"inline_message\">{$message}</div>\n"; 318 } 319 320 /** 321 * Output a single error message. 322 * 323 * @param string $error The message to output. 324 */ 325 function output_error($error) 326 { 327 echo "<div class=\"error\">\n"; 328 echo "{$error}\n"; 329 echo "</div>\n"; 330 } 331 332 /** 333 * Output one or more inline error messages. 334 * 335 * @param array $errors Array of error messages to output. 336 */ 337 function output_inline_error($errors) 338 { 339 global $lang; 340 341 if(!is_array($errors)) 342 { 343 $errors = array($errors); 344 } 345 echo "<div class=\"error\">\n"; 346 echo "<p><em>{$lang->encountered_errors}</em></p>\n"; 347 echo "<ul>\n"; 348 foreach($errors as $error) 349 { 350 echo "<li>{$error}</li>\n"; 351 } 352 echo "</ul>\n"; 353 echo "</div>\n"; 354 } 355 356 /** 357 * Generate the login page. 358 * 359 * @param string $message The any message to output on the page if there is one. 360 * @param string $class The class name of the message (defaults to success) 361 */ 362 function show_login($message="", $class="success") 363 { 364 global $plugins, $lang, $cp_style, $mybb; 365 366 $args = array( 367 'this' => &$this, 368 'message' => &$message, 369 'class' => &$class 370 ); 371 372 $plugins->run_hooks('admin_page_show_login_start', $args); 373 374 $copy_year = COPY_YEAR; 375 376 $login_container_width = ""; 377 $login_label_width = ""; 378 379 // If the language string for "Username" is too cramped then use this to define how much larger you want the gap to be (in px) 380 if(isset($lang->login_field_width)) 381 { 382 $login_label_width = " style=\"width: ".((int)$lang->login_field_width+100)."px;\""; 383 $login_container_width = " style=\"width: ".(410+((int)$lang->login_field_width))."px;\""; 384 } 385 386 $login_page = <<<EOF 387<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 388<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> 389<head profile="http://gmpg.org/xfn/1"> 390<title>{$lang->mybb_admin_login}</title> 391<meta name="author" content="MyBB Group" /> 392<meta name="copyright" content="Copyright {$copy_year} MyBB Group." /> 393<link rel="stylesheet" href="./styles/{$cp_style}/login.css" type="text/css" /> 394<script type="text/javascript" src="../jscripts/jquery.js?ver=1823"></script> 395<script type="text/javascript" src="../jscripts/general.js?ver=1821"></script> 396<script type="text/javascript" src="./jscripts/admincp.js?ver=1821"></script> 397<script type="text/javascript"> 398//<![CDATA[ 399 loading_text = '{$lang->loading_text}'; 400//]]> 401</script> 402</head> 403<body> 404<div id="container"{$login_container_width}> 405 <div id="header"> 406 <div id="logo"> 407 <h1><a href="../" title="{$lang->return_to_forum}"><span class="invisible">{$lang->mybb_acp}</span></a></h1> 408 409 </div> 410 </div> 411 <div id="content"> 412 <h2>{$lang->please_login}</h2> 413EOF; 414 if($message) 415 { 416 $login_page .= "<p id=\"message\" class=\"{$class}\"><span class=\"text\">{$message}</span></p>"; 417 } 418 // Make query string nice and pretty so that user can go to his/her preferred destination 419 $query_string = ''; 420 if($_SERVER['QUERY_STRING']) 421 { 422 $query_string = '?'.preg_replace('#adminsid=(.{32})#i', '', $_SERVER['QUERY_STRING']); 423 $query_string = preg_replace('#my_post_key=(.{32})#i', '', $query_string); 424 $query_string = str_replace('action=logout', '', $query_string); 425 $query_string = preg_replace('#&+#', '&', $query_string); 426 $query_string = str_replace('?&', '?', $query_string); 427 $query_string = htmlspecialchars_uni($query_string); 428 } 429 switch($mybb->settings['username_method']) 430 { 431 case 0: 432 $lang_username = $lang->username; 433 break; 434 case 1: 435 $lang_username = $lang->username1; 436 break; 437 case 2: 438 $lang_username = $lang->username2; 439 break; 440 default: 441 $lang_username = $lang->username; 442 break; 443 } 444 445 // Secret PIN 446 global $config; 447 if(isset($config['secret_pin']) && $config['secret_pin'] != '') 448 { 449 $secret_pin = "<div class=\"label\"{$login_label_width}><label for=\"pin\">{$lang->secret_pin}</label></div> 450 <div class=\"field\"><input type=\"password\" name=\"pin\" id=\"pin\" class=\"text_input\" /></div>"; 451 } 452 else 453 { 454 $secret_pin = ''; 455 } 456 457 $login_lang_string = $lang->enter_username_and_password; 458 459 switch($mybb->settings['username_method']) 460 { 461 case 0: // Username only 462 $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_username); 463 break; 464 case 1: // Email only 465 $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_email); 466 break; 467 case 2: // Username and email 468 default: 469 $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_username_and_password); 470 break; 471 } 472 473 $this_file = htmlspecialchars_uni($_SERVER['SCRIPT_NAME']); 474 475 $login_page .= <<<EOF 476 <p>{$login_lang_string}</p> 477 <form method="post" action="{$this_file}{$query_string}"> 478 <div class="form_container"> 479 480 <div class="label"{$login_label_width}><label for="username">{$lang_username}</label></div> 481 482 <div class="field"><input type="text" name="username" id="username" class="text_input initial_focus" /></div> 483 484 <div class="label"{$login_label_width}><label for="password">{$lang->password}</label></div> 485 <div class="field"><input type="password" name="password" id="password" class="text_input" /></div> 486 {$secret_pin} 487 </div> 488 <p class="submit"> 489 <span class="forgot_password"> 490 <a href="../member.php?action=lostpw">{$lang->lost_password}</a> 491 </span> 492 493 <input type="submit" value="{$lang->login}" /> 494 <input type="hidden" name="do" value="login" /> 495 </p> 496 </form> 497 </div> 498</div> 499</body> 500</html> 501EOF; 502 503 $args = array( 504 'this' => &$this, 505 'login_page' => &$login_page 506 ); 507 508 $plugins->run_hooks('admin_page_show_login_end', $args); 509 510 echo $login_page; 511 exit; 512 } 513 514 function show_2fa() 515 { 516 global $lang, $cp_style, $mybb; 517 518 $copy_year = COPY_YEAR; 519 520 $mybb2fa_page = <<<EOF 521<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 522<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> 523<head profile="http://gmpg.org/xfn/1"> 524<title>{$lang->my2fa}</title> 525<meta name="author" content="MyBB Group" /> 526<meta name="copyright" content="Copyright {$copy_year} MyBB Group." /> 527<link rel="stylesheet" href="./styles/{$cp_style}/login.css" type="text/css" /> 528<script type="text/javascript" src="../jscripts/jquery.js?ver=1823"></script> 529<script type="text/javascript" src="../jscripts/general.js?ver=1821"></script> 530<script type="text/javascript" src="./jscripts/admincp.js?ver=1821"></script> 531<script type="text/javascript"> 532//<![CDATA[ 533 loading_text = '{$lang->loading_text}'; 534//]]> 535</script> 536</head> 537<body> 538<div id="container"> 539 <div id="header"> 540 <div id="logo"> 541 <h1><a href="../" title="{$lang->return_to_forum}"><span class="invisible">{$lang->mybb_acp}</span></a></h1> 542 </div> 543 </div> 544 <div id="content"> 545 <h2>{$lang->my2fa}</h2> 546EOF; 547 // Make query string nice and pretty so that user can go to his/her preferred destination 548 $query_string = ''; 549 if($_SERVER['QUERY_STRING']) 550 { 551 $query_string = '?'.preg_replace('#adminsid=(.{32})#i', '', $_SERVER['QUERY_STRING']); 552 $query_string = preg_replace('#my_post_key=(.{32})#i', '', $query_string); 553 $query_string = str_replace('action=logout', '', $query_string); 554 $query_string = preg_replace('#&+#', '&', $query_string); 555 $query_string = str_replace('?&', '?', $query_string); 556 $query_string = htmlspecialchars_uni($query_string); 557 } 558 $mybb2fa_page .= <<<EOF 559 <p>{$lang->my2fa_code}</p> 560 <form method="post" action="index.php{$query_string}"> 561 <div class="form_container"> 562 <div class="label"><label for="code">{$lang->my2fa_label}</label></div> 563 <div class="field"><input type="text" name="code" id="code" class="text_input initial_focus" /></div> 564 </div> 565 <p class="submit"> 566 <input type="submit" value="{$lang->login}" /> 567 <input type="hidden" name="do" value="do_2fa" /> 568 </p> 569 </form> 570 </div> 571</div> 572</body> 573</html> 574EOF; 575 echo $mybb2fa_page; 576 exit; 577 } 578 579 /** 580 * Generate the lockout page 581 * 582 */ 583 function show_lockedout() 584 { 585 global $lang, $mybb, $cp_style; 586 587 $copy_year = COPY_YEAR; 588 $allowed_attempts = (int)$mybb->settings['maxloginattempts']; 589 $lockedout_message = $lang->sprintf($lang->error_mybb_admin_lockedout_message, $allowed_attempts); 590 591 print <<<EOF 592<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 593<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> 594<head profile="http://gmpg.org/xfn/1"> 595<title>{$lang->mybb_admin_cp} - {$lang->error_mybb_admin_lockedout}</title> 596<meta name="author" content="MyBB Group" /> 597<meta name="copyright" content="Copyright {$copy_year} MyBB Group." /> 598<link rel="stylesheet" href="./styles/{$cp_style}/login.css" type="text/css" /> 599</head> 600<body> 601<div id="container"> 602 <div id="header"> 603 <div id="logo"> 604 <h1><a href="../" title="{$lang->return_to_forum}"><span class="invisible">{$lang->mybb_acp}</span></a></h1> 605 606 </div> 607 </div> 608 <div id="content"> 609 <h2>{$lang->error_mybb_admin_lockedout}</h2> 610 <div class="alert">{$lockedout_message}</div> 611 </div> 612</div> 613</body> 614</html> 615EOF; 616 exit; 617 } 618 619 /** 620 * Generate the lockout unlock page 621 * 622 * @param string $message The any message to output on the page if there is one. 623 * @param string $class The class name of the message (defaults to success) 624 */ 625 function show_lockout_unlock($message="", $class="success") 626 { 627 global $lang, $mybb, $cp_style; 628 629 $copy_year = COPY_YEAR; 630 631 $login_label_width = ""; 632 633 // If the language string for "Username" is too cramped then use this to define how much larger you want the gap to be (in px) 634 if(isset($lang->login_field_width)) 635 { 636 $login_label_width = " style=\"width: ".((int)$lang->login_field_width+100)."px;\""; 637 } 638 639 switch($mybb->settings['username_method']) 640 { 641 case 0: 642 $lang_username = $lang->username; 643 break; 644 case 1: 645 $lang_username = $lang->username1; 646 break; 647 case 2: 648 $lang_username = $lang->username2; 649 break; 650 default: 651 $lang_username = $lang->username; 652 break; 653 } 654 655 if($message) 656 { 657 $message = "<p id=\"message\" class=\"{$class}\"><span class=\"text\">{$message}</span></p>"; 658 } 659 660 print <<<EOF 661<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 662<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> 663<head profile="http://gmpg.org/xfn/1"> 664<title>{$lang->mybb_admin_cp} - {$lang->lockout_unlock}</title> 665<meta name="author" content="MyBB Group" /> 666<meta name="copyright" content="Copyright {$copy_year} MyBB Group." /> 667<link rel="stylesheet" href="./styles/{$cp_style}/login.css" type="text/css" /> 668</head> 669<body> 670<div id="container"> 671 <div id="header"> 672 <div id="logo"> 673 <h1><a href="../" title="{$lang->return_to_forum}"><span class="invisible">{$lang->mybb_acp}</span></a></h1> 674 675 </div> 676 </div> 677 <div id="content"> 678 <h2>{$lang->lockout_unlock}</h2> 679 {$message} 680 <p>{$lang->enter_username_and_token}</p> 681 <form method="post" action="index.php"> 682 <div class="form_container"> 683 684 <div class="label"{$login_label_width}><label for="username">{$lang_username}</label></div> 685 686 <div class="field"><input type="text" name="username" id="username" class="text_input initial_focus" /></div> 687 688 <div class="label"{$login_label_width}><label for="token">{$lang->unlock_token}</label></div> 689 <div class="field"><input type="text" name="token" id="token" class="text_input" /></div> 690 </div> 691 <p class="submit"> 692 <span class="forgot_password"> 693 <a href="../member.php?action=lostpw">{$lang->lost_password}</a> 694 </span> 695 696 <input type="submit" value="{$lang->unlock_account}" /> 697 <input type="hidden" name="action" value="unlock" /> 698 </p> 699 </form> 700 </div> 701</div> 702</body> 703</html> 704EOF; 705 exit; 706 } 707 708 /** 709 * Add an item to the primary navigation menu. 710 * 711 * @param string $title The title of the menu item. 712 * @param string $id The ID of the menu item. This should correspond with the module the menu will run. 713 * @param string $link The link to follow when the menu item is clicked. 714 * @param int $order The display order of the menu item. Lower display order means closer to start of the menu. 715 * @param array $submenu Array of sub menu items if there are any. 716 */ 717 function add_menu_item($title, $id, $link, $order=10, $submenu=array()) 718 { 719 $this->_menu[$order][] = array( 720 "title" => $title, 721 "id" => $id, 722 "link" => $link, 723 "submenu" => $submenu 724 ); 725 } 726 727 /** 728 * Build the actual navigation menu. 729 * 730 * @return bool|string 731 */ 732 function _build_menu() 733 { 734 if(!is_array($this->_menu)) 735 { 736 return false; 737 } 738 $build_menu = "<div id=\"menu\">\n<ul>\n"; 739 ksort($this->_menu); 740 foreach($this->_menu as $items) 741 { 742 foreach($items as $menu_item) 743 { 744 $menu_item['link'] = htmlspecialchars_uni($menu_item['link']); 745 if($menu_item['id'] == $this->active_module) 746 { 747 $sub_menu = $menu_item['submenu']; 748 $sub_menu_title = $menu_item['title']; 749 $build_menu .= "<li><a href=\"{$menu_item['link']}\" class=\"active\">{$menu_item['title']}</a></li>\n"; 750 751 } 752 else 753 { 754 $build_menu .= "<li><a href=\"{$menu_item['link']}\">{$menu_item['title']}</a></li>\n"; 755 } 756 } 757 } 758 $build_menu .= "</ul>\n</div>"; 759 760 if(!empty($sub_menu)) 761 { 762 $this->_build_submenu($sub_menu_title, $sub_menu); 763 } 764 return $build_menu; 765 } 766 767 /** 768 * Build a navigation sub menu if we have one. 769 * 770 * @param string $title A title for the sub menu. 771 * @param array $items Array of items for the sub menu. 772 */ 773 function _build_submenu($title, $items) 774 { 775 if(is_array($items)) 776 { 777 $sidebar = new sideBarItem($title); 778 $sidebar->add_menu_items($items, $this->active_action); 779 $this->submenu .= $sidebar->get_markup(); 780 } 781 } 782 783 /** 784 * Output a Javascript based tab control on to the page. 785 * 786 * @param array $tabs Array of tabs in name => title format. Name should correspond to the name of a DIV containing the tab content. 787 * @param boolean $observe_onload Whether or not to run the event onload or instantly 788 * @param string $id The ID to use for the tabs for if you run multiple instances of the tabbing control in one html page 789 */ 790 function output_tab_control($tabs=array(), $observe_onload=true, $id="tabs") 791 { 792 global $plugins; 793 $tabs = $plugins->run_hooks("admin_page_output_tab_control_start", $tabs); 794 echo "<ul class=\"tabs\" id=\"{$id}\">\n"; 795 $tab_count = count($tabs); 796 $done = 1; 797 foreach($tabs as $anchor => $title) 798 { 799 $class = ""; 800 if($tab_count == $done) 801 { 802 $class .= " last"; 803 } 804 if($done == 1) 805 { 806 $class .= " first"; 807 } 808 ++$done; 809 echo "<li class=\"{$class}\"><a href=\"#tab_{$anchor}\">{$title}</a></li>\n"; 810 } 811 echo "</ul>\n"; 812 $plugins->run_hooks("admin_page_output_tab_control_end", $tabs); 813 } 814 815 /** 816 * Output a series of primary navigation tabs for swithcing between items within a particular module/action. 817 * 818 * @param array $tabs Nested array of tabs containing possible keys of align, link_target, link_rel, link, title. 819 * @param string $active The name of the active tab. Corresponds with the key of each tab item. 820 */ 821 function output_nav_tabs($tabs=array(), $active='') 822 { 823 global $plugins; 824 $tabs = $plugins->run_hooks("admin_page_output_nav_tabs_start", $tabs); 825 echo "<div class=\"nav_tabs\">"; 826 echo "\t<ul>\n"; 827 foreach($tabs as $id => $tab) 828 { 829 $class = ''; 830 if($id == $active) 831 { 832 $class = ' active'; 833 } 834 if(isset($tab['align']) == "right") 835 { 836 $class .= " right"; 837 } 838 $target = ''; 839 if(isset($tab['link_target'])) 840 { 841 $target = " target=\"{$tab['link_target']}\""; 842 } 843 $rel = ''; 844 if(isset($tab['link_rel'])) 845 { 846 $rel = " rel=\"{$tab['link_rel']}\""; 847 } 848 if(!isset($tab['link'])) 849 { 850 $tab['link'] = ''; 851 } 852 echo "\t\t<li class=\"{$class}\"><a href=\"{$tab['link']}\"{$target}{$rel}>{$tab['title']}</a></li>\n"; 853 $target = ''; 854 } 855 echo "\t</ul>\n"; 856 if(!empty($tabs[$active]['description'])) 857 { 858 echo "\t<div class=\"tab_description\">{$tabs[$active]['description']}</div>\n"; 859 } 860 echo "</div>"; 861 $arguments = array('tabs' => $tabs, 'active' => $active); 862 $plugins->run_hooks("admin_page_output_nav_tabs_end", $arguments); 863 } 864 865 /** 866 * Output a page asking if a user wishes to continue performing a specific action. 867 * 868 * @param string $url The URL to be forwarded to. 869 * @param string $message The confirmation message to output. 870 * @param string $title The title to use in the output header 871 */ 872 function output_confirm_action($url, $message="", $title="") 873 { 874 global $lang, $plugins; 875 876 $args = array( 877 'this' => &$this, 878 'url' => &$url, 879 'message' => &$message, 880 'title' => &$title, 881 ); 882 883 $plugins->run_hooks('admin_page_output_confirm_action', $args); 884 885 if(!$message) 886 { 887 $message = $lang->confirm_action; 888 } 889 $this->output_header($title); 890 $form = new Form($url, 'post'); 891 892 echo "<div class=\"confirm_action\">\n"; 893 echo "<p>{$message}</p>\n"; 894 echo "<br />\n"; 895 echo "<p class=\"buttons\">\n"; 896 echo $form->generate_submit_button($lang->yes, array('class' => 'button_yes')); 897 echo $form->generate_submit_button($lang->no, array("name" => "no", 'class' => 'button_no')); 898 echo "</p>\n"; 899 echo "</div>\n"; 900 901 $form->end(); 902 $this->output_footer(); 903 } 904 905 /** 906 * Build a clickable MyCode editor for the Admin CP. 907 * 908 * @param string $bind The ID of the textarea to bind the editor to. 909 * @param string $editor_language The language string for the editor. 910 * @param bool $smilies Whether or not smilies should be included 911 * @return string The build MyCode editor Javascript. 912 */ 913 function build_codebuttons_editor($bind, $editor_language, $smilies) 914 { 915 global $lang, $mybb, $smiliecache, $smiliecount, $cache; 916 917 // Smilies 918 $emoticon = ""; 919 $emoticons_enabled = "false"; 920 if($smilies) 921 { 922 if($mybb->settings['smilieinserter'] && $mybb->settings['smilieinsertercols'] && $mybb->settings['smilieinsertertot']) 923 { 924 $emoticon = ",emoticon"; 925 } 926 $emoticons_enabled = "true"; 927 928 if(!$smiliecount) 929 { 930 $smilie_cache = $cache->read("smilies"); 931 if(!is_array($smilie_cache)) 932 { 933 $smilie_cache = array(); 934 } 935 $smiliecount = count($smilie_cache); 936 } 937 938 if(!$smiliecache) 939 { 940 if(!is_array($smilie_cache)) 941 { 942 $smilie_cache = $cache->read("smilies"); 943 } 944 foreach($smilie_cache as $smilie) 945 { 946 $smilie['image'] = str_replace("{theme}", "images", $smilie['image']); 947 $smiliecache[$smilie['sid']] = $smilie; 948 } 949 } 950 951 unset($smilie); 952 953 if(is_array($smiliecache)) 954 { 955 reset($smiliecache); 956 957 $dropdownsmilies = $moresmilies = $hiddensmilies = ""; 958 $i = 0; 959 960 foreach($smiliecache as $smilie) 961 { 962 $finds = explode("\n", $smilie['find']); 963 $finds_count = count($finds); 964 965 // Only show the first text to replace in the box 966 $find = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($finds[0])); 967 $image = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($smilie['image'])); 968 if(substr($image, 0, 4) != "http") 969 { 970 $image = $mybb->settings['bburl']."/".$image; 971 } 972 973 if(!$mybb->settings['smilieinserter'] || !$mybb->settings['smilieinsertercols'] || !$mybb->settings['smilieinsertertot'] || !$smilie['showclickable']) 974 { 975 $hiddensmilies .= '"'.$find.'": "'.$image.'",'; 976 } 977 elseif($i < $mybb->settings['smilieinsertertot']) 978 { 979 $dropdownsmilies .= '"'.$find.'": "'.$image.'",'; 980 ++$i; 981 } 982 else 983 { 984 $moresmilies .= '"'.$find.'": "'.$image.'",'; 985 } 986 987 for($j = 1; $j < $finds_count; ++$j) 988 { 989 $find = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($finds[$j])); 990 $hiddensmilies .= '"'.$find.'": "'.$image.'",'; 991 } 992 } 993 } 994 } 995 996 $basic1 = $basic2 = $align = $font = $size = $color = $removeformat = $email = $link = $list = $code = $sourcemode = ""; 997 998 if($mybb->settings['allowbasicmycode'] == 1) 999 { 1000 $basic1 = "bold,italic,underline,strike|"; 1001 $basic2 = "horizontalrule,"; 1002 } 1003 1004 if($mybb->settings['allowalignmycode'] == 1) 1005 { 1006 $align = "left,center,right,justify|"; 1007 } 1008 1009 if($mybb->settings['allowfontmycode'] == 1) 1010 { 1011 $font = "font,"; 1012 } 1013 1014 if($mybb->settings['allowsizemycode'] == 1) 1015 { 1016 $size = "size,"; 1017 } 1018 1019 if($mybb->settings['allowcolormycode'] == 1) 1020 { 1021 $color = "color,"; 1022 } 1023 1024 if($mybb->settings['allowfontmycode'] == 1 || $mybb->settings['allowsizemycode'] == 1 || $mybb->settings['allowcolormycode'] == 1) 1025 { 1026 $removeformat = "removeformat|"; 1027 } 1028 1029 if($mybb->settings['allowemailmycode'] == 1) 1030 { 1031 $email = "email,"; 1032 } 1033 1034 if($mybb->settings['allowlinkmycode'] == 1) 1035 { 1036 $link = "link,unlink"; 1037 } 1038 1039 if($mybb->settings['allowlistmycode'] == 1) 1040 { 1041 $list = "bulletlist,orderedlist|"; 1042 } 1043 1044 if($mybb->settings['allowcodemycode'] == 1) 1045 { 1046 $code = "code,php,"; 1047 } 1048 1049 if($mybb->user['sourceeditor'] == 1) 1050 { 1051 $sourcemode = "MyBBEditor.sourceMode(true);"; 1052 } 1053 1054 return <<<EOF 1055 1056<script type="text/javascript"> 1057var partialmode = {$mybb->settings['partialmode']}, 1058opt_editor = { 1059 plugins: "undo", 1060 format: "bbcode", 1061 bbcodeTrim: true, 1062 style: "../jscripts/sceditor/styles/jquery.sceditor.mybb.css", 1063 rtl: {$lang->settings['rtl']}, 1064 locale: "mybblang", 1065 enablePasteFiltering: true, 1066 autoUpdate: true, 1067 emoticonsEnabled: {$emoticons_enabled}, 1068 emoticons: { 1069 // Emoticons to be included in the dropdown 1070 dropdown: { 1071 {$dropdownsmilies} 1072 }, 1073 // Emoticons to be included in the more section 1074 more: { 1075 {$moresmilies} 1076 }, 1077 // Emoticons that are not shown in the dropdown but will still be converted. Can be used for things like aliases 1078 hidden: { 1079 {$hiddensmilies} 1080 } 1081 }, 1082 emoticonsCompat: true, 1083 toolbar: "{$basic1}{$align}{$font}{$size}{$color}{$removeformat}{$basic2}image,{$email}{$link}|video{$emoticon}|{$list}{$code}quote|maximize,source", 1084}; 1085{$editor_language} 1086$(function() { 1087 $("#{$bind}").sceditor(opt_editor); 1088 1089 MyBBEditor = $("#{$bind}").sceditor("instance"); 1090 {$sourcemode} 1091}); 1092</script> 1093EOF; 1094 } 1095} 1096 1097/** 1098 * A class for generating side bar blocks. 1099 */ 1100class DefaultSidebarItem 1101{ 1102 /** 1103 * @var string The title of the side bar block. 1104 */ 1105 private $_title; 1106 1107 /** 1108 * @var string The contents of the side bar block. 1109 */ 1110 private $_contents; 1111 1112 /** 1113 * Constructor. Set the title of the side bar block. 1114 * 1115 * @param string $title The title of the side bar block. 1116 */ 1117 function __construct($title="") 1118 { 1119 $this->_title = $title; 1120 } 1121 1122 /** 1123 * Add menus item to the side bar block. 1124 * 1125 * @param array $items Array of menu items to add. Each menu item should be a nested array of id, link and title. 1126 * @param string $active The ID of the active menu item if there is one. 1127 */ 1128 function add_menu_items($items, $active) 1129 { 1130 global $run_module; 1131 1132 $this->_contents = "<ul class=\"menu\">"; 1133 foreach($items as $item) 1134 { 1135 if(!check_admin_permissions(array("module" => $run_module, "action" => $item['id']), false)) 1136 { 1137 continue; 1138 } 1139 1140 $class = ""; 1141 if($item['id'] == $active) 1142 { 1143 $class = "active"; 1144 } 1145 $item['link'] = htmlspecialchars_uni($item['link']); 1146 $this->_contents .= "<li class=\"{$class}\"><a href=\"{$item['link']}\">{$item['title']}</a></li>\n"; 1147 } 1148 $this->_contents .= "</ul>"; 1149 } 1150 1151 /** 1152 * Sets custom html to the contents variable 1153 * 1154 * @param string $html The custom html to set 1155 */ 1156 function set_contents($html) 1157 { 1158 $this->_contents = $html; 1159 } 1160 1161 /** 1162 * Fetch the HTML markup for the side bar box. 1163 * 1164 * @return string 1165 */ 1166 function get_markup() 1167 { 1168 $markup = "<div class=\"left_menu_box\">\n"; 1169 $markup .= "<div class=\"title\">{$this->_title}</div>\n"; 1170 if($this->_contents) 1171 { 1172 $markup .= $this->_contents; 1173 } 1174 $markup .= "</div>\n"; 1175 return $markup; 1176 } 1177} 1178 1179/** 1180 * Generate a Javascript based popup menu. 1181 */ 1182class DefaultPopupMenu 1183{ 1184 /** 1185 * @var string The title of the popup menu to be shown on the button. 1186 */ 1187 private $_title; 1188 1189 /** 1190 * @var string The ID of this popup menu. Must be unique. 1191 */ 1192 private $_id; 1193 1194 /** 1195 * @var string Built HTML for the items in the popup menu. 1196 */ 1197 private $_items; 1198 1199 /** 1200 * Initialise a new popup menu. 1201 * 1202 * @var string $id The ID of the popup menu. 1203 * @var string $title The title of the popup menu. 1204 */ 1205 function __construct($id, $title='') 1206 { 1207 $this->_id = $id; 1208 $this->_title = $title; 1209 } 1210 1211 /** 1212 * Add an item to the popup menu. 1213 * 1214 * @param string $text The title of this item. 1215 * @param string $link The page this item should link to. 1216 * @param string $onclick The onclick event handler if we have one. 1217 */ 1218 function add_item($text, $link, $onclick='') 1219 { 1220 if($onclick) 1221 { 1222 $onclick = " onclick=\"{$onclick}\""; 1223 } 1224 $this->_items .= "<div class=\"popup_item_container\"><a href=\"{$link}\"{$onclick} class=\"popup_item\">{$text}</a></div>\n"; 1225 } 1226 1227 /** 1228 * Fetch the contents of the popup menu. 1229 * 1230 * @return string The popup menu. 1231 */ 1232 function fetch() 1233 { 1234 $popup = "<div class=\"popup_menu\" id=\"{$this->_id}_popup\">\n{$this->_items}</div>\n"; 1235 if($this->_title) 1236 { 1237 $popup .= "<a href=\"javascript:;\" id=\"{$this->_id}\" class=\"popup_button\">{$this->_title}</a>\n"; 1238 } 1239 $popup .= "<script type=\"text/javascript\">\n"; 1240 $popup .= "$(\"#{$this->_id}\").popupMenu();\n"; 1241 $popup .= "</script>\n"; 1242 return $popup; 1243 } 1244 1245 /** 1246 * Outputs a popup menu to the browser. 1247 */ 1248 function output() 1249 { 1250 echo $this->fetch(); 1251 } 1252} 1253