├── avatars └── .htaccess ├── templates ├── login │ ├── login_error.html │ ├── login_errors.html │ └── login_form.html ├── message.html ├── generic │ └── page_message.html ├── thread │ ├── label.html │ ├── thread_label.html │ ├── thread_title.html │ ├── modtools_button.html │ ├── thread.html │ ├── thread_display_blank.html │ ├── thread_title_edit.html │ ├── modtools.html │ ├── thread_display.html │ └── reply_box.html ├── header │ ├── menu_page.html │ ├── nav_seperator.html │ ├── nav_button.html │ ├── nav_disabled.html │ ├── title.html │ ├── nav_last.html │ ├── title_img.html │ └── header.html ├── pagination │ ├── page_button.html │ ├── page_button_disabled.html │ └── pagination.html ├── panel │ ├── panel_button.html │ └── panel_navigation.html ├── post │ ├── post_quote.html │ ├── post_restore.html │ ├── post_buttons.html │ ├── post_display_hidden.html │ ├── post_display.html │ └── post_edit.html ├── fatal.html ├── userlist │ ├── user_button.html │ ├── userlist.html │ ├── sort_options.html │ └── user_display.html ├── userpanel │ └── profilesettings.html ├── search │ ├── search_table.html │ └── search_page.html ├── category │ ├── category_page.html │ └── category_display.html ├── footer.html └── homepage │ └── homepage.html ├── lang ├── FA_IR.json ├── EN_US.json └── RU_RU.json ├── CREDITS.md ├── install ├── install.ico ├── logo.svg ├── install.css ├── install.svg └── install.php ├── themes ├── Aurora │ ├── icon.ico │ └── icon.png ├── Midnight │ ├── icon.ico │ ├── icon.png │ └── style.css └── Skyline │ ├── icon.ico │ └── icon.png ├── config ├── extensions-default.php └── config-setup.php ├── assets ├── panel.js ├── search.js ├── bbcode.js └── thread.js ├── .htaccess ├── extensions ├── Symbolism │ ├── manifest.json │ └── extension.php └── Stats │ ├── manifest.json │ ├── style.css │ └── extension.php ├── pages ├── footer.php ├── post.page.php ├── thread.ajax.php ├── userpanel.page.php ├── panel.page.php ├── userpanelprofilesettings.page.php ├── paneluseradmin.page.php ├── homepage.page.php ├── header.php ├── userpanelaccountsettings.page.php ├── category.page.php ├── panelextensions.page.php ├── userpanelavatarsettings.page.php ├── login.page.php ├── userlist.page.php ├── newthread.page.php ├── panelauditlog.page.php ├── panelsettings.page.php ├── user.page.php ├── signup.page.php ├── search.page.php └── panelcategory.page.php ├── libs ├── extensions.php ├── ajax.php ├── templates.php ├── language.php ├── permission.php └── formatter.php ├── README.md ├── index.php └── upgrade └── upgrade.page.php /avatars/.htaccess: -------------------------------------------------------------------------------- 1 | php_flag engine off 2 | -------------------------------------------------------------------------------- /templates/login/login_error.html: -------------------------------------------------------------------------------- 1 |
  • [[ error ]]
  • 2 | -------------------------------------------------------------------------------- /templates/message.html: -------------------------------------------------------------------------------- 1 |
    [[ content ]]
    2 | -------------------------------------------------------------------------------- /lang/FA_IR.json: -------------------------------------------------------------------------------- 1 | {"name": "فارسی", "region": "Iran", "region_abbr": "IR"} 2 | -------------------------------------------------------------------------------- /templates/generic/page_message.html: -------------------------------------------------------------------------------- 1 |

    [[ title ]]

    2 | [[ message ]] 3 | -------------------------------------------------------------------------------- /templates/thread/label.html: -------------------------------------------------------------------------------- 1 | [[ text ]] 2 | -------------------------------------------------------------------------------- /templates/thread/thread_label.html: -------------------------------------------------------------------------------- 1 | [[ label ]] 2 | -------------------------------------------------------------------------------- /templates/thread/thread_title.html: -------------------------------------------------------------------------------- 1 | [[ title ]] 2 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | tormater-yak 2 | GigaHacer 3 | vegbao 4 | cosmopolityan 5 | abdulhalim 6 | -------------------------------------------------------------------------------- /lang/EN_US.json: -------------------------------------------------------------------------------- 1 | {"name": "English", "region": "United States", "region_abbr": "US"} 2 | -------------------------------------------------------------------------------- /templates/header/menu_page.html: -------------------------------------------------------------------------------- 1 | [[ label ]] 2 | -------------------------------------------------------------------------------- /templates/header/nav_seperator.html: -------------------------------------------------------------------------------- 1 | [[ label ]] 2 | -------------------------------------------------------------------------------- /lang/RU_RU.json: -------------------------------------------------------------------------------- 1 | {"name": "Русский", "region": "Russian Federation", "region_abbr": "RU"} 2 | -------------------------------------------------------------------------------- /templates/header/nav_button.html: -------------------------------------------------------------------------------- 1 | [[ label ]] 2 | -------------------------------------------------------------------------------- /templates/header/nav_disabled.html: -------------------------------------------------------------------------------- 1 | [[ label ]] 2 | -------------------------------------------------------------------------------- /install/install.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tormater/tormater-forum/HEAD/install/install.ico -------------------------------------------------------------------------------- /templates/header/title.html: -------------------------------------------------------------------------------- 1 | [[ $forumName ]] 2 | -------------------------------------------------------------------------------- /templates/pagination/page_button.html: -------------------------------------------------------------------------------- 1 | [[ label ]] 2 | -------------------------------------------------------------------------------- /templates/panel/panel_button.html: -------------------------------------------------------------------------------- 1 | [[ title ]]  2 | -------------------------------------------------------------------------------- /templates/panel/panel_navigation.html: -------------------------------------------------------------------------------- 1 |
    2 | [[ buttons ]] 3 |
    4 | -------------------------------------------------------------------------------- /templates/header/nav_last.html: -------------------------------------------------------------------------------- 1 | [[ label ]] 2 | -------------------------------------------------------------------------------- /templates/pagination/page_button_disabled.html: -------------------------------------------------------------------------------- 1 | [[ label ]] 2 | -------------------------------------------------------------------------------- /themes/Aurora/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tormater/tormater-forum/HEAD/themes/Aurora/icon.ico -------------------------------------------------------------------------------- /themes/Aurora/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tormater/tormater-forum/HEAD/themes/Aurora/icon.png -------------------------------------------------------------------------------- /themes/Midnight/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tormater/tormater-forum/HEAD/themes/Midnight/icon.ico -------------------------------------------------------------------------------- /themes/Midnight/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tormater/tormater-forum/HEAD/themes/Midnight/icon.png -------------------------------------------------------------------------------- /themes/Skyline/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tormater/tormater-forum/HEAD/themes/Skyline/icon.ico -------------------------------------------------------------------------------- /themes/Skyline/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tormater/tormater-forum/HEAD/themes/Skyline/icon.png -------------------------------------------------------------------------------- /config/extensions-default.php: -------------------------------------------------------------------------------- 1 | false, 4 | ); 5 | ?> 6 | -------------------------------------------------------------------------------- /templates/post/post_quote.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /templates/fatal.html: -------------------------------------------------------------------------------- 1 |

    [[ title ]]

    2 | [[ message ]] 3 |
    4 | [[ back ]] 5 | -------------------------------------------------------------------------------- /templates/header/title_img.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /templates/userlist/user_button.html: -------------------------------------------------------------------------------- 1 |
    2 | -------------------------------------------------------------------------------- /templates/thread/modtools_button.html: -------------------------------------------------------------------------------- 1 |
    2 | -------------------------------------------------------------------------------- /assets/panel.js: -------------------------------------------------------------------------------- 1 | function checkColorRadio() { 2 | document.getElementById('newcolor').checked = true; 3 | document.getElementById('resetcolor').checked = false; 4 | } 5 | -------------------------------------------------------------------------------- /templates/post/post_restore.html: -------------------------------------------------------------------------------- 1 |
    2 | -------------------------------------------------------------------------------- /templates/userlist/userlist.html: -------------------------------------------------------------------------------- 1 |

    [[ title ]]

    2 | [[ sort_options ]] 3 | [[ pagination ]] 4 |
    5 | [[ users ]] 6 |
    7 |
    8 | [[ pagination ]] 9 | -------------------------------------------------------------------------------- /templates/userpanel/profilesettings.html: -------------------------------------------------------------------------------- 1 |

    [[ header ]]

    2 |
    3 |
    4 | [[ colors ]] 5 |
    6 | [[ bio_form ]] 7 | -------------------------------------------------------------------------------- /templates/login/login_errors.html: -------------------------------------------------------------------------------- 1 |

    [[ title ]]

    2 | [[ badfields ]] 3 | 6 |
    7 | [[ go_back ]] 8 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | php_value display_errors Off 2 | 3 | RewriteEngine On 4 | RewriteCond %{REQUEST_FILENAME} !-f 5 | RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] 6 | 7 | -------------------------------------------------------------------------------- /templates/search/search_table.html: -------------------------------------------------------------------------------- 1 | [[ pagination ]] 2 | 3 | [[ threads ]] 4 |
    [[ th_thread ]]
    [[ th_posts ]]
    [[ th_lastpost ]]
    5 | [[ pagination ]] 6 | -------------------------------------------------------------------------------- /extensions/Symbolism/manifest.json: -------------------------------------------------------------------------------- 1 | {"title": "Symbolism", "author": "[url=https://github.com/tormater]Tormater Organization[/url]", "readme": "Tormater Forum extension that adds FontAwesome icons to some elements."} 2 | -------------------------------------------------------------------------------- /extensions/Stats/manifest.json: -------------------------------------------------------------------------------- 1 | {"title": "Statistics", "author": "[url=https://github.com/tormater]Tormater Organization[/url]", "readme": "Tormater Forum extension that adds board statistics to the bottom of the page."} 2 | -------------------------------------------------------------------------------- /templates/thread/thread.html: -------------------------------------------------------------------------------- 1 | [[ error ]] 2 | [[ title ]] 3 | [[ info ]] 4 | [[ modtools ]] 5 | [[ labels ]] 6 | [[ pagination ]] 7 | [[ posts ]] 8 | [[ pagination ]] 9 | [[ reply ]] 10 | -------------------------------------------------------------------------------- /templates/thread/thread_display_blank.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | [[ title ]] 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /templates/thread/thread_title_edit.html: -------------------------------------------------------------------------------- 1 |
    2 | -------------------------------------------------------------------------------- /templates/pagination/pagination.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /extensions/Stats/style.css: -------------------------------------------------------------------------------- 1 | .statsLeft { 2 | min-width: 50%; 3 | max-width: 50%; 4 | float: left 5 | } 6 | .statsRight { 7 | min-width: 50%; 8 | max-width: 50%; 9 | float: right; 10 | text-align: right; 11 | } 12 | -------------------------------------------------------------------------------- /templates/thread/modtools.html: -------------------------------------------------------------------------------- 1 |
    2 |
    5 | [[ buttons ]] 6 |
    7 | -------------------------------------------------------------------------------- /templates/category/category_page.html: -------------------------------------------------------------------------------- 1 | [[ title ]] 2 | [[ desc ]] 3 | [[ pagination ]] 4 | 5 | [[ threads ]] 6 |
    [[ th_thread ]]
    [[ th_posts ]]
    [[ th_lastpost ]]
    7 | [[ pagination ]] 8 | -------------------------------------------------------------------------------- /templates/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /templates/homepage/homepage.html: -------------------------------------------------------------------------------- 1 |

    [[ title ]]

    2 | 3 | [[ categories ]] 4 |
    [[ th_category ]]
    [[ th_threads ]]
    [[ th_lastpost ]]
    5 | 6 | [[ threads ]] 7 |
    [[ th_recentthreads ]]
    [[ th_posts ]]
    [[ th_lastpost ]]
    8 | -------------------------------------------------------------------------------- /templates/userlist/sort_options.html: -------------------------------------------------------------------------------- 1 |
    2 | [[ label ]] 3 | 4 | 5 | 6 |
    7 | -------------------------------------------------------------------------------- /templates/userlist/user_display.html: -------------------------------------------------------------------------------- 1 |
    [[ username ]]  [[ role ]]  [[ buttons ]]
    [[ action ]] ([[ relative_time ]])
    2 | -------------------------------------------------------------------------------- /templates/post/post_buttons.html: -------------------------------------------------------------------------------- 1 |
    6 | -------------------------------------------------------------------------------- /templates/post/post_display_hidden.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | [[ profile ]] 4 |
    5 |
    6 |
    [[ hidden_info ]][[ quote ]]
    7 |
    8 |
    9 | -------------------------------------------------------------------------------- /templates/post/post_display.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | [[ profile ]] 4 | [[ buttons ]] 5 | 6 |
    7 |
    8 |
    9 | [[ quote ]] 10 |
    11 | 12 | [[ body ]] 13 |
    14 | 15 | -------------------------------------------------------------------------------- /templates/login/login_form.html: -------------------------------------------------------------------------------- 1 |

    [[ title ]]

    2 |
    3 |
    4 |
    5 |
    6 |
    7 | -------------------------------------------------------------------------------- /templates/thread/thread_display.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | [[ labels ]] 4 | [[ title ]] 5 |
    [[ startuser ]]
    6 | 7 | 8 |
    [[ posts ]]
    9 | 10 | 11 | [[ user ]] 12 |
    [[ reldate ]]
    13 | 14 | 15 | -------------------------------------------------------------------------------- /templates/category/category_display.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | [[ title ]] 4 |
    [[ desc ]]
    5 | 6 | 7 |
    [[ threads ]]
    8 | 9 | 10 | [[ lastpost ]] 11 |
    [[ user ]]
    12 | 13 | 14 | -------------------------------------------------------------------------------- /templates/post/post_edit.html: -------------------------------------------------------------------------------- 1 |
    2 | [[ bbcodebar ]] 3 |
    4 |
    5 | -------------------------------------------------------------------------------- /assets/search.js: -------------------------------------------------------------------------------- 1 | function search() { 2 | let searchPath = new URL(baseURL + '/search/', window.location.origin); 3 | var searchBox = document.getElementById('searchbox').value; 4 | if (searchBox.length > 0) { 5 | window.location.href = searchPath + "?search=" + encodeURIComponent(searchBox); 6 | } 7 | else window.location.href = searchPath; 8 | } 9 | 10 | document.querySelector('#searchbox').addEventListener('keydown', function (event) { 11 | if (event.keyCode == 13) { 12 | search(); 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /install/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | Tormater Forum 16 | Lightweight, easy-to-use, free forum software. 17 | 18 | 19 | -------------------------------------------------------------------------------- /templates/search/search_page.html: -------------------------------------------------------------------------------- 1 |

    [[ title ]]

    2 |
    3 |
    4 |
    5 |
    7 |
    8 | 9 |
    10 |
    11 | [[ table ]] 12 | -------------------------------------------------------------------------------- /pages/footer.php: -------------------------------------------------------------------------------- 1 | "© 2022-" . date("Y") . " Tormater Forum", 11 | "footer" => formatFooter($config["footer"]), 12 | "language" => $languageSelector, 13 | ); 14 | 15 | ob_start(); 16 | listener("beforeFooter"); 17 | $data["footer"] = $data["footer"] . ob_get_contents(); 18 | ob_end_clean(); 19 | ob_start(); 20 | listener("afterFooter"); 21 | $data["footer"] .= ob_get_contents(); 22 | ob_end_clean(); 23 | 24 | echo $template->render("templates/footer.html", $data); 25 | -------------------------------------------------------------------------------- /libs/extensions.php: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /templates/thread/reply_box.html: -------------------------------------------------------------------------------- 1 |
    2 |
    [[ title ]]
    3 | [[ bbcodebar ]] 4 |
    5 | 6 |
    7 | 8 | 9 |
    10 | [[ discard ]] 11 |
    12 | -------------------------------------------------------------------------------- /pages/post.page.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM posts WHERE postid='" . $db->real_escape_string($q2) . "'"); 13 | 14 | if ($post->num_rows < 1) redirect("404"); 15 | $row = $post->fetch_assoc(); 16 | 17 | $posts = $db->query("SELECT * FROM posts WHERE thread='" . $db->real_escape_string($row["thread"]) . "' ORDER BY timestamp"); 18 | 19 | if ($posts->num_rows < 1) redirect("404"); 20 | 21 | $post_position = 0; 22 | while ($p = $posts->fetch_assoc()) { 23 | $post_position++; 24 | if ($p["postid"] == $row["postid"]) break; 25 | } 26 | 27 | $postsPerPage = (is_numeric($config["postsPerPage"]) ? (int)$config["postsPerPage"] : 10); 28 | if ($postsPerPage < 1) $postsPerPage = 1; 29 | 30 | $pagenum = ceil($post_position/$postsPerPage); 31 | 32 | redirect("thread/" . $row["thread"] . "/" . $pagenum . "/#post_" . $row["postid"]); 33 | 34 | ?> 35 | -------------------------------------------------------------------------------- /pages/thread.ajax.php: -------------------------------------------------------------------------------- 1 | query("SELECT content, deletedby FROM posts WHERE postid='" . $db->real_escape_string($_POST["postid"]) . "'"); 10 | while($row = $post->fetch_assoc()) 11 | { 12 | if (!isset($row["deletedby"])) 13 | { 14 | echo "[quote]"; 15 | $quotecontent = preg_replace("/\[quote\](.+?)\[\/quote\]\s+/is", "", $row["content"]); 16 | $quotecontent = preg_replace("/\[blockquote\](.+?)\[\/blockquote\]\s+/is", "", $quotecontent); 17 | echo $quotecontent; 18 | echo "[/quote]"; 19 | echo "\n"; 20 | } 21 | } 22 | } 23 | if (isset($_POST["postRaw"]) && strlen($_POST["postRaw"]) <= $config['maxCharsPerPost']) 24 | { 25 | echo formatPost(htmlspecialchars_decode($_POST["postRaw"])); 26 | } 27 | } 28 | ?> 29 | -------------------------------------------------------------------------------- /libs/ajax.php: -------------------------------------------------------------------------------- 1 | 51 | -------------------------------------------------------------------------------- /pages/userpanel.page.php: -------------------------------------------------------------------------------- 1 | array("userpanelavatarsettings.page.php", $lang["userpanel.AvatarSettings"]), 18 | "accountsettings" => array("userpanelaccountsettings.page.php", $lang["userpanel.AccountSettings"]), 19 | "profilesettings" => array("userpanelprofilesettings.page.php", $lang["userpanel.ProfileSettings"]) 20 | ); 21 | 22 | listener("userpanelBeforeRender"); 23 | 24 | include "header.php"; 25 | 26 | 27 | $data = array( 28 | "buttons" => "" 29 | ); 30 | 31 | foreach($panel_pages as $k => $v) { 32 | if (!strlen($v[1])) continue; 33 | $b_data = array("url" => genURL("userpanel/" . $k), "title" => $v[1]); 34 | $data["buttons"] .= $template->render("templates/panel/panel_button.html",$b_data); 35 | } 36 | 37 | echo $template->render("templates/panel/panel_navigation.html",$data); 38 | 39 | if (array_key_exists($q2,$panel_pages)) { 40 | include $panel_pages[$q2][0]; 41 | } 42 | else include $panel_pages["avatarsettings"][0]; 43 | 44 | include "footer.php"; 45 | 46 | ?> 47 | -------------------------------------------------------------------------------- /pages/panel.page.php: -------------------------------------------------------------------------------- 1 | array("panelsettings.page.php", $lang["panel.ForumSettings"]), 18 | "category" => array("panelcategory.page.php", $lang["panel.Categories"]), 19 | "extensions" => array("panelextensions.page.php", $lang["panel.Extensions"]), 20 | "auditlog" => array("panelauditlog.page.php", $lang["panel.AuditLog"]), 21 | "useradmin" => array("paneluseradmin.page.php",""), 22 | "restoreuser" => array("paneluseradmin.page.php","") 23 | ); 24 | 25 | listener("panelBeforeRender"); 26 | 27 | include "header.php"; 28 | 29 | $data = array( 30 | "buttons" => "" 31 | ); 32 | 33 | foreach($panel_pages as $k => $v) { 34 | if (!strlen($v[1])) continue; 35 | $b_data = array("url" => genURL("panel/" . $k), "title" => $v[1]); 36 | $data["buttons"] .= $template->render("templates/panel/panel_button.html",$b_data); 37 | } 38 | 39 | echo $template->render("templates/panel/panel_navigation.html",$data); 40 | 41 | if (array_key_exists($q2,$panel_pages)) { 42 | include $panel_pages[$q2][0]; 43 | } 44 | else include $panel_pages["settings"][0]; 45 | 46 | 47 | include "footer.php"; 48 | 49 | update_last_action("action.Panel"); 50 | 51 | ?> 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

    2 | Tormater Forum - Lightweight, easy to use, free forum software 3 | 4 |

    5 | 6 | ### Requirements 7 | - `Apache 2` or `nginx` 8 | - `PHP 7.4+` with `php-mysqli`, `php-gd`, `php-mbstring` 9 | - `MySQL` or `MariaDB` 10 | ### Installation 11 | 1. Install the requirements, and create a MySQL user. 12 | 2. Create a database for the forum, grant your user privileges on it. 13 | 3. Upload the forum software to your server (using git is recommended). 14 | 4. Navigate to your forum and fill out the installer. 15 | 16 | For more info on installing your forum, please view the [Installing your forum](https://github.com/tormater/tormater-forum/wiki/Installing-your-forum) wiki page. 17 | ### Help & Support 18 | - Support forum 19 | - Wiki 20 | 21 | ![image](https://github.com/tormater/tormater-forum/assets/115832947/f5a107dd-2aae-4a9e-9111-280f5c198277) 22 | More screenshots... 23 | -------------------------------------------------------------------------------- /extensions/Stats/extension.php: -------------------------------------------------------------------------------- 1 | " threads • ", 6 | "stats.Posts" => " posts • ", 7 | "stats.Users" => " users", 8 | ); 9 | 10 | function customLang($val) { 11 | global $lang, $stats_CustomLang; 12 | 13 | if (!in_array($val, $lang)) { 14 | return $stats_CustomLang[$val]; 15 | } 16 | else { 17 | return $lang[$val]; 18 | } 19 | } 20 | 21 | // Define the functions 22 | $start_time = microtime(true); 23 | 24 | function Stats_displayPageLoadTime() { 25 | global $start_time, $db; 26 | 27 | // Get counts of threads, users, and posts 28 | $threads = $db->query("SELECT * FROM threads"); 29 | $threadcount = $threads->num_rows; 30 | $users = $db->query("SELECT * FROM users"); 31 | $usercount = $users->num_rows; 32 | $posts = $db->query("SELECT * FROM posts"); 33 | $postcount = $posts->num_rows; 34 | 35 | // Display all the information 36 | print '
    '; 37 | print '
    This page was generated in ' . number_format((microtime(true) - $start_time)*1000, 3) . ' ms.
    '; 38 | print '
    ' . number_format($threadcount) . customLang("stats.Threads") . number_format($postcount) . customLang("stats.Posts") . number_format($usercount) . customLang("stats.Users") . '
    '; 39 | } 40 | 41 | function Stats_addStyles() { 42 | echo ''; 43 | } 44 | 45 | // Hook the functions 46 | hook("meta", "Stats_addStyles"); 47 | hook("afterFooter", "Stats_displayPageLoadTime"); 48 | ?> 49 | -------------------------------------------------------------------------------- /templates/header/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [[ title ]] 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | [[ color ]] 25 | [[ meta ]] 26 | 27 | 28 |
    29 |
    30 | [[ header ]] 31 |
    [[ welcome ]]
    32 |
    33 | 34 |
    35 | 37 |
    38 | [[ searchButton ]] 39 |
    40 |
    41 | 42 |
    43 | -------------------------------------------------------------------------------- /assets/bbcode.js: -------------------------------------------------------------------------------- 1 | function formatText(tag, num) { 2 | var Field = document.getElementById('textbox' + num); 3 | var val = Field.value; 4 | var selected_txt = val.substring(Field.selectionStart, Field.selectionEnd); 5 | var before_txt = val.substring(0, Field.selectionStart); 6 | var after_txt = val.substring(Field.selectionEnd, val.length); 7 | open_tag = '[' + tag + ']'; 8 | end_tag = '[/' + tag + ']'; 9 | new_selection_start = Field.selectionStart + open_tag.length; 10 | new_selection_end = Field.selectionEnd + open_tag.length; 11 | Field.value = before_txt + open_tag + selected_txt + end_tag + after_txt; 12 | Field.setSelectionRange(new_selection_start, new_selection_end); 13 | Field.focus(); 14 | } 15 | function formatTextWithDetails(tag, input, num) { 16 | var Field = document.getElementById('textbox' + num); 17 | var val = Field.value; 18 | 19 | var Details = document.getElementById(input + num ); 20 | if (Details.nodeName == 'SELECT') 21 | { 22 | var detailsVal = Details.options[Details.selectedIndex].value; 23 | } 24 | else { 25 | var detailsVal = Details.value; 26 | } 27 | 28 | var selected_txt = val.substring(Field.selectionStart, Field.selectionEnd); 29 | var before_txt = val.substring(0, Field.selectionStart); 30 | var after_txt = val.substring(Field.selectionEnd, val.length); 31 | open_tag = '[' + tag + '=' + detailsVal + ']'; 32 | end_tag = '[/' + tag + ']'; 33 | new_selection_start = Field.selectionStart + open_tag.length; 34 | new_selection_end = Field.selectionEnd + open_tag.length; 35 | Field.value = before_txt + open_tag + selected_txt + end_tag + after_txt; 36 | Field.setSelectionRange(new_selection_start, new_selection_end); 37 | Field.focus(); 38 | } 39 | -------------------------------------------------------------------------------- /libs/templates.php: -------------------------------------------------------------------------------- 1 | $config["forumTheme"], 24 | "forumName" => htmlspecialchars($config["forumName"]), 25 | "forumDescription" => $config["forumDescription"], 26 | "forumFooter" => $config["footer"], 27 | "baseURL" => $config["baseURL"], 28 | ); 29 | 30 | foreach ($template_global_tags as $k) { 31 | if (!str_contains($page, "[[ #" . $k . " ]]")) continue; 32 | $page = str_replace("[[ #" . $k . " ]]", $this->render("templates/" . $k . ".html", $menu_pages), $page); 33 | } 34 | foreach ($template_var_tags as $k => $v) { 35 | $page = str_replace("[[ $" . $k . " ]]", $v, $page); 36 | } 37 | 38 | if (!$strings) return $page; 39 | 40 | foreach ($strings as $k => $v) { 41 | if (is_null($v)) $v = ""; 42 | $page = str_replace("[[ " . $k . " ]]", $v, $page); 43 | } 44 | listener("beforeTemplateReturn", $page, $path, $strings); 45 | return $page; 46 | } 47 | function error($type) 48 | { 49 | global $cfg, $lang; 50 | $data = array( 51 | "title" => $lang["error." . $type], 52 | "desc" => sprintf($lang["error.desc"], "javascript:history.back()", $cfg->get("baseURL")), 53 | ); 54 | echo $this->render("templates/error.html", $data); 55 | exit; 56 | } 57 | } 58 | 59 | $template = new Template; 60 | -------------------------------------------------------------------------------- /libs/language.php: -------------------------------------------------------------------------------- 1 | $val) { // note: do not use $v for this because of the &$v above. Unless you want "Install Tormater Forum" to be a language. 43 | if (!array_key_exists($k,$lang)) { 44 | $lang[$k] = $k; 45 | } 46 | } 47 | 48 | $languageSelector = '
    '; 65 | 66 | ?> 67 | -------------------------------------------------------------------------------- /assets/thread.js: -------------------------------------------------------------------------------- 1 | function quotePost(id) { 2 | let ajaxPath = new URL(baseURL + '/pages/thread.ajax.php', document.location); 3 | var Field = document.getElementById('textbox1'); 4 | var val = Field.value; 5 | var selected_txt = val.substring(Field.selectionStart, Field.selectionEnd); 6 | var before_txt = val.substring(0, Field.selectionStart); 7 | var after_txt = val.substring(Field.selectionEnd, val.length); 8 | var xhttp = new XMLHttpRequest(); 9 | xhttp.onreadystatechange = function() { 10 | if (this.readyState == 4 && this.status == 200) { 11 | Field.value += this.responseText;; 12 | Field.focus(); 13 | Field.setSelectionRange(Field.selectionStart,Field.selectionEnd); 14 |        } 15 | }; 16 | xhttp.open('POST', ajaxPath, true); 17 | xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 18 | xhttp.send('postid=' + id); 19 | } 20 | 21 | function previewPost(num, type) { 22 | let ajaxPath = new URL(baseURL + '/pages/thread.ajax.php'); 23 | var Field = document.getElementById('textbox' + num); 24 | var PreviewBox = document.getElementById("previewbox" + num) 25 | var PreviewButton = document.getElementById("showpreview" + num) 26 | var HidePreviewButton = document.getElementById("hidepreview" + num) 27 | var val = Field.value; 28 | 29 | if (type == 1) { 30 | var xhttp = new XMLHttpRequest(); 31 | xhttp.onreadystatechange = function() { 32 | if (this.readyState == 4 && this.status == 200) { 33 | Field.setSelectionRange(Field.selectionStart,Field.selectionEnd); 34 | PreviewButton.style = "display: none"; 35 | HidePreviewButton.style = ""; 36 | PreviewBox.innerHTML = this.responseText; 37 | PreviewBox.style = ""; 38 | PreviewButton.blur(); 39 | HidePreviewButton.scrollIntoView(); 40 | 41 |         } 42 | }; 43 | 44 | xhttp.open('POST', ajaxPath, true); 45 | xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 46 | const postParams = new URLSearchParams(); 47 | postParams.set('postRaw', Field.value); 48 | 49 | xhttp.send(postParams.toString()); 50 | } 51 | else { 52 | PreviewButton.style = ""; 53 | HidePreviewButton.style = "display: none"; 54 | PreviewBox.style = "display: none"; 55 | PreviewBox.innerHTML = "" 56 | HidePreviewButton.blur(); 57 | PreviewButton.scrollIntoView(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /install/install.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: Arial, sans-serif; 3 | } 4 | body { 5 | background: #e6e6e6; 6 | font-size: 75%; 7 | margin: 0; 8 | color: #333333; 9 | max-width: 600px; 10 | margin: 10px auto; 11 | } 12 | 13 | img { 14 | width: 100%; 15 | height: auto; 16 | margin-bottom: 20px; 17 | } 18 | #titlebar { 19 | padding: 15px 30px; 20 | width: 100%; 21 | box-sizing: border-box; 22 | background-color: #000; 23 | background-image: linear-gradient(#ffffffad 0%, #ffffff20 50%, #0001 50%, #fff3 100%); 24 | border: #000 1px solid; 25 | text-shadow: #000 0px 1px; 26 | color: #fff; 27 | font-size: 175%; 28 | } 29 | #content { 30 | padding: 15px 25px; 31 | width: 100%; 32 | box-sizing: border-box; 33 | background: #fff; 34 | border: 1px solid #ccc; 35 | border-radius: 10px; 36 | text-align: left; 37 | box-shadow: 0px 1px 2px #0000001c; 38 | } 39 | 40 | 41 | .field { 42 | display: grid; 43 | grid-template-columns: auto 40%; 44 | } 45 | 46 | label { 47 | color: #000; 48 | display:inline-block; 49 | } 50 | 51 | input { 52 | display:inline-block; 53 | padding: 2px 4px; 54 | background: linear-gradient(#fff, #d4d4d4); 55 | border: 1px solid #808080; 56 | border-radius: 3px; 57 | font-size: 100%; 58 | margin: 2px 0px; 59 | } 60 | 61 | input:hover { 62 | filter: brightness(105%); 63 | } 64 | 65 | input:focus { 66 | background: #fff; 67 | border: #0292fc 1px solid; 68 | box-shadow: 0px 0px 3px #5dbcff; 69 | outline: none; 70 | } 71 | 72 | h3 { 73 | color: #000; 74 | display:inline-block; 75 | } 76 | h1 { 77 | color: #000; 78 | } 79 | 80 | .buttonbig { 81 | padding: 5px 10px; 82 | background: linear-gradient(#fff, #d3d3d3); 83 | border: 1px solid #808080; 84 | border-radius: 3px; 85 | color: #000; 86 | font-size: 15px; 87 | cursor: pointer; 88 | } 89 | 90 | .buttonbig:hover { 91 | filter: brightness(110%); 92 | text-decoration: none; 93 | } 94 | 95 | .buttonbig:active { 96 | filter: brightness(80%); 97 | outline: none; 98 | border: 1px solid #808080; 99 | } 100 | 101 | .buttonbig:focus { 102 | filter: brightness(80%); 103 | outline: none; 104 | border: 1px solid #808080; 105 | } 106 | 107 | hr { 108 | margin: 16px 0px; 109 | height: 1px; 110 | border-width: 0; 111 | background-color: rgb(199, 199, 199); 112 | } 113 | 114 | .message { 115 | padding: 8px 12px; 116 | background: linear-gradient(#4a5269, #656c81); 117 | box-shadow: 0px 1px inset #727b97; 118 | text-shadow: 0 1px #3a3f4e; 119 | border: 1px solid #3a4050; 120 | color: #fff; 121 | margin-bottom: 2px; 122 | } 123 | 124 | .message a { 125 | color: #7cb7fc; 126 | text-decoration: none; 127 | } 128 | -------------------------------------------------------------------------------- /libs/permission.php: -------------------------------------------------------------------------------- 1 | PERM_EDIT_POST|PERM_EDIT_THREAD|PERM_EDIT_USER|PERM_EDIT_CATEGORY|PERM_EDIT_FORUM|PERM_VIEW_AUDIT|PERM_CREATE_THREAD|PERM_CREATE_POST|PERM_VIEW_USERLIST|PERM_VIEW_USER|PERM_VIEW_THREAD|PERM_VIEW_CATEGORY|PERM_EDIT_PROFILE|PERM_IGNORE_THREAD_LABELS, 26 | "Moderator" => PERM_EDIT_POST|PERM_EDIT_THREAD|PERM_EDIT_USER|PERM_VIEW_AUDIT|PERM_CREATE_THREAD|PERM_CREATE_POST|PERM_VIEW_USERLIST|PERM_VIEW_USER|PERM_VIEW_THREAD|PERM_VIEW_CATEGORY|PERM_EDIT_PROFILE|PERM_IGNORE_THREAD_LABELS, 27 | "Member" => PERM_CREATE_THREAD|PERM_CREATE_POST|PERM_VIEW_USERLIST|PERM_VIEW_USER|PERM_VIEW_THREAD|PERM_VIEW_CATEGORY|PERM_EDIT_PROFILE, 28 | "Guest" => PERM_VIEW_USERLIST|PERM_VIEW_USER|PERM_VIEW_THREAD|PERM_VIEW_CATEGORY, 29 | "Suspended" => PERM_VIEW_USERLIST|PERM_VIEW_USER|PERM_VIEW_THREAD|PERM_VIEW_CATEGORY, 30 | ); 31 | 32 | if ($config["userlistMembersOnly"]) { 33 | $permissions["Guest"] ^= PERM_VIEW_USERLIST; 34 | } 35 | 36 | listener("afterDefaultPerms"); 37 | 38 | function get_role_from_session() { 39 | if (isset($_SESSION["role"])) return $_SESSION["role"]; 40 | else if (isset($_SESSION['signed_in']) && $_SESSION['signed_in']) return "Member"; 41 | else return "Guest"; 42 | } 43 | 44 | function get_role_permissions($r = "") { 45 | global $permissions; 46 | 47 | if ($r != "") $role = $r; 48 | else $role = get_role_from_session(); 49 | 50 | return $permissions[$role]; 51 | } 52 | 53 | function get_roles() { 54 | global $permissions; 55 | return array_diff(array_keys($permissions),array("Guest")); 56 | } 57 | 58 | function get_changeable_roles($r = "") { 59 | if ($r == "") $r = get_role_from_session(); 60 | if ($r == "Guest") return array(); 61 | if (!(get_role_permissions($r) & PERM_EDIT_USER)) return NULL; 62 | if (get_role_permissions($r) & PERM_EDIT_FORUM) return get_roles(); 63 | return array_slice(get_roles(),array_search($r,get_roles())+1); 64 | } 65 | 66 | function allowed_to_edit_user($victim_role, $role="") { 67 | return get_role_permissions($role) & PERM_EDIT_USER and in_array($victim_role,get_changeable_roles()); 68 | } 69 | -------------------------------------------------------------------------------- /extensions/Symbolism/extension.php: -------------------------------------------------------------------------------- 1 | '; 7 | echo ''; 8 | } 9 | 10 | hook("meta","symbolismAddCSS"); 11 | 12 | $lang["header.Home"] = " " . $lang["header.Home"]; 13 | $lang["header.Userlist"] = " " . $lang["header.Userlist"]; 14 | $lang["header.UserPanel"] = " " . $lang["header.UserPanel"]; 15 | $lang["header.NewThread"] = " " . $lang["header.NewThread"]; 16 | $lang["header.Panel"] = " " . $lang["header.Panel"]; 17 | $lang["header.Logout"] = " " . $lang["header.Logout"]; 18 | //$lang["header.Login"] = " " . $lang["header.Login"]; 19 | //$lang["header.Signup"] = " " . $lang["header.Signup"]; 20 | $lang["label.Sticky"] = " " . $lang["label.Sticky"]; 21 | $lang["label.Locked"] = " " . $lang["label.Locked"]; 22 | $lang["label.Pinned"] = " " . $lang["label.Pinned"]; 23 | $lang["thread.MoveThreadBtn"] = " " . $lang["thread.MoveThreadBtn"]; 24 | $lang["thread.DeleteThreadBtn"] = " " . $lang["thread.DeleteThreadBtn"]; 25 | $lang["thread.LockThreadBtn"] = " " . $lang["thread.LockThreadBtn"]; 26 | $lang["thread.StickyThreadBtn"] = " " . $lang["thread.StickyThreadBtn"]; 27 | $lang["thread.UnlockThreadBtn"] = " " . $lang["thread.UnlockThreadBtn"]; 28 | $lang["thread.UnstickyThreadBtn"] = " " . $lang["thread.UnstickyThreadBtn"]; 29 | $lang["thread.PinThreadBtn"] = " " . $lang["thread.PinThreadBtn"]; 30 | $lang["thread.UnpinThreadBtn"] = " " . $lang["thread.UnpinThreadBtn"]; 31 | 32 | $lang["post.DeleteBtn"] = ""; 33 | $lang["post.EditBtn"] = ""; 34 | $lang["post.HideBtn"] = ""; 35 | $lang["search.Button"] = " ". $lang["search.Button"]; 36 | $lang["thread.QuotePost"] = ""; 37 | $lang["post.RestoreHiddenBtn"] = ""; 38 | 39 | 40 | 41 | ?> 42 | -------------------------------------------------------------------------------- /pages/userpanelprofilesettings.page.php: -------------------------------------------------------------------------------- 1 | 0) and ($_POST["newcolor"] <= 16)) { 9 | $result = $db->query("UPDATE users SET color='" . $db->real_escape_string($_POST["newcolor"]) . "' WHERE userid='" . $_SESSION["userid"] . "'"); 10 | if (!$result) { 11 | message($lang["settings.SetColorError"]); 12 | } 13 | else { 14 | message($lang["settings.SetColorSuccess"]); 15 | header("Cache-Control:private"); 16 | } 17 | } 18 | else if (get_role_permissions() & PERM_EDIT_PROFILE) { 19 | if (isset($_POST["signature"]) and (strlen($_POST["signature"]) <= 512)) { 20 | $db->query("UPDATE users SET signature='" . $db->real_escape_string($_POST["signature"]) . "' WHERE userid='" . $_SESSION["userid"] . "'"); 21 | } 22 | elseif (isset($_POST["bio"]) and (strlen($_POST["bio"]) <= 2048)) { 23 | $db->query("UPDATE users SET bio='" . $db->real_escape_string($_POST["bio"]) . "' WHERE userid='" . $_SESSION["userid"] . "'"); 24 | } 25 | } 26 | 27 | $data = array( 28 | "header" => $lang["settings.PostColor"], 29 | "colors" => "", 30 | "bio_form" => "", 31 | ); 32 | 33 | $result = $db->query("SELECT color FROM users WHERE userid='" . $_SESSION["userid"] . "'"); 34 | $user = $result->fetch_assoc(); 35 | 36 | for ($i = 1; $i <= 16; $i++) { 37 | if ($user['color'] == $i) $usercolor = " userscolor"; 38 | else $usercolor = ""; 39 | $data["colors"] .= ''; 40 | } 41 | 42 | $userCheck = $db->query("SELECT signature, bio FROM users WHERE userid='" . $_SESSION["userid"] . "'"); 43 | 44 | while ($row = $userCheck->fetch_assoc()) { 45 | if (array_key_exists("signature",$_POST) and strlen($_POST["signature"])) { 46 | $signature = $_POST["signature"]; 47 | } 48 | else if (array_key_exists("signature",$row) and strlen($row["signature"])) { 49 | $signature = $row["signature"]; 50 | } 51 | else $signature = ""; 52 | 53 | if (array_key_exists("bio",$_POST) and strlen($_POST["bio"])) { 54 | $bio = $_POST["bio"]; 55 | } 56 | else if (array_key_exists("bio",$row) and strlen($row["bio"])) { 57 | $bio = $row["bio"]; 58 | } 59 | else $bio = ""; 60 | } 61 | 62 | if (get_role_permissions() & PERM_EDIT_PROFILE) { 63 | $data["bio_form"] .= "

    " . $lang["userpanel.Signature"] . "

    "; 64 | $data["bio_form"] .= BBCodeButtons(1,false) . "
    "; 65 | $data["bio_form"] .= "

    " . $lang["userpanel.Bio"] . "

    "; 66 | $data["bio_form"] .= BBCodeButtons(2,false) . "
    "; 67 | } 68 | 69 | echo $template->render("templates/userpanel/profilesettings.html", $data); 70 | 71 | // If the viewing user is logged in, update their last action. 72 | if ($_SESSION['signed_in'] == true) 73 | { 74 | update_last_action($lang["action.ProfileSettings"]); 75 | } 76 | 77 | ?> 78 | -------------------------------------------------------------------------------- /config/config-setup.php: -------------------------------------------------------------------------------- 1 | 'no', // Whether or not the forum is installed. (yes/no) 10 | 'MySQLServer' => '', // URL for your MySQL server. Set to localhost if it's on the same machine. 11 | 'MySQLUser' => '', // Username for native MySQL user. 12 | 'MySQLPass' => '', // Password for native MySQL user. 13 | 'MySQLDatabase' => '', // Name of the MySQL database you wish to use. 14 | 'baseURL' => 'http://example.com', // The base URL for the website that the forum is on. 15 | 'cookieName' => 'forum', // The name of cookies set by the forum. 16 | 'forumName' => 'Tormater Forum', // The forum's name. 17 | 'footer' => '', // The text that appears on the footer. Supports BBCode. 18 | 'postsPerPage' => 10, // Number of posts to display on a page in a thread. 19 | 'threadsPerPage' => 20, // Number of threads to display on a page in a category. 20 | 'usersPerPage' => 30, // Number of users to display per page in the userlist. 21 | 'maxCharsPerPost' => 50000, // Maximum number of characters allowable in a single post. 22 | 'maxUsernameLength' => 24, // Maximum username length. 23 | 'postDelay' => 5, // Number of seconds between posts during which a user can't make another post. 24 | 'maxCharsPerTitle' => 35, // Maximum number of characters allowable in a title. Includes category names along with thread titles. 25 | 'forumTheme' => 'Aurora', // The directory that the forum should look in for skin files 26 | 'forumLang' => 'EN_US', // The language file that the forum should use to display strings 27 | 'userlistEnabled' => true, // Whether or not the userlist is enabled. 28 | 'userlistMembersOnly' => false, // Whether or not the userlist is only viewable by members. 29 | 'maxAccountsPerIP' => 5, // Maximum number of accounts that can be created on one IP. 30 | 'hashAlgo' => "sha512", // The default hashing algorithm for your forum to use. 31 | 'avatarWidth' => 200, // Maximum avatar width. 32 | 'avatarHeight' => 200, // Maximum avatar height. 33 | 'avatarUploadsDisabled' => false, // Whether or not avatar uploads are disabled. 34 | 'timeBetweenAvatarUploads' => 120, // How much time (in seconds) the user should have to wait to upload another avatar. 35 | 'maxLoginAttempts' => 3, // Number of login attempts allowed every 5 minutes. 36 | 'captchaLength' => 5, // Number of characters to use in the captcha. 37 | 'captchaEnabled' => true, // Whether or not the captcha is enabled. 38 | 'mainAdmin' => 1, // Userid of the main administrator. 39 | 'forumDescription' => 'Tormater Forum is a lightweight, easy-to-use forum software created with PHP and MySQL.', 40 | 'draftsPerMinute' => 5, // Number of draft posts a user can make per minute. 41 | 'forumColor' => null, // Forum color 42 | 'registration' => 'open', // Registration options. 'open' for unrestricted signups, 'closed' for no signups, 'approval' for signups requiring manual approval by mods and admins. 43 | 'onlinePeriod' => '600', // The amount of time a user is shown as "online". 44 | 'showDeletedInUserlist' => 0, // If deleted users should be shown in the userlist. 45 | 'modRewriteDisabled' => 0, // If mod_rewrite is disabled, use query parameters [127.0.0.1/thread/10] vs [127.0.0.1/index.php?url=thread/10] 46 | 'parentSite' => '', // The URL of the parent website (for example, if the forum is at 127.0.0.1/forum, the parent site would be 127.0.0.1) 47 | 'parentSiteName' => '', // The name of the parent website (see above) 48 | 'maxAvatarSize' => 5000000, // The maximum acceptable filesize (in bytes) for an avatar upload 49 | ); 50 | 51 | ?> 52 | -------------------------------------------------------------------------------- /libs/formatter.php: -------------------------------------------------------------------------------- 1 | ' . str_replace(array('[', ']'), array('[', ']'), $match[1]) . ''; 15 | }, $returnPost); 16 | 17 | $find = array( 18 | '/\[b\](.+?)\[\/b\]/is', 19 | '/\[i\](.+?)\[\/i\]/is', 20 | '/\[u\](.+?)\[\/u\]/is', 21 | '/\[s\](.+?)\[\/s\]/is', 22 | '/\[url=(http|ftp|https):\/\/(.+?)\](.+?)\[\/url\]/is', 23 | '/\[url=(.+?)\](http|ftp|https):\/\/(.+?)\[\/url\]/is', 24 | '/\[url\](http|ftp|https):\/\/(.+?)\[\/url\]/is', 25 | '/\[img\](http|https):\/\/(.+?)\[\/img\]/is', 26 | '/\[spoiler\](.+?)\[\/spoiler\]/is', 27 | '/\[spoiler=(.+?)\](.+?)\[\/spoiler\]/is', 28 | '/\[color=(.+?)\](.+?)\[\/color\]/is', 29 | '/\[size=([0-3][0-9][0-9])\](.+?)\[\/size\]/is', 30 | '/\[size=([8-9][0-9])\](.+?)\[\/size\]/is', 31 | //'/\[code\](.+?)\[\/code\]/is', 32 | '/\[pre\](.+?)\[\/pre\]/is', 33 | '/\[h\](.+?)\[\/h\]/is', 34 | '/\[h2\](.+?)\[\/h2\]/is', 35 | '/\[list\](.+?)\[\/list\]/is', 36 | '/\[list=1\](.+?)\[\/list\]/is', 37 | '/\[list=a\](.+?)\[\/list\]/is', 38 | '/\[\*\](.+?)(\n|\r\n?)/is', 39 | '/(\n|\r\n?)\[hr\]\[\/hr\](\n|\r\n?)/is', 40 | '/(\n|\r\n?)\[hr\]\[\/hr\]/is', 41 | '/\[quote\](.+?)\[\/quote\]/is', 42 | '/\[blockquote\](.+?)\[\/blockquote\]/is', 43 | ); 44 | 45 | $replace = array( 46 | '$1', 47 | '$1', 48 | '$1', 49 | '$1', 50 | '$3', 51 | '$1', 52 | '$2', 53 | '', 54 | '
    Spoiler$1
    ', 55 | '
    Spoiler: $1$2
    ', 56 | '$2', 57 | '$2', 58 | '$2', 59 | //'$1', 60 | '
    $1
    ', 61 | '$1', 62 | '$1', 63 | '', 64 | '
      $1
    ', 65 | '
      $1
    ', 66 | '
  • $1
  • ', 67 | '
    ', 68 | '
    ', 69 | '
    $1
    ', 70 | '
    $1
    ', 71 | ); 72 | 73 | listener("beforeFormatBBCode"); 74 | $returnPost = preg_replace($find, $replace, $returnPost); 75 | $returnPost = str_replace(array('[', ']'), array('[', ']'), $returnPost); 76 | return $returnPost; 77 | } 78 | function formatPost($post) 79 | { 80 | $returnPost = formatBBCode($post); 81 | $returnPost = str_replace("\n","
    ",$returnPost); 82 | listener("beforeReturnFormattedPost"); 83 | return $returnPost; 84 | } 85 | function formatFooter($post) 86 | { 87 | $returnPost = formatBBCode($post); 88 | listener("beforeReturnFormattedFooter"); 89 | return $returnPost; 90 | } 91 | ?> 92 | -------------------------------------------------------------------------------- /pages/paneluseradmin.page.php: -------------------------------------------------------------------------------- 1 | query("SELECT ip FROM users WHERE userid='" . $db->real_escape_string($q3) . "'"); 20 | $r = $ip->fetch_assoc(); 21 | $result = $db->query("SELECT userid FROM users WHERE ip='" . $r["ip"] . "' AND NOT userid='" . $db->real_escape_string($q3) . "'"); 22 | if ($result->num_rows == 0) 23 | { 24 | message($lang["panel.noSameIP"]); 25 | } 26 | else 27 | { 28 | $result = $db->query("SELECT userid FROM users WHERE ip='" . $r["ip"] . "'"); 29 | while($row = $result->fetch_assoc()) { 30 | deleteUser("deleteRemovePosts", $row["userid"], false); 31 | } 32 | message($lang["panel.DeleteAllIPSuccess"]); 33 | } 34 | } 35 | } 36 | 37 | else { 38 | 39 | if ($q2 == "restoreuser") { 40 | $db->query("UPDATE users SET deleted=0 WHERE userid='" . $db->real_escape_string($q3) . "'"); 41 | } 42 | 43 | // Start off by making a query for our list. 44 | $ip = $db->query("SELECT ip, username, deleted FROM users WHERE userid='" . $db->real_escape_string($q3) . "'"); 45 | while ($r = $ip->fetch_assoc()) { 46 | $deleted = $r["deleted"]; 47 | $name = $r["username"]; 48 | $result = $db->query("SELECT * FROM users WHERE ip='" . $r["ip"] . "' AND NOT userid='" . $db->real_escape_string($q3) . "'"); 49 | } 50 | 51 | echo '
    '; 52 | echo '

    '. sprintf($lang["panel.sameIP"], $name) .'

    '; 53 | 54 | if($result->num_rows == 0) 55 | { 56 | message($lang["panel.noSameIP"]); 57 | } 58 | else { 59 | echo "
    "; 60 | while($row = $result->fetch_assoc()) 61 | { 62 | $role = $lang["role." . $row["role"]]; 63 | if ($row["deleted"] == "1") $deletedClass = " deleteduser"; 64 | else $deletedClass = ""; 65 | 66 | if ($row["deleted"] == "1") { 67 | $username = $lang["user.Deleted"] . $row["userid"]; 68 | } 69 | else { 70 | $username = $row["username"]; 71 | } 72 | 73 | echo '
    ' . htmlspecialchars($username) . '  ' . $role . '  '; 74 | if (($config["mainAdmin"] != $row["userid"])) { 75 | echo '' . $lang["panel.Administrate"] . '  '; 76 | } 77 | echo '
    ' . parseAction($row["lastaction"], $lang) . ' (' . relativeTime($row["lastactive"]) . ')
    '; 78 | } 79 | 80 | echo "
    "; 81 | } 82 | 83 | echo '
    '; 84 | echo '

    '. $lang["panel.DangerZone"] .'

    '; 85 | if (($config["mainAdmin"] != $row["userid"]) and ($deleted != "1")) { 86 | echo($lang["panel.DeleteUserMessage"] . "



    " . "
    "); 87 | } 88 | elseif ($deleted == "1") { 89 | echo '' . $lang["panel.RestoreUser"] . '  '; 90 | } 91 | 92 | } 93 | 94 | ?> 95 | -------------------------------------------------------------------------------- /pages/homepage.page.php: -------------------------------------------------------------------------------- 1 | $lang["homepage.Title"], 12 | "th_category" => $lang["homepage.Cats"], 13 | "th_threads" => $lang["homepage.CatThreads"], 14 | "th_lastpost" => $lang["category.LastPost"], 15 | "categories" => "", 16 | "th_recentthreads" => $lang["homepage.Threads"], 17 | "th_posts" => $lang["category.Posts"], 18 | "threads" => "", 19 | ); 20 | 21 | $categories = $db->query("SELECT * FROM `categories` ORDER BY `order` ASC"); 22 | $threads = $db->query("SELECT * FROM threads WHERE draft='0' ORDER BY lastposttime DESC LIMIT 5"); 23 | 24 | while($row = $categories->fetch_assoc()) 25 | { 26 | $numthreads = $db->query("SELECT * FROM threads WHERE draft='0' AND category='" . $row["categoryid"] . "' ORDER BY lastposttime DESC"); 27 | $trow = $numthreads->fetch_assoc(); 28 | $title = ""; 29 | $user = ""; 30 | if ($numthreads->num_rows > 0) { 31 | $uinfo = $db->query("SELECT * FROM users WHERE userid='" . $trow["lastpostuser"] . "'"); 32 | $title = htmlspecialchars($trow['title']); 33 | $u = $uinfo->fetch_assoc(); 34 | if ($u["deleted"] == 1) $username = $lang["user.Deleted"] . $u["userid"]; 35 | else $username = $u["username"]; 36 | if ($trow["posts"] > 1) $title = sprintf($lang["category.ReplyTo"], $title); 37 | $user = sprintf("" .$lang["thread.Info"] . "", $u["role"], genURL("user/" . htmlspecialchars($trow["lastpostuser"])), htmlspecialchars($username), date('m-d-Y h:i:s A', $trow['lastposttime']), relativeTime($trow["lastposttime"])); 38 | } 39 | 40 | $category_data = array 41 | ( 42 | "url" => genURL("category/" . $row["categoryid"]), 43 | "title" => htmlspecialchars($row["categoryname"]), 44 | "desc" => formatPost($row["categorydescription"]), 45 | "threads" => $numthreads->num_rows, 46 | "lastpost" => $title, 47 | "lastposturl" => !isset($trow['threadid']) ?: genURL('thread/' . $trow['threadid']), 48 | "user" => $user, 49 | ); 50 | 51 | $data["categories"] .= $template->render("templates/category/category_display.html", $category_data); 52 | } 53 | 54 | while($row = $threads->fetch_assoc()) 55 | { 56 | $suinfo = $db->query("SELECT * FROM users WHERE userid='" . $row["startuser"] . "'"); 57 | $su = $suinfo->fetch_assoc(); 58 | if ($su["deleted"] == 1) $susername = $lang["user.Deleted"] . $su["userid"]; 59 | else $susername = $su["username"]; 60 | 61 | $uinfo = $db->query("SELECT * FROM users WHERE userid='" . $row["lastpostuser"] . "'"); 62 | $u = $uinfo->fetch_assoc(); 63 | if ($u["deleted"] == 1) $username = $lang["user.Deleted"] . $u["userid"]; 64 | else $username = $u["username"]; 65 | 66 | $thread_data = array 67 | ( 68 | "labels" => "", 69 | "url" => genURL('thread/' . $row['threadid']), 70 | "title" => htmlspecialchars($row['title']), 71 | "startuser" => sprintf("" .$lang["thread.Info"] . "", $su["role"], genURL("user/" . htmlspecialchars($row["startuser"])), htmlspecialchars($susername), date('m-d-Y h:i:s A', $row['starttime']), relativeTime($row["starttime"])), 72 | "posts" => $row['posts'], 73 | "user" => '' . htmlspecialchars($username) . '', 74 | "date" => date('m-d-Y h:i:s A', $row['lastposttime']), 75 | "reldate" => relativeTime($row["lastposttime"]), 76 | ); 77 | $labels = array(); 78 | if ($row["locked"] == true) $labels["locked"] = $lang["label.Locked"]; 79 | if ($row["sticky"] == true) $labels["sticky"] = $lang["label.Sticky"]; 80 | if ($row["draft"] == true) $labels["draft"] = $lang["label.Draft"]; 81 | if ($row["pinned"] == true) $labels["pinned"] = $lang["label.Pinned"]; 82 | listener("beforeRenderThreadLabels",$labels); 83 | foreach ($labels as $k => $v) { 84 | $label_data = array("text" => $v, "class" => $k); 85 | $thread_data["labels"] .= $template->render("templates/thread/label.html",$label_data); 86 | } 87 | $data["threads"] .= $template->render("templates/thread/thread_display.html", $thread_data); 88 | } 89 | if ($threads->num_rows == 0) $data["threads"] = $template->render("templates/thread/thread_display_blank.html", array("title" => $lang["error.ForumEmpty"])); 90 | 91 | echo $template->render("templates/homepage/homepage.html", $data); 92 | 93 | include 'footer.php'; 94 | 95 | update_last_action("action.Homepage"); 96 | 97 | ?> 98 | -------------------------------------------------------------------------------- /pages/header.php: -------------------------------------------------------------------------------- 1 | array($lang["header.Home"], genURL(""), 0), 10 | "userlist" => array($lang["header.Userlist"], genURL("userlist"), 0), 11 | "userpanel" => array($lang["header.UserPanel"], genURL("userpanel"), 1), 12 | "newthread" => array($lang["header.NewThread"], genURL("newthread"), 1), 13 | "panel" => array($lang["header.Panel"], genURL("panel"), 4), 14 | "logout" => array($lang["header.Logout"], genURL("logout"), 1), 15 | ); 16 | 17 | if (isset($categoryID)) $m_pages["newthread"][1] = genURL('newthread/' . $categoryID); 18 | if (isset($_GET['url']) && strlen($_GET['url']) > 0) { 19 | $login_redirect = "?next=" . ltrim($_GET['url'], '/'); 20 | } 21 | 22 | if (!isset($login_redirect)) $login_redirect = ""; 23 | 24 | $data = array( 25 | "locale" => str_replace("_", "-", $lang["locale"]), 26 | "search" => genURL("assets/search.js"), 27 | "title" => (empty($lang["page." . $q1])) ? $config["forumName"] : $lang["page." . $q1] . ' • ' . $config["forumName"], 28 | "stylesheet" => genURL('themes/' . $config["forumTheme"] . '/style.css?v=0.1'), 29 | "favicon" => genURL('themes/' . $config["forumTheme"] . '/icon.ico'), 30 | "favicon_svg" => genURL('themes/' . $config["forumTheme"] . '/icon.svg'), 31 | "favicon_png" => genURL('themes/' . $config["forumTheme"] . '/icon.png'), 32 | "pages" => "", 33 | "welcome" => sprintf($lang["header.Welcome"],genURL("login" . $login_redirect),genURL("signup")), 34 | "homeURL" => genURL(""), 35 | "searchText" => "", 36 | "searchPlaceholder" => $lang["search.Placeholder"], 37 | "searchButton" => $lang["search.Button"], 38 | "meta" => "", 39 | "color" => "", 40 | "keywords" => strtolower($config["forumName"]), 41 | "navigation" => drawNavigation(), 42 | "header" => $template->render("templates/header/title.html", null), 43 | ); 44 | 45 | if ($config["forumColor"] != null) 46 | { 47 | $grTop = hexAdjustLight($config["forumColor"], 0.9); 48 | $grMedium = hexAdjustLight($config["forumColor"], 1); 49 | $grBottom = hexAdjustLight($config["forumColor"], -0.4); 50 | $grBottomDarker = hexAdjustLight($config["forumColor"], -0.6); 51 | $grHighlight = hexAdjustLight($config["forumColor"], 0.4); 52 | $grBorder = hexAdjustLight($config["forumColor"], -0.8); 53 | $data["color"] = ""; 63 | } 64 | 65 | $files = scandir("assets/"); 66 | $matches = preg_grep("/forumLogo\.(png|jpg|svg|gif)/i", $files); 67 | sort($matches); 68 | 69 | if (isset($matches[0])) 70 | { 71 | $data["header"] = $template->render("templates/header/title_img.html", array("url" => genURL("assets/" . $matches[0]))); 72 | } 73 | 74 | ob_start(); 75 | listener("meta"); 76 | $data["meta"] = ob_get_contents(); 77 | ob_end_clean(); 78 | 79 | if (isset($_GET["search"]) && !empty($_GET["search"])) { 80 | $data["searchText"] = htmlspecialchars(urldecode($_GET["search"])); 81 | } 82 | 83 | if (isset($_SESSION['signed_in']) && $_SESSION['signed_in'] == true) 84 | { 85 | $data["welcome"] = sprintf($lang["header.Hello"], '' . htmlspecialchars($_SESSION["username"]) . ''); 86 | } 87 | 88 | if (($q1 == "thread") and isset($title)) 89 | { 90 | if (($draft == 0) or ($_SESSION["userid"] == $startuser) or (($_SESSION["role"] == "Moderator") or ($_SESSION["role"] == "Administrator"))) { 91 | $data["title"] = htmlspecialchars($title) . ' • ' . $config["forumName"]; 92 | } 93 | } 94 | else if ($q1 == "category" && isset($categoryName)) $data["title"] = htmlspecialchars($categoryName) . ' • ' . $config["forumName"]; 95 | else if ($q1 == "user" && isset($username)) $data["title"] = htmlspecialchars($username) . ' • ' . $config["forumName"]; 96 | else if (($q1 == "panel" || $q1 == "userpanel") && array_key_exists($q2,$panel_pages) && strlen($panel_pages[$q2][1])) $data["title"] = $panel_pages[$q2][1] . ' • ' . $config["forumName"]; 97 | 98 | foreach ($m_pages as $v) { 99 | if (getNumForRole(@$_SESSION["role"]) >= $v[2]) { 100 | $p_data = array( 101 | "label" => $v[0], 102 | "url" => $v[1] 103 | ); 104 | $data["pages"] = $data["pages"] . $template->render("templates/header/menu_page.html", $p_data); 105 | } 106 | } 107 | 108 | echo $template->render("templates/header/header.html", $data); 109 | 110 | ?> 111 | -------------------------------------------------------------------------------- /pages/userpanelaccountsettings.page.php: -------------------------------------------------------------------------------- 1 | query("SELECT password FROM users WHERE username = '" . $db->real_escape_string($_SESSION['username']) . "'"); 11 | if(!$res) { 12 | $errors[] = $lang["error.Database"]; 13 | } 14 | while($row = $res->fetch_assoc()) { 15 | $password = $row["password"]; 16 | } 17 | $hash = hashstring($salt . $_POST["confirmpass"]); 18 | $errors = array(); 19 | if (isset($_POST["newusername"])) { 20 | $newusername = $_POST["newusername"]; 21 | if (!isset($newusername)) { 22 | $errors[] = $lang["settings.NewUsernameEmpty"]; 23 | } 24 | elseif (!isset($_POST["confirmpass"])) { 25 | $errors[] = $lang["settings.PasswordEmpty"]; 26 | } 27 | elseif ($newusername == $_SESSION["username"]) { 28 | $errors[] = $lang["settings.NewUsernameSame"]; 29 | } 30 | elseif (strlen($newusername) > 24) { 31 | $errors[] = $lang["settings.NewUsernameBig"]; 32 | } 33 | elseif (!checkUsername($newusername)) { 34 | $errors[] = $lang["settings.NewUsernameNonAlph"]; 35 | } 36 | elseif (!password_verify($_POST["confirmpass"], $password)) { 37 | $errors[] = $lang["error.PasswordWrong"]; 38 | } 39 | else { 40 | $result = $db->query("UPDATE users SET username='" . $db->real_escape_string($_POST["newusername"]) . "' WHERE userid='" . $_SESSION["userid"] . "'"); 41 | if (!$result) { 42 | message($lang["settings.NewUsernameError"]); 43 | } 44 | else { 45 | $_SESSION["username"] = $_POST["newusername"]; 46 | message($lang["settings.NewUsernameChanged"]); 47 | include "footer.php"; 48 | refresh(1.5); 49 | exit; 50 | } 51 | } 52 | } 53 | 54 | if (isset($_POST["newpass"])) { 55 | $newpass = $_POST["newpass"]; 56 | $confirmnewpass = $_POST["confirmnewpass"]; 57 | if(empty($newpass)) { 58 | $errors[] = $lang["settings.NewPasswordEmpty"]; 59 | } 60 | elseif (empty($confirmnewpass)) { 61 | $errors[] = $lang["settings.ConfirmNewPasswordEmpty"]; 62 | } 63 | elseif (empty($_POST["oldpass"])) { 64 | $errors[] = $lang["settings.OldPasswordEmpty"]; 65 | } 66 | elseif ($newpass != $confirmnewpass) { 67 | $errors[] = $lang["settings.ConfirmNewPasswordError"]; 68 | } 69 | elseif (!password_verify($_POST["oldpass"], $password)) { 70 | $errors[] = $lang["error.PasswordWrong"]; 71 | } 72 | else { 73 | $salt = ""; 74 | $password = password_hash($_POST["newpass"], PASSWORD_DEFAULT); 75 | $result = $db->query("UPDATE users SET password ='" . $db->real_escape_string($password) . "', salt = '" . $db->real_escape_string($salt) . "' WHERE userid='" . $_SESSION["userid"] . "'"); 76 | if (!$result) { 77 | message($lang["settings.ChangePasswordError"]); 78 | } 79 | else { 80 | message($lang["settings.ChangePasswordChanged"]); 81 | include "footer.php"; 82 | refresh(1.5); 83 | exit; 84 | } 85 | } 86 | } 87 | 88 | if(!empty($errors)) { 89 | echo $lang["error.BadFields"]; 90 | echo ''; 95 | echo ''.$lang["error.GoBack"].''; 96 | include "footer.php"; 97 | exit; 98 | } 99 | } 100 | 101 | // Display the change username form. 102 | echo '

    '.$lang["settings.ChangeUsername"].'

    103 |
    104 |
    105 |
    106 |
    '; 107 | 108 | // Display the change password form. 109 | echo '

    '.$lang["settings.ChangePassword"].'

    110 |
    111 |
    112 |
    113 |
    114 |
    '; 115 | 116 | // If the viewing user is logged in, update their last action. 117 | if ($_SESSION['signed_in'] == true) 118 | { 119 | update_last_action($lang["action.AccountSettings"]); 120 | } 121 | 122 | ?> 123 | -------------------------------------------------------------------------------- /themes/Midnight/style.css: -------------------------------------------------------------------------------- 1 | @import url("../Aurora/style.css"); 2 | 3 | /* Base Styles. */ 4 | :root { 5 | --c-gradient-top: #7e79c4; 6 | --c-gradient-medium: #585b91; 7 | --c-gradient-bottom: #464a82; 8 | --c-gradient-bottom-darker: #3b3d62; 9 | --c-highlight: #8588ae; 10 | --c-border: #464a82; 11 | 12 | --slate: #2b3235; 13 | 14 | --input: #fff; 15 | --input-text: #000; 16 | 17 | --bg-primary: #131313; 18 | --bg-secondary: #1e1e1e; 19 | --bg-tertiary: #151515; 20 | 21 | --border-primary: #333; 22 | --border-secondary: #333; 23 | 24 | --text-light: #aaa; 25 | --text-medium: #ddd; 26 | --text-heavy: #fff; 27 | 28 | --button-g-top: #7b7b7b; 29 | --button-g-bottom: #000; 30 | 31 | --input-border: #444; 32 | --input-border-bold: #444; 33 | 34 | --button-text: #fff; 35 | --button-text-disabled: #ccc; 36 | 37 | --widget-g-top: #4b4b4b; 38 | --widget-g-bottom: #000; 39 | --widget-border: #555; 40 | --widget-highlight: #000; 41 | 42 | accent-color: var(--c-gradient-bottom); 43 | } 44 | 45 | body { 46 | background: linear-gradient(var(--c-gradient-bottom-darker), var(--bg-tertiary) 80px); 47 | background-repeat: no-repeat; 48 | background-color: var(--bg-tertiary); 49 | } 50 | a { 51 | color: #64ccff; 52 | } 53 | 54 | .Member { 55 | color: #fff; 56 | } 57 | 58 | .Administrator { 59 | color: #5fc; 60 | } 61 | 62 | .Moderator { 63 | color: #3bf; 64 | } 65 | 66 | .Suspended { 67 | color: #ddd; 68 | } 69 | 70 | #userbar .Administrator { 71 | color: #004f31; 72 | } 73 | #userbar .Moderator { 74 | color: #003c7b; 75 | } 76 | #userbar .Member { 77 | color: #000; 78 | } 79 | #userbar a { 80 | color: #00529b; 81 | } 82 | 83 | 84 | #menu { 85 | border: 1px solid #626b6f; 86 | } 87 | 88 | td { 89 | border-bottom: 1px solid #ffffff26; 90 | border-right: 1px solid #ffffff26; 91 | } 92 | tr:nth-child(2n) { 93 | background: none; 94 | } 95 | 96 | .postc button { 97 | border: 1px solid rgba(255, 255, 255, 0.2); 98 | } 99 | 100 | input:focus { 101 | background: var(--button-g-bottom); 102 | } 103 | 104 | .message { 105 | background: linear-gradient(#4a5269, #656c81); 106 | box-shadow: 0px 1px inset #727b97; 107 | text-shadow: 0 1px #3a3f4e; 108 | border: 1px solid #3a4050; 109 | color: #fff; 110 | } 111 | 112 | .postcode { 113 | background: #222; 114 | box-shadow: 0px 1px inset #2b2b2b; 115 | border: 1px solid rgb(26, 26, 26); 116 | border-bottom-width: 2px; 117 | color: #4d8fc1; 118 | } 119 | 120 | .message a { 121 | color: #7cf0fc; 122 | text-decoration: none; 123 | } 124 | 125 | .threadbutton { 126 | background-image: linear-gradient(#9d9d9dad 0%, #84848421 50%, #0000005e 50%, #35353533 100%); 127 | border: 1px solid var(--c-gradient-bottom); 128 | } 129 | .searchbutton { 130 | background-image: linear-gradient(#9d9d9dad 0%, #84848421 50%, #0000005e 50%, #35353533 100%); 131 | } 132 | .paginationdots { 133 | background: linear-gradient(#444,#111); 134 | color: var(--text-medium); 135 | } 136 | #forumheader { 137 | background-image: linear-gradient(#9d9d9dad 0%, #84848421 50%, #0000005e 50%, #35353533 100%); 138 | box-shadow: none; 139 | } 140 | th { 141 | background-image: linear-gradient(#9d9d9dad 0%, #84848421 50%, #0000005e 50%, #35353533 100%); 142 | } 143 | .thread, .usertop, .userlist-top { 144 | background-image: linear-gradient(#ffffff17, #fff0); 145 | border: none; 146 | box-shadow: none; 147 | } 148 | .threadcontent, .userbottom { 149 | border: 1px solid rgba(255, 255, 255, 0.1); 150 | box-shadow: none; 151 | border-left: none; 152 | text-shadow: none; 153 | } 154 | #editthread { 155 | text-decoration-color: var(--text-light); 156 | } 157 | .postquote { 158 | background-color: rgba(255, 255, 255, 0.05); 159 | } 160 | .userextra { 161 | border: none; 162 | box-shadow: none; 163 | } 164 | @media (max-width: 800px) { 165 | .threadcontent, 166 | .userbottom { 167 | border-left: 1px solid rgba(255, 255, 255, 0.1); 168 | } 169 | } 170 | 171 | [postcolor="1"] { 172 | background-color: #21434f; 173 | } 174 | 175 | [postcolor="2"] { 176 | background-color: #104610; 177 | } 178 | 179 | [postcolor="3"] { 180 | background-color: #866500; 181 | } 182 | 183 | [postcolor="4"] { 184 | background-color: rgb(145, 0, 0); 185 | } 186 | 187 | [postcolor="5"] { 188 | background-color: #75003a; 189 | } 190 | 191 | [postcolor="6"] { 192 | background-color: rgb(48, 16, 111); 193 | } 194 | 195 | [postcolor="7"] { 196 | background-color: rgb(138, 50, 19); 197 | } 198 | 199 | [postcolor="8"] { 200 | background-color: rgb(45, 69, 115); 201 | } 202 | 203 | [postcolor="9"] { 204 | background-color: #222239; 205 | } 206 | 207 | [postcolor="10"] { 208 | background-color: rgb(49, 42, 38); 209 | } 210 | 211 | [postcolor="11"] { 212 | background-color: #806533; 213 | } 214 | 215 | [postcolor="12"] { 216 | background-color: rgb(87, 62, 40); 217 | } 218 | 219 | [postcolor="13"] { 220 | background-color: rgb(26, 108, 63); 221 | } 222 | 223 | [postcolor="14"] { 224 | background-color: rgb(145, 81, 0); 225 | } 226 | 227 | [postcolor="15"] { 228 | background-color: #550f55; 229 | } 230 | 231 | [postcolor="16"] { 232 | background-color: #222324; 233 | } 234 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | "upgrade/upgrade.page.php", 12 | "signup" => "pages/signup.page.php", 13 | "register" => "pages/signup.page.php", 14 | "login" => "pages/login.page.php", 15 | "newthread" => "pages/newthread.page.php", 16 | "category" => "pages/category.page.php", 17 | "thread" => "pages/thread.page.php", 18 | "userlist" => "pages/userlist.page.php", 19 | "user" => "pages/user.page.php", 20 | "userpanel" => "pages/userpanel.page.php", 21 | "panel" => "pages/panel.page.php", 22 | "search" => "pages/search.page.php", 23 | "post" => "pages/post.page.php" 24 | ); 25 | $functionPages = array( 26 | "logout" => "logout", 27 | ); 28 | $fallbackPage = "pages/homepage.page.php"; 29 | 30 | // Require all the necessary files for the forum to function. 31 | require "libs/functions.php"; 32 | 33 | // Config handling, stop your config from being overwritten on upgrade 34 | if (file_exists("config/config-setup.php")) { 35 | require "config/config-setup.php"; 36 | } 37 | 38 | if (file_exists("config/config.php")) { 39 | require "config/config.php"; 40 | } 41 | else { 42 | saveConfig("config/config.php", $config); 43 | } 44 | 45 | // Now that we have the config, connect to the MySQL database if the forum is installed. 46 | if ($config["installed"] == "yes") { 47 | $db = mysqli_connect($config["MySQLServer"], $config["MySQLUser"], $config["MySQLPass"], $config["MySQLDatabase"]); 48 | } 49 | 50 | // Load up the formatter. 51 | require "libs/formatter.php"; 52 | require "libs/permission.php"; 53 | 54 | // Extensions config 55 | if (file_exists("config/extensions.php")) { 56 | require "config/extensions.php"; 57 | } 58 | else { 59 | if (file_exists("config/extensions-default.php")) { 60 | require "config/extensions-default.php"; 61 | } 62 | saveExtensionConfig("config/extensions.php", $extensions); 63 | } 64 | 65 | // Check for malformed baseURLs. 66 | $config["baseURL"] = rtrim($config["baseURL"], '/'); 67 | 68 | // Get our language file 69 | require 'lang/EN_US.php'; 70 | $lang_compat = $lang; 71 | unset($lang); 72 | if(is_null($config["forumLang"]) or !isset($config["forumLang"]) or !file_exists("lang/" . $config["forumLang"] . ".php")) 73 | { 74 | require 'lang/EN_US.php'; 75 | } 76 | else 77 | { 78 | require 'lang/' . $config["forumLang"] . '.php'; 79 | } 80 | 81 | foreach($lang_compat as $k => $v) { 82 | if (!array_key_exists($k, $lang)) { 83 | $lang[$k] = "Missing: '" . $k . "'"; 84 | } 85 | } 86 | 87 | // If a session doesn't exist, set one. 88 | if (!session_id()) { 89 | session_name($config["cookieName"] . "_Session"); 90 | session_start(); 91 | } 92 | 93 | // Check the user's role, verification status, and deletion status. Then ensure their session reflects it accordingly. 94 | if ($config['installed'] != "no" && isset($_SESSION["signed_in"]) && $_SESSION["signed_in"] == true) { 95 | $rolecheck = $db->query("SELECT role, verified, deleted, ip FROM users WHERE userid='" . $_SESSION["userid"] . "'"); 96 | while ($r = $rolecheck->fetch_assoc()) 97 | { 98 | // Prevent session stealing, log the user out if their IP is different from the one they logged in with. 99 | if (hashstring($_SERVER["REMOTE_ADDR"]) != $r["ip"]) { 100 | logout(); 101 | } 102 | if ($r["role"] != $_SESSION["role"]) { 103 | $_SESSION["role"] = $r["role"]; 104 | } 105 | if (isset($_SESSION["verified"]) && ($r["verified"] != $_SESSION["verified"])) { 106 | $_SESSION["verified"] = $r["verified"]; 107 | } 108 | if (isset($_SESSION["deleted"]) && ($r["deleted"] != $_SESSION["deleted"])) { 109 | $_SESSION["deleted"] = $r["deleted"]; 110 | } 111 | } 112 | // Log out any suspended, unverified, or deleted users. 113 | if (($_SESSION["role"] == "Suspended") 114 | or (isset($_SESSION["verified"]) && $_SESSION["verified"] == "0") 115 | or (isset($_SESSION["deleted"]) && $_SESSION["deleted"] == "1")) { 116 | logout(); 117 | } 118 | } 119 | 120 | require "libs/language.php"; 121 | 122 | // Process the URL and set a couple of variables for easy use. 123 | if (isset($_GET['url'])) $url = explode('/', $_GET['url']); 124 | $q1 = $q2 = $q3 = $q4 = ""; 125 | if (isset($url[0])) $q1 = $url[0]; 126 | if (isset($url[1])) $q2 = $url[1]; 127 | if (isset($url[2])) $q3 = $url[2]; 128 | if (isset($url[3])) $q4 = $url[3]; 129 | 130 | require "libs/templates.php"; 131 | require "libs/extensions.php"; 132 | 133 | listener("beforePageLoad"); 134 | 135 | // Based on the URL, serve the user with a corresponding page. 136 | if ($config['installed'] != "yes") require "install/install.php"; 137 | elseif (isset($pages[$q1])) require $pages[$q1]; 138 | elseif (isset($functionPages[$q1])) call_user_func($functionPages[$q1]); 139 | elseif (!$q1) require $fallbackPage; 140 | else { 141 | http_response_code(404); 142 | include "pages/header.php"; 143 | $data = array("title" => $lang["error.SomethingWentWrong"], "message" => message($lang["error.PageNotFound"],true), "back" => $lang["error.GoBack"]); 144 | echo $template->render("templates/fatal.html", $data); 145 | include "pages/footer.php"; 146 | } 147 | 148 | listener("afterPageLoad"); 149 | 150 | ?> 151 | -------------------------------------------------------------------------------- /pages/category.page.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM categories WHERE categoryid='" . $db->real_escape_string($q2) . "'"); 9 | 10 | if (isset($q3) && is_numeric($q3)) 11 | { 12 | $currentPage = $q3; 13 | } 14 | else 15 | { 16 | $currentPage = 1; 17 | } 18 | 19 | while ($row = $category->fetch_assoc()) 20 | { 21 | $categoryName = $row["categoryname"]; 22 | $categoryID = $db->real_escape_string($q2); 23 | $category_data = array( 24 | "title" => htmlspecialchars($row["categoryname"]), 25 | "desc" => formatPost($row["categorydescription"]), 26 | "pagination" => "", 27 | "threads" => "", 28 | "th_thread" => $lang["category.Thread"], 29 | "th_posts" => $lang["category.Posts"], 30 | "th_lastpost" => $lang["category.LastPost"], 31 | ); 32 | } 33 | 34 | include "header.php"; 35 | 36 | $thread_count = $db->query("SELECT 1 FROM threads WHERE category='" . $db->real_escape_string($q2) . "'"); 37 | 38 | // Important details for sorting the threads into pages. 39 | $threadsPerPage = (is_numeric($config["threadsPerPage"]) ? (int)$config["threadsPerPage"] : 20); 40 | if ($threadsPerPage < 1) $threadsPerPage = 1; 41 | $numThreads = $thread_count->num_rows; 42 | if ($numThreads < 1) $numThreads = 1; 43 | $pages = ceil($numThreads / $threadsPerPage); 44 | 45 | // Calculate the offset for the threads query. 46 | $offset = (($currentPage * $threadsPerPage) - $threadsPerPage); 47 | 48 | if (!isset($_SESSION["signed_in"]) || $_SESSION["signed_in"] != true) { 49 | $threads = $db->query("SELECT * FROM threads WHERE category='" . $db->real_escape_string($q2) . "' AND draft='0' UNION SELECT * FROM threads WHERE pinned='1' AND draft='0' ORDER BY pinned DESC, sticky DESC, lastposttime DESC LIMIT " . $threadsPerPage . " OFFSET " . $offset . ""); 50 | } 51 | else if (($_SESSION["role"] == "Moderator") or ($_SESSION["role"] == "Administrator")) { 52 | $threads = $db->query("SELECT * FROM threads WHERE category='" . $db->real_escape_string($q2) . "' UNION SELECT * FROM threads WHERE pinned='1' ORDER BY pinned DESC, sticky DESC, lastposttime DESC LIMIT " . $threadsPerPage . " OFFSET " . $offset . ""); 53 | } 54 | else { 55 | $threads = $db->query("SELECT * FROM threads WHERE category='" . $db->real_escape_string($q2) . "' AND draft='0' OR (draft='1' AND startuser='" . $_SESSION["userid"] . "') UNION SELECT * FROM threads WHERE pinned='1' AND draft='0' OR (draft='1' AND startuser='" . $_SESSION["userid"] . "') ORDER BY pinned DESC, sticky DESC, lastposttime DESC LIMIT " . $threadsPerPage . " OFFSET " . $offset . ""); 56 | } 57 | 58 | if (!$category) 59 | { 60 | message($lang["error.CategoryMisc"]); 61 | include 'footer.php'; 62 | exit; 63 | } 64 | else if ($category->num_rows == 0) 65 | { 66 | message($lang["error.CategoryNotFound"]); 67 | include 'footer.php'; 68 | exit; 69 | } 70 | 71 | while($row = $threads->fetch_assoc()) 72 | { 73 | $suinfo = $db->query("SELECT * FROM users WHERE userid='" . $row["startuser"] . "'"); 74 | $su = $suinfo->fetch_assoc(); 75 | if ($su["deleted"] == 1) $susername = $lang["user.Deleted"] . $su["userid"]; 76 | else $susername = $su["username"]; 77 | 78 | $uinfo = $db->query("SELECT * FROM users WHERE userid='" . $row["lastpostuser"] . "'"); 79 | $u = $uinfo->fetch_assoc(); 80 | if ($u["deleted"] == 1) $username = $lang["user.Deleted"] . $u["userid"]; 81 | else $username = $u["username"]; 82 | 83 | $thread_data = array 84 | ( 85 | "labels" => "", 86 | "url" => genURL('thread/' . $row['threadid']), 87 | "title" => htmlspecialchars($row['title']), 88 | "startuser" => sprintf("" .$lang["thread.Info"] . "", $su["role"], genURL("user/" . htmlspecialchars($row["startuser"])), htmlspecialchars($susername), date('m-d-Y h:i:s A', $row['starttime']), relativeTime($row["starttime"])), 89 | "posts" => $row['posts'], 90 | "user" => '' . htmlspecialchars($username) . '', 91 | "date" => date('m-d-Y h:i:s A', $row['lastposttime']), 92 | "reldate" => relativeTime($row["lastposttime"]), 93 | ); 94 | $labels = array(); 95 | if ($row["locked"] == true) $labels["locked"] = $lang["label.Locked"]; 96 | if ($row["sticky"] == true) $labels["sticky"] = $lang["label.Sticky"]; 97 | if ($row["draft"] == true) $labels["draft"] = $lang["label.Draft"]; 98 | if ($row["pinned"] == true) $labels["pinned"] = $lang["label.Pinned"]; 99 | listener("beforeRenderThreadLabels",$labels); 100 | foreach ($labels as $k => $v) { 101 | $label_data = array("text" => $v, "class" => $k); 102 | $thread_data["labels"] .= $template->render("templates/thread/label.html",$label_data); 103 | } 104 | $category_data["threads"] .= $template->render("templates/thread/thread_display.html", $thread_data); 105 | } 106 | 107 | $category_data["pagination"] = pagination_return("category"); 108 | 109 | if ($threads->num_rows == 0) $category_data["threads"] = $template->render("templates/thread/thread_display_blank.html", array("title" => $lang["error.CategoryEmpty"])); 110 | 111 | echo $template->render("templates/category/category_page.html", $category_data); 112 | 113 | include 'footer.php'; 114 | -------------------------------------------------------------------------------- /upgrade/upgrade.page.php: -------------------------------------------------------------------------------- 1 | query("SHOW COLUMNS FROM `users` WHERE field LIKE 'deleted'"); 11 | $usersignature = $db->query("SHOW COLUMNS FROM `users` WHERE field LIKE 'signature'"); 12 | $userbio = $db->query("SHOW COLUMNS FROM `users` WHERE field LIKE 'bio'"); 13 | $userpassword = $db->query("SHOW COLUMNS FROM `users` WHERE field LIKE 'password' AND type LIKE 'varchar(128)'"); 14 | $userip = $db->query("SHOW COLUMNS FROM `users` WHERE field LIKE 'ip' AND type LIKE 'varchar(128)'"); 15 | $usersalt = $db->query("SHOW COLUMNS FROM `users` WHERE field LIKE 'salt' AND type LIKE 'char(64)'"); 16 | $useravatar = $db->query("SHOW COLUMNS FROM `users` WHERE field LIKE 'avatar'"); 17 | $useravatartime = $db->query("SHOW COLUMNS FROM `users` WHERE field LIKE 'avataruploadtime'"); 18 | $logins = $db->query("SHOW TABLES LIKE 'logins'"); 19 | $drafts = $db->query("SHOW TABLES LIKE 'drafts'"); 20 | $draft = $db->query("SHOW COLUMNS FROM `threads` WHERE field LIKE 'draft'"); 21 | $auditlog = $db->query("SHOW TABLES LIKE 'auditlog'"); 22 | $pinned = $db->query("SHOW COLUMNS FROM `threads` WHERE field LIKE 'pinned'"); 23 | $order = $db->query("SHOW COLUMNS FROM `categories` WHERE field LIKE 'order'"); 24 | $category_perms = $db->query("SHOW COLUMNS FROM `categories` WHERE field LIKE 'permissions'"); 25 | 26 | 27 | if ($category_perms->num_rows < 1) 28 | { 29 | $db->query("ALTER TABLE `categories` ADD `permissions` text DEFAULT NULL"); 30 | $upgraded = true; 31 | } 32 | if ($deleteduser->num_rows < 1) 33 | { 34 | $db->query("ALTER TABLE `users` ADD `deleted` tinyint(1) NOT NULL DEFAULT '0'"); 35 | $upgraded = true; 36 | } 37 | if ($usersignature->num_rows < 1) 38 | { 39 | $db->query("ALTER TABLE `users` ADD `signature` varchar(512) DEFAULT NULL"); 40 | $upgraded = true; 41 | } 42 | if ($userbio->num_rows < 1) 43 | { 44 | $db->query("ALTER TABLE `users` ADD `bio` varchar(2048) DEFAULT NULL"); 45 | $upgraded = true; 46 | } 47 | if ($userpassword->num_rows < 1) 48 | { 49 | $db->query("ALTER TABLE `users` MODIFY `password` varchar(128) NOT NULL"); 50 | $upgraded = true; 51 | } 52 | if ($userip->num_rows < 1) 53 | { 54 | $db->query("ALTER TABLE `users` MODIFY `ip` varchar(128) NOT NULL"); 55 | $upgraded = true; 56 | } 57 | if ($usersalt->num_rows < 1) 58 | { 59 | $db->query("ALTER TABLE `users` MODIFY `salt` char(64) NOT NULL"); 60 | $upgraded = true; 61 | } 62 | if ($useravatar->num_rows < 1) 63 | { 64 | $db->query("ALTER TABLE `users` ADD `avatar` enum('none', 'png', 'jpg', 'gif') NOT NULL DEFAULT 'none'"); 65 | $upgraded = true; 66 | } 67 | if ($useravatartime->num_rows < 1) 68 | { 69 | $db->query("ALTER TABLE `users` ADD `avataruploadtime` int unsigned DEFAULT NULL"); 70 | $upgraded = true; 71 | } 72 | if ($logins->num_rows < 1) 73 | { 74 | $db->query("CREATE TABLE `logins` ( 75 | `ip` varchar(128) NOT NULL, 76 | `time` int unsigned NOT NULL 77 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;"); 78 | $upgraded = true; 79 | } 80 | if ($drafts->num_rows < 1) 81 | { 82 | $db->query("CREATE TABLE `drafts` ( 83 | `user` int unsigned NOT NULL, 84 | `thread` int unsigned NOT NULL, 85 | `timestamp` int unsigned NOT NULL, 86 | `content` text NOT NULL 87 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;"); 88 | $upgraded = true; 89 | } 90 | if ($draft->num_rows < 1) 91 | { 92 | $db->query("ALTER TABLE `threads` ADD `draft` tinyint(1) NOT NULL DEFAULT '0'"); 93 | $upgraded = true; 94 | } 95 | if ($auditlog->num_rows < 1) 96 | { 97 | $db->query("CREATE TABLE `auditlog` ( 98 | `time` int unsigned DEFAULT NULL, 99 | `actionid` int unsigned NOT NULL AUTO_INCREMENT, 100 | `action` enum('edit_post','delete_post','hide_post','rename_thread','delete_thread','move_thread','edit_labels','delete_avatar','edit_role','delete_user','change_forum_setting') DEFAULT NULL, 101 | `userid` int unsigned NOT NULL, 102 | `victimid` int unsigned NOT NULL, 103 | `before` text DEFAULT NULL, 104 | `after` text DEFAULT NULL, 105 | `context` text DEFAULT NULL, 106 | PRIMARY KEY (`actionid`) 107 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;"); 108 | $upgraded = true; 109 | } 110 | if ($pinned->num_rows < 1) 111 | { 112 | $db->query("ALTER TABLE `threads` ADD `pinned` tinyint(1) NOT NULL DEFAULT '0'"); 113 | $upgraded = true; 114 | } 115 | if ($order->num_rows < 1) 116 | { 117 | $db->query("ALTER TABLE `categories` ADD `order` int unsigned NOT NULL DEFAULT '0'"); 118 | $upgraded = true; 119 | } 120 | // Always run this because checking for it is too hard. 121 | $db->query("ALTER TABLE `users` MODIFY `avatar` enum('none', 'png', 'jpg', 'gif', 'webp') NOT NULL DEFAULT 'none'"); 122 | $db->query("ALTER TABLE `users` MODIFY `role` varchar(255) NOT NULL DEFAULT 'Member'"); 123 | 124 | // Get the forum config and the setup config. 125 | if (file_exists("config/config-setup.php")) { 126 | $current = $config; 127 | require "config/config-setup.php"; 128 | $setup = $config; 129 | // Merge them, the config overwriting the setup config. 130 | $config = array_merge($setup, $current); 131 | saveConfig("config/config.php", $config); 132 | } 133 | 134 | require "pages/header.php"; 135 | 136 | if ($upgraded == true) 137 | { 138 | message($lang["upgrade.Success"]); 139 | } 140 | else 141 | { 142 | message($lang["upgrade.None"]); 143 | } 144 | 145 | require "pages/footer.php"; 146 | 147 | ?> 148 | -------------------------------------------------------------------------------- /pages/panelextensions.page.php: -------------------------------------------------------------------------------- 1 | '; 62 | echo '

    ' . htmlspecialchars($manifest["title"]) . '

    '; 63 | echo '' . '' . formatPost($manifest["readme"]) . ''; 64 | echo '
    '; 65 | if (!isset($extensions[$e]) || $extensions[$e] != true || $extensions[$e] == false) 66 | { 67 | echo '
    '; 68 | } 69 | else if ($extensions[$e] == true || $extensions[$e] != false) 70 | { 71 | echo '
    '; 72 | } 73 | echo '
    '; 74 | echo '' . '' . formatPost($manifest["author"]) . ''; 75 | echo "
    "; 76 | // Output the extension settings 77 | if (isset($manifest["settings"])) { 78 | echo "
    " . $lang["page.settings"] . ""; 79 | echo '
    '; 80 | 81 | foreach($manifest["settings"] as $setting) 82 | { 83 | echo ""; 84 | //var_dump($setting); 85 | 86 | $value = htmlspecialchars($extension_config[$e][$setting["id"]]); 87 | 88 | switch ($setting["type"]) { 89 | case "bool": 90 | if ($value == "1") $value = 'checked=""'; 91 | echo ''; 92 | break; 93 | case "int": 94 | echo ''; 95 | break; 96 | case "string": 97 | echo ''; 98 | break; 99 | case "text": 100 | echo ''; 101 | break; 102 | default: 103 | echo "???"; 104 | break; 105 | } 106 | 107 | echo "
    "; 108 | } 109 | echo '
    '; 110 | echo '
    '; 111 | echo "
    "; 112 | } 113 | echo '
    '; 114 | } 115 | } 116 | ?> 117 | -------------------------------------------------------------------------------- /pages/userpanelavatarsettings.page.php: -------------------------------------------------------------------------------- 1 | array("png","imagecreatefrompng","imagepng",true), 21 | "image/gif" => array("gif","imagecreatefromgif","imagegif",true), 22 | "image/jpeg" => array("jpg","imagecreatefromjpeg","imagejpeg",false), 23 | "image/webp" => array("webp","imagecreatefromwebp","imagewebp",true), 24 | ); 25 | 26 | // Handle post requests. 27 | if ($_SERVER["REQUEST_METHOD"] == "POST") { 28 | if (isset($_FILES["uploadedFile"]) && $_FILES["uploadedFile"]["size"]) { 29 | $timeCheck = $db->query("SELECT avataruploadtime FROM users WHERE userid='" . $_SESSION["userid"] . "'"); 30 | 31 | while ($t = $timeCheck->fetch_assoc()) { 32 | $uploadTime = $t["avataruploadtime"]; 33 | } 34 | 35 | if (($config["timeBetweenAvatarUploads"] > 0) and isset($uploadTime) and ((time() - $uploadTime) <= $config["timeBetweenAvatarUploads"])) { 36 | message($lang["userpanel.WaitToUpload"]); 37 | return; 38 | } 39 | 40 | list($width,$height,$type,$attr) = getimagesize($_FILES["uploadedFile"]["tmp_name"]); 41 | $mime = image_type_to_mime_type($type); 42 | 43 | // Make sure the width and height is valid. 44 | if (!isset($width) or !isset($height) or ($width < 1) or ($height < 1)) { 45 | message($lang["userpanel.InvalidDimensions"]); 46 | } 47 | // Check for uploading errors. 48 | elseif (!isset($_FILES["uploadedFile"]["error"]) or (is_array($_FILES["uploadedFile"]["error"])) or ($_FILES["uploadedFile"]["error"] !== 0)) { 49 | message($lang["userpanel.FileUploadFail"]); 50 | } 51 | // Make sure the avatar isn't too big. 52 | elseif ($_FILES["uploadedFile"]["size"] > $config["maxAvatarSize"]) { 53 | message($lang["userpanel.FileTooBig"]); 54 | } 55 | else { 56 | if (array_key_exists($mime,$mimes)) { 57 | $w = $config["avatarWidth"]; 58 | if ($config["avatarWidth"] >= $width) { 59 | $w = $width; 60 | } 61 | $h = $config["avatarHeight"]; 62 | if ($config["avatarHeight"] >= $height) { 63 | $h = $height; 64 | } 65 | 66 | $originalRatio = $width/$height; 67 | 68 | if ($w/$h > $originalRatio) { 69 | $w = $h*$originalRatio; 70 | } 71 | else { 72 | $h = $w/$originalRatio; 73 | } 74 | 75 | $src = call_user_func($mimes[$mime][MIME_IMPORTFUNC],$_FILES["uploadedFile"]["tmp_name"]); 76 | $dst = imagecreatetruecolor($w, $h); 77 | 78 | if ($mimes[$mime][MIME_ALPHA]) { 79 | imagesavealpha($dst, true); 80 | $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127); 81 | imagefill($dst, 0, 0, $transparent); 82 | } 83 | 84 | imagecopyresampled($dst, $src, 0, 0, 0, 0, $w, $h, $width, $height); 85 | removeAvatar($_SESSION["userid"]); 86 | call_user_func($mimes[$mime][MIME_EXPORTFUNC],$dst, "avatars/" . $_SESSION["userid"] . "." . $mimes[$mime][MIME_EXTENSION]); 87 | 88 | if (file_exists("avatars/" . $_SESSION["userid"] . "." . $mimes[$mime][MIME_EXTENSION])) { 89 | $db->query("UPDATE users SET avatar='".$mimes[$mime][MIME_EXTENSION]."', avataruploadtime='" . time() . "' WHERE userid='" . $_SESSION["userid"] . "'"); 90 | message($lang["userpanel.AvatarUploadSuccess"]); 91 | } 92 | else { 93 | message($lang["userpanel.Fail"]); 94 | } 95 | } 96 | else { 97 | message($lang["userpanel.UnsupportedImageType"]); 98 | } 99 | } 100 | } 101 | elseif (isset($_POST["removeAvatar"])) { 102 | if (removeAvatar($_SESSION["userid"])) message($lang["userpanel.RemoveAvatarSuccess"]); 103 | } 104 | } 105 | 106 | $avatarCheck = $db->query("SELECT avatar, avataruploadtime FROM users WHERE userid='" . $_SESSION["userid"] . "'"); 107 | 108 | $avatarURL = ""; 109 | 110 | while ($a = $avatarCheck->fetch_assoc()) { 111 | if ($a["avatar"] != "none") { 112 | $avatarURL = "
    "; 113 | } 114 | } 115 | 116 | echo("

    " . $lang["userpanel.ChangeAvatar"] . "

    " . $avatarURL . "
    117 |
    118 | 119 |
    120 |
    "); 121 | 122 | // If the viewing user is logged in, update their last action. 123 | if ($_SESSION['signed_in'] == true) 124 | { 125 | update_last_action($lang["action.AvatarSettings"]); 126 | } 127 | 128 | ?> 129 | -------------------------------------------------------------------------------- /pages/login.page.php: -------------------------------------------------------------------------------- 1 | $lang["login.Header"], 20 | "message" => message(sprintf($lang["error.AlreadyLoggedIn"], genURL("logout")), true) 21 | ); 22 | echo $template->render("templates/generic/page_message.html", $data); 23 | include 'footer.php'; 24 | exit(); 25 | } 26 | 27 | if ($_SERVER['REQUEST_METHOD'] != 'POST') 28 | { 29 | include 'header.php'; 30 | 31 | $data = array( 32 | "title" => $lang["login.Header"], 33 | "username" => $lang["login.Username"], 34 | "password" => $lang["login.Password"], 35 | "submit" => $lang["login.Submit"] 36 | ); 37 | echo $template->render("templates/login/login_form.html", $data); 38 | include 'footer.php'; 39 | exit(); 40 | } 41 | 42 | $errors = array(); 43 | 44 | if (!isset($_POST['user_name']) || strlen($_POST['user_name']) == 0) { 45 | $errors[] = $lang["error.UsernameNull"]; 46 | } 47 | 48 | if (!isset($_POST['user_pass']) || strlen($_POST['user_pass']) == 0) { 49 | $errors[] = $lang["error.PasswordNull"]; 50 | } 51 | 52 | $db->query("DELETE FROM logins WHERE time<" . time() . "-300"); 53 | 54 | $logins = $db->query("SELECT * FROM logins WHERE ip='" . $db->real_escape_string(hashstring($_SERVER["REMOTE_ADDR"])) . "'"); 55 | 56 | if ($logins->num_rows >= $config["maxLoginAttempts"]) { 57 | $errors[] = $lang["error.TooManyLogins"]; 58 | } 59 | 60 | if (count($errors)) { 61 | include 'header.php'; 62 | $data = array( 63 | "title" => $lang["login.Header"], 64 | "badfields" => $lang["error.BadFields"], 65 | "errors" => "", 66 | "go_back" => $lang["error.GoBack"] 67 | ); 68 | 69 | foreach($errors as $key => $value) { 70 | $data["errors"] .= $template->render("templates/login/login_error.html", array("error" => $value)); 71 | } 72 | echo $template->render("templates/login/login_errors.html", $data); 73 | include 'footer.php'; 74 | exit(); 75 | } 76 | 77 | $username = $db->real_escape_string($_POST['user_name']); 78 | $resemail = $db->query("SELECT username FROM users WHERE email = '" . $username . "'"); 79 | 80 | if (strpos($username, '@') !== "0") { 81 | while($rowe = $resemail->fetch_assoc()) { 82 | $username = $rowe["username"]; 83 | } 84 | } 85 | 86 | $res = $db->query("SELECT salt FROM users WHERE username = '" . $username . "'"); 87 | if (!$res) { 88 | $errors[] = $lang["error.Database"]; 89 | } 90 | 91 | if (!$res->num_rows) { 92 | $errors[] = $lang["error.UsernameWrong"]; 93 | } 94 | 95 | $row = $res->fetch_assoc(); 96 | $salt = $row["salt"]; 97 | 98 | $hash = $db->real_escape_string(hashstring($salt . $_POST["user_pass"])); 99 | $result = $db->query("SELECT userid, username, role, password, verified FROM users WHERE username = '" . $username . "'"); 100 | 101 | if (!$result) { 102 | $errors[] = $lang["error.Database"]; 103 | } 104 | else { 105 | if (!$result->num_rows) { 106 | $errors[] = $lang["error.UsernameWrong"]; 107 | } 108 | $row = $result->fetch_assoc(); 109 | $userid = $row["userid"]; 110 | $username = $row["username"]; 111 | $role = $row["role"]; 112 | if ($row["verified"] == "0") { 113 | $errors[] = $lang["error.NeedsApproval"]; 114 | } 115 | 116 | // If the password doesn't match the hash in the database, we need some additional checks. 117 | if ($row["password"] != $hash) { 118 | // Check if the hash is a bcrypt hash. 119 | if (!password_verify($_POST["user_pass"], $row["password"])) { 120 | $errors[] = $lang["error.PasswordWrong"]; 121 | } 122 | } 123 | // If it does, we want to upgrade it to a bcrypt hash. 124 | else { 125 | $db->query("UPDATE users SET password='" . $db->real_escape_string(password_hash($_POST["user_pass"], PASSWORD_DEFAULT)) . "' WHERE userid='" . $db->real_escape_string($userid) . "'"); 126 | } 127 | } 128 | 129 | if (count($errors)) { 130 | $db->query("INSERT INTO logins (ip, time) VALUES ('" . $db->real_escape_string(hashstring($_SERVER["REMOTE_ADDR"])) . "', '" . time() . "')"); 131 | 132 | include 'header.php'; 133 | $data = array( 134 | "title" => $lang["login.Header"], 135 | "badfields" => $lang["error.BadFields"], 136 | "errors" => "", 137 | "go_back" => $lang["error.GoBack"] 138 | ); 139 | 140 | foreach($errors as $key => $value) { 141 | $data["errors"] .= $template->render("templates/login/login_error.html", array("error" => $value)); 142 | } 143 | echo $template->render("templates/login/login_errors.html", $data); 144 | include 'footer.php'; 145 | exit(); 146 | } 147 | 148 | $_SESSION['signed_in'] = true; 149 | $_SESSION['userid'] = $userid; 150 | $_SESSION['username'] = $username; 151 | $_SESSION['role'] = $role; 152 | 153 | $db->query("UPDATE users SET ip='" . $db->real_escape_string(hashstring($_SERVER["REMOTE_ADDR"])) . "' WHERE userid='" . $_SESSION["userid"] . "'"); 154 | header("Refresh:1; url=" . genURL($next)); 155 | include 'header.php'; 156 | 157 | $data = array( 158 | "title" => $lang["login.Header"], 159 | "message" => message(sprintf($lang["login.Welcome"], htmlspecialchars($_SESSION['username']), genURL($next)),true) 160 | ); 161 | echo $template->render("templates/generic/page_message.html", $data); 162 | 163 | include 'footer.php'; 164 | 165 | ?> 166 | -------------------------------------------------------------------------------- /pages/userlist.page.php: -------------------------------------------------------------------------------- 1 | "userid", 10 | "alphabet" => "username", 11 | "role" => "role", 12 | "activity" => "lastactive" 13 | ); 14 | 15 | $sortorderoptions = array( 16 | "asc" => "ASC", 17 | "desc" => "DESC" 18 | ); 19 | 20 | listener("beforeUserlistLoad"); 21 | 22 | // Handle requests to approve accounts. 23 | if (isset($_POST["approve"]) and is_numeric($_POST["approve"])) { 24 | $check = $db->query("SELECT 1 FROM users WHERE userid='" . $db->real_escape_string($_POST["approve"]) . "'"); 25 | 26 | if ($check->num_rows > 0) { 27 | if (allowed_to_edit_user($check["role"])) { 28 | $db->query("UPDATE users SET verified='1' WHERE userid='" . $db->real_escape_string($_POST["approve"]) . "'"); 29 | } 30 | } 31 | } 32 | 33 | $currentPage = 1; 34 | if (isset($q2) && is_numeric($q2)) $currentPage = $q2; 35 | 36 | if ($config["showDeletedInUserlist"] != 1) $user_count = $db->query("SELECT 1 FROM users WHERE deleted='0'"); 37 | else $user_count = $db->query("SELECT 1 FROM users"); 38 | $numUsers = $user_count->num_rows; 39 | 40 | if (!$numUsers) { 41 | include "header.php"; 42 | echo $lang["error.NoUsers"]; 43 | require "pages/footer.php"; 44 | exit; 45 | } 46 | 47 | $pages = ceil($numUsers / $config["usersPerPage"]); 48 | if ($currentPage > $pages) $currentPage = $pages; 49 | if ($currentPage < 1) $currentPage = 1; 50 | 51 | // Calculate the offset for the threads query. 52 | $offset = (($currentPage * $config["usersPerPage"]) - $config["usersPerPage"]); 53 | 54 | if ($config["userlistEnabled"] == false) { 55 | include "header.php"; 56 | message($lang["error.UserlistDisabled"]); 57 | require "pages/footer.php"; 58 | exit; 59 | } 60 | if (!(get_role_permissions() & PERM_VIEW_USERLIST)) { 61 | include "header.php"; 62 | message(sprintf($lang["error.UserlistMembersOnly"], genURL("signup"), genURL("login"))); 63 | require "pages/footer.php"; 64 | exit; 65 | } 66 | 67 | include "header.php"; 68 | 69 | $sort = $sortoptions["time"]; 70 | $order = $sortorderoptions["asc"]; 71 | if (array_key_exists("sort_by",$_GET) && array_key_exists($_GET["sort_by"],$sortoptions)) $sort = $sortoptions[$_GET["sort_by"]]; 72 | if (array_key_exists("sort_order",$_GET) && array_key_exists($_GET["sort_order"],$sortorderoptions)) $order = $sortorderoptions[$_GET["sort_order"]]; 73 | if ($order == $sortorderoptions["asc"] && $sort == $sortoptions["activity"]) $order = $sortorderoptions["desc"]; 74 | else if ($order == $sortorderoptions["desc"] && $sort == $sortoptions["activity"]) $order = $sortorderoptions["asc"]; 75 | $hidedeleted = ""; 76 | if ($config["showDeletedInUserlist"] != 1) $hidedeleted = " WHERE deleted='0'"; 77 | $result = $db->query("SELECT * FROM users" . $hidedeleted . " ORDER BY ".$sort." ".$order." LIMIT " . $config["usersPerPage"] . " OFFSET " . $offset . ""); 78 | 79 | if (!$result) { 80 | echo $lang["error.FailedFetchUsers"]; 81 | require "pages/footer.php"; 82 | exit; 83 | } 84 | $sort_data = array( 85 | "label" => $lang["userlist.SortBy"], 86 | "sort_by_options" => "", 87 | "sort_order_options" => "", 88 | "label_submit" => $lang["userlist.Submit"] 89 | ); 90 | 91 | foreach ($sortoptions as $s => $v) { 92 | if (isset($_GET["sort_by"]) && $_GET["sort_by"] == $s) $selected = "selected=''"; 93 | else $selected = ""; 94 | 95 | $sort_data["sort_by_options"] .= ''; 96 | } 97 | foreach ($sortorderoptions as $s => $v) { 98 | if (isset($_GET["sort_order"]) && $_GET["sort_order"] == $s) $selected = "selected=''"; 99 | else $selected = ""; 100 | 101 | $sort_data["sort_order_options"] .= ''; 102 | } 103 | 104 | $data = array( 105 | "title" => $lang["header.Userlist"], 106 | "pagination" => renderPagination(2, true), 107 | "users" => "", 108 | "sort_options" => $template->render("templates/userlist/sort_options.html",$sort_data) 109 | ); 110 | 111 | while($row = $result->fetch_assoc()) 112 | { 113 | $user_data = array( 114 | "deleted_class" => "", 115 | "color" => $row["color"], 116 | "url" => genURL('user/' . $row["userid"]), 117 | "role_class" => $row["role"], 118 | "username" => $row["username"], 119 | "role" => $lang["role.".$row["role"]], 120 | "buttons" => "", 121 | "action" => parseAction($row["lastaction"], $lang), 122 | "time" => date('m-d-Y h:i:s A', $row["lastactive"]), 123 | "relative_time" => relativeTime($row["lastactive"]) 124 | ); 125 | 126 | if ($row["deleted"] == "1") { 127 | $user_data["deleted_class"] = " deleteduser"; 128 | $user_data["username"] = $lang["user.Deleted"] . $row["userid"]; 129 | } 130 | 131 | if ($row["verified"] == "0" and allowed_to_edit_user($row["role"])) { 132 | $user_data["buttons"] = $template->render("templates/userlist/user_button.html",array("userid" => $row["userid"], "label" => $lang["userlist.Approve"])); 133 | } 134 | else if ($config["mainAdmin"] != $row["userid"] and get_role_permissions() & PERM_EDIT_FORUM) { 135 | $user_data["buttons"] = '' . $lang["panel.Administrate"] . ''; 136 | } 137 | 138 | $data["users"] .= $template->render("templates/userlist/user_display.html",$user_data); 139 | } 140 | 141 | echo $template->render("templates/userlist/userlist.html", $data); 142 | 143 | 144 | include "footer.php"; 145 | 146 | if (get_role_from_session() != "Guest") 147 | { 148 | update_last_action($lang["action.Userlist"]); 149 | } 150 | 151 | ?> 152 | -------------------------------------------------------------------------------- /pages/newthread.page.php: -------------------------------------------------------------------------------- 1 | "); 24 | 25 | if($_SERVER['REQUEST_METHOD'] == 'POST') 26 | { 27 | $cat = $db->query("SELECT 1 FROM categories WHERE categoryid='" . $db->real_escape_string($_POST["category"]) . "'"); 28 | 29 | if (mb_strlen(trim($_POST["title"])) < 1) 30 | { 31 | message($lang["newthread.TitleEmpty"]); 32 | $catSave = $_POST["category"]; 33 | $titleSave = trim($_POST["title"]); 34 | $contentSave = $_POST["content"]; 35 | } 36 | 37 | elseif (mb_strlen(trim($_POST["title"])) > $config["maxCharsPerTitle"]) 38 | { 39 | message(sprintf($lang["newthread.TitleBig1"], $config["maxCharsPerTitle"])); 40 | $catSave = $_POST["category"]; 41 | $titleSave = trim($_POST["title"]); 42 | $contentSave = $_POST["content"]; 43 | } 44 | 45 | elseif (mb_strlen($_POST["content"]) < 1) 46 | { 47 | message($lang["newthread.PostEmpty"]); 48 | $catSave = $_POST["category"]; 49 | $titleSave = trim($_POST["title"]); 50 | $contentSave = $_POST["content"]; 51 | } 52 | 53 | elseif (mb_strlen($_POST["content"]) > $config["maxCharsPerPost"]) 54 | { 55 | message(sprintf($lang["newthread.PostBig1"], $config["maxCharsPerPost"])); 56 | $catSave = $_POST["category"]; 57 | $titleSave = $_POST["title"]; 58 | $contentSave = $_POST["content"]; 59 | } 60 | 61 | elseif ((!$cat) or ($cat->num_rows < 1)) 62 | { 63 | message($lang["newthread.InvalidCategory"]); 64 | $catSave = $_POST["category"]; 65 | $titleSave = trim($_POST["title"]); 66 | $contentSave = $_POST["content"]; 67 | } 68 | 69 | else 70 | { 71 | // First check and see if the user has made a post too recently according to the post delay. 72 | $delaycheck = $db->query("SELECT 1 FROM posts WHERE user='" . $_SESSION["userid"] . "' AND timestamp>'" . (time() - $config["postDelay"]) . "'"); 73 | 74 | if ($delaycheck->num_rows > 0) 75 | { 76 | message(sprintf($lang["newthread.PostSoon1"], $config["postDelay"])); 77 | $catSave = $_POST["category"]; 78 | $titleSave = trim($_POST["title"]); 79 | $contentSave = $_POST["content"]; 80 | } 81 | 82 | else 83 | { 84 | 85 | $beginwork = $db->query("BEGIN WORK"); 86 | 87 | if(!$beginwork) 88 | { 89 | message($lang["newthread.CreateError"]); 90 | } 91 | 92 | else 93 | { 94 | $justnow = time(); 95 | $userid = $_SESSION["userid"]; 96 | 97 | if (isset($_POST["saveDraft"])) { 98 | $draft = "1"; 99 | } 100 | else { 101 | $draft = "0"; 102 | } 103 | 104 | $threadresult = $db->query("INSERT INTO threads (title, sticky, locked, posts, startuser, starttime, lastpostuser, lastposttime, category, draft) VALUES ('" . $db->real_escape_string(trim($_POST["title"])) . "', '0', '0', '1', '$userid', '$justnow', '$userid', '$justnow', '" . $db->real_escape_string($_POST["category"]) . "', '" . $db->real_escape_string($draft) . "')"); 105 | 106 | if (!$threadresult) 107 | { 108 | echo $lang["newthread.InsertThreadError"]; 109 | $db->query("ROLLBACK"); 110 | } 111 | 112 | else 113 | { 114 | $threadid = $db->insert_id; 115 | 116 | $result = $db->query("INSERT INTO posts (thread, user, timestamp, content) VALUES ('$threadid', '$userid', '$justnow', '" . $db->real_escape_string($_POST["content"]) . "')"); 117 | 118 | if(!$result) 119 | { 120 | echo $lang["newthread.InsertPostError"]; 121 | $db->query("ROLLBACK"); 122 | } 123 | else 124 | { 125 | $db->query("COMMIT"); 126 | 127 | message($lang["newthread.SuccessCreate1"] . ' ' . $lang["newthread.SuccessCreate2"] . ''); 128 | include("footer.php"); 129 | redirect("thread/" . $threadid); 130 | exit; 131 | } 132 | } 133 | } 134 | } 135 | } 136 | } 137 | 138 | echo '

    '.$lang["newthread.Header"].'

    '; 139 | 140 | $result = $db->query("SELECT * FROM categories"); 141 | 142 | if(!$result) 143 | { 144 | message($lang["newthread.DataError"]); 145 | } 146 | 147 | else 148 | { 149 | if(!$result->num_rows) 150 | { 151 | if($_SESSION['role'] == "Administrator") 152 | { 153 | message($lang["newthread.NoCategoryAdmin"]); 154 | } 155 | 156 | else 157 | { 158 | message($lang["newthread.NoCategoryUser"]); 159 | } 160 | } 161 | 162 | else 163 | { 164 | 165 | echo '
    '; 166 | echo '
    '; 169 | 170 | echo '
    '; 179 | 180 | BBCodeButtons(1); 181 | echo '
    '; 184 | echo ''; 185 | echo '
    '; 186 | echo ''; 187 | echo '
    '; 188 | echo '
    '; 189 | echo '
    '; 190 | } 191 | } 192 | } 193 | 194 | include 'footer.php'; 195 | 196 | // If the viewing user is logged in, update their last action. 197 | if ($_SESSION['signed_in'] == true) 198 | { 199 | update_last_action("action.CreateAThread"); 200 | } 201 | 202 | ?> 203 | -------------------------------------------------------------------------------- /pages/panelauditlog.page.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM auditlog ORDER BY `time` DESC LIMIT " . $config["postsPerPage"] . " OFFSET " . $offset . ""); 23 | 24 | $pagec = $db->query("SELECT * FROM auditlog"); 25 | 26 | while($row = $pagec->fetch_assoc()) { 27 | $numPosts = $row['actionid']; 28 | $pages = ceil($numPosts / $config["postsPerPage"]); 29 | } 30 | 31 | if (!$result) 32 | { 33 | message($lang["panel.UnknownError"]); 34 | } 35 | 36 | else 37 | { 38 | if ($pagec->num_rows == 0) 39 | { 40 | message($lang["panel.NoLogsFound"]); 41 | } 42 | 43 | else 44 | { 45 | echo "
    "; 46 | pagination("panel"); // so basically, this takes the arg, then adds $q2 to it, being "auditlog", so it links to /panel/auditlog/PAGE 47 | echo "
    "; 48 | 49 | 50 | while($row = $result->fetch_assoc()) 51 | { 52 | echo "
    "; 53 | 54 | if ($row["action"] == "edit_post") { 55 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["userid"] . "'"); 56 | while($urow = $user->fetch_assoc()) 57 | { 58 | $name = $urow["username"]; 59 | } 60 | printf($lang["panel.LogEdit"], 61 | "" . htmlspecialchars($name) . "", 62 | $row["victimid"]); 63 | 64 | echo "
    " . $lang["panel.BeforeEdit"] . "
    " . formatPost($row["before"]) . "
    "; 65 | echo "
    " . $lang["panel.AfterEdit"] . "
    " . formatPost($row["after"]) . "
    "; 66 | } 67 | elseif ($row["action"] == "edit_role") { 68 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["userid"] . "'"); 69 | while($urow = $user->fetch_assoc()) $name = $urow["username"]; 70 | $user2 = $db->query("SELECT * FROM users WHERE userid='" . $row["victimid"] . "'"); 71 | while($urow = $user2->fetch_assoc()) $vname = $urow["username"]; 72 | printf($lang["panel.LogEditRole"], 73 | "" . htmlspecialchars($name) . "", 74 | "" . htmlspecialchars($vname) . "",$row["before"],$row["after"]); 75 | } 76 | elseif ($row["action"] == "delete_avatar") { 77 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["userid"] . "'"); 78 | while($urow = $user->fetch_assoc()) $name = $urow["username"]; 79 | $user2 = $db->query("SELECT * FROM users WHERE userid='" . $row["victimid"] . "'"); 80 | while($urow = $user2->fetch_assoc()) $vname = $urow["username"]; 81 | printf($lang["panel.LogDeleteAvatar"], 82 | "" . htmlspecialchars($name) . "", 83 | "" . htmlspecialchars($vname) . ""); 84 | } 85 | elseif ($row["action"] == "hide_post") { 86 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["userid"] . "'"); 87 | while($urow = $user->fetch_assoc()) 88 | { 89 | $name = $urow["username"]; 90 | } 91 | $toggled = "panel.Restored"; 92 | if ($row["after"] == "hidden") { 93 | $toggled = "panel.Hid"; 94 | } 95 | printf($lang["panel.LogHide"], 96 | "" . htmlspecialchars($name) . "", 97 | $lang[$toggled], $row["victimid"]); 98 | } 99 | elseif ($row["action"] == "delete_post") { 100 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["userid"] . "'"); 101 | while($urow = $user->fetch_assoc()) 102 | { 103 | $name = $urow["username"]; 104 | } 105 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["victimid"] . "'"); 106 | while($urow = $user->fetch_assoc()) 107 | { 108 | $name2 = $urow["username"]; 109 | } 110 | printf($lang["panel.LogDelete"], 111 | "" . htmlspecialchars($name) . "", 112 | "" . htmlspecialchars($name2) . ""); 113 | echo "
    " . $lang["panel.PostContent"] . "
    " . formatPost($row["before"]) . "
    "; 114 | } 115 | elseif ($row["action"] == "delete_thread") { 116 | 117 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["userid"] . "'"); 118 | while($urow = $user->fetch_assoc()) 119 | { 120 | $name = $urow["username"]; 121 | } 122 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["victimid"] . "'"); 123 | while($urow = $user->fetch_assoc()) 124 | { 125 | $name2 = $urow["username"]; 126 | } 127 | printf($lang["panel.LogDeleteThread"], 128 | "" . htmlspecialchars($name) . "", 129 | "" . htmlspecialchars($name2) . "", 130 | htmlspecialchars($row["before"]) ); 131 | } 132 | else if ($row["action"] == "move_thread") { 133 | $user = $db->query("SELECT * FROM users WHERE userid='" . $row["userid"] . "'"); 134 | while($urow = $user->fetch_assoc()) 135 | { 136 | $name = $urow["username"]; 137 | } 138 | printf($lang["panel.LogMoveThread"], 139 | "" . htmlspecialchars($name) . "", 140 | htmlspecialchars($row["victimid"]), 141 | htmlspecialchars($row["before"]), 142 | htmlspecialchars($row["after"])); 143 | } 144 | echo relativeTime($row["time"]); 145 | echo "
    "; 146 | } 147 | echo "
    "; 148 | pagination("panel"); 149 | } 150 | } 151 | 152 | ?> 153 | -------------------------------------------------------------------------------- /pages/panelsettings.page.php: -------------------------------------------------------------------------------- 1 | "); 11 | echo '
    '; 12 | // Display the change forum name form. 13 | echo '

    ' . $lang["panel.BasicSettings"] . '

    14 |
    15 |
    '; 16 | 17 | // Display the change language form. 18 | echo '
    '; 19 | $adminLanguageSelector = str_replace('", $languageSelector); 20 | $adminLanguageSelector = str_replace('', "", $adminLanguageSelector); 21 | echo $adminLanguageSelector; 22 | echo '
    '; 23 | 24 | // Display the change theme form. 25 | echo '
    '; 26 | echo '
    '; 41 | 42 | // Display the change forum color form. 43 | $presetColor = "#000000"; 44 | $defaultchecked = ""; 45 | $newchecked = ""; 46 | if ($config["forumColor"] != null) 47 | { 48 | $presetColor = $config["forumColor"]; 49 | $newchecked = 'checked=""'; 50 | } 51 | else 52 | { 53 | $defaultchecked = 'checked=""'; 54 | } 55 | echo '

    ' . $lang["panel.ForumColor"] . '

    '; 56 | echo '
    '; 57 | echo ''; 58 | echo "
    "; 59 | echo '
    '; 60 | echo ''; 61 | echo '
    '; 62 | 63 | // Display the advanced settings. 64 | echo '

    ' . $lang["panel.AdvancedSettings"] . '

    '; 65 | echo '
    66 |
    67 |
    68 |
    69 |
    70 |
    71 |
    77 |
    78 |
    '; 84 | 85 | echo '
    86 |
    '; 92 | 93 | $options = array("open", "closed", "approval"); 94 | echo "
    "; 104 | 105 | // Display the change footer form. 106 | echo '

    ' . $lang["panel.ChangeFooter"] . '

    107 |
    108 |
    109 |
    '; 110 | } 111 | 112 | else 113 | { 114 | if (!isset($_POST)) 115 | { 116 | message($lang["panel.ChangeError"]); 117 | } 118 | else 119 | { 120 | if(isset($_POST["newuserlistEnabled"])) 121 | { 122 | $newuserlistEnabled = 1; 123 | } 124 | else 125 | { 126 | $newuserlistEnabled = 0; 127 | } 128 | if(isset($_POST["newuserlistMembersOnly"])) 129 | { 130 | $newuserlistMembersOnly = 1; 131 | } 132 | else 133 | { 134 | $newuserlistMembersOnly = 0; 135 | } 136 | if(isset($_POST["showDeletedInUserlist"])) 137 | { 138 | $showDeletedInUserlist = 1; 139 | } 140 | else 141 | { 142 | $showDeletedInUserlist = 0; 143 | } 144 | $newforumname = $_POST["newforumname"]; 145 | $newthreadsPerPage = $_POST["newthreadsPerPage"]; 146 | $newpostsPerPage = $_POST["newpostsPerPage"]; 147 | $newtheme = $_POST["newtheme"]; 148 | $newlang = $_POST["newlang"]; 149 | $newcolor = $_POST["newcolor"]; 150 | $color = $_POST["color"]; 151 | $newfooter = $_POST["newfooter"]; 152 | 153 | $config["forumName"] = htmlspecialchars($newforumname); 154 | $config["threadsPerPage"] = $newthreadsPerPage; 155 | $config["postsPerPage"] = $newpostsPerPage; 156 | $config['userlistEnabled'] = $newuserlistEnabled; 157 | $config['userlistMembersOnly'] = $newuserlistMembersOnly; 158 | $config["forumTheme"] = $newtheme; 159 | $config["forumLang"] = $newlang; 160 | $config["registration"] = $_POST["registration"]; 161 | $config["showDeletedInUserlist"] = $showDeletedInUserlist; 162 | 163 | if ($color == "new") 164 | { 165 | $config["forumColor"] = $newcolor; 166 | } 167 | else 168 | { 169 | $config["forumColor"] = null; 170 | } 171 | 172 | $config["footer"] = $newfooter; 173 | saveConfig("./config/config.php", $config); 174 | message($lang["panel.ChangesSaved"]); 175 | include "footer.php"; 176 | refresh(3, "panel"); 177 | } 178 | } 179 | ?> 180 | -------------------------------------------------------------------------------- /pages/user.page.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM users WHERE userid='" . $db->real_escape_string($q2) . "'"); 9 | 10 | if (!$result) 11 | { 12 | include "header.php"; 13 | message($lang["user.FaildFindUser"]); 14 | include "footer.php"; 15 | exit; 16 | } 17 | 18 | if ($result->num_rows == 0) 19 | { 20 | include "header.php"; 21 | message($lang["user.NoSuchUser"]); 22 | include "footer.php"; 23 | exit; 24 | } 25 | 26 | while ($row = $result->fetch_assoc()) 27 | { 28 | if ($row["deleted"] == "1") $username = $lang["user.Deleted"] . $row["userid"]; 29 | else $username = $row["username"]; 30 | 31 | $userid = $row["userid"]; 32 | $color = $row["color"]; 33 | $role = $row["role"]; 34 | $verified = $row["verified"]; 35 | $lastactive = $row["lastactive"]; 36 | $jointime = $row["jointime"]; 37 | $deleted = $row["deleted"]; 38 | $avatar = $row["avatar"]; 39 | $avatarTime = $row["avataruploadtime"]; 40 | } 41 | 42 | if ($_SERVER['REQUEST_METHOD'] == 'POST') 43 | { 44 | if (isset($_POST["role"]) and allowed_to_edit_user($role)) 45 | { 46 | if (is_numeric($q2) and ($_SESSION["userid"] != $q2) and ($config["mainAdmin"] != $q2)) { 47 | if (in_array($_POST["role"],get_changeable_roles(get_role_from_session()))) { 48 | $setrole = $db->query("UPDATE users SET role='" . $db->real_escape_string($_POST["role"]) . "' WHERE userid='" . $db->real_escape_string($q2) . "'"); 49 | if (!$setrole) echo $lang["user.FaildChangeRole"]; 50 | else { 51 | $db->query("INSERT INTO auditlog (`time`, `action`, `userid`, `victimid`, `before`, `after`) VALUES ('" . time() . "', 'edit_role', '" . $_SESSION["userid"] . "', '" . $db->real_escape_string($q2) . "', '" . $role . "', '" . $db->real_escape_string($_POST["role"]) ."')"); 52 | } 53 | refresh(0); 54 | } 55 | } 56 | } 57 | elseif (isset($_POST["removeAvatar"]) and $config["mainAdmin"] != $q2 and allowed_to_edit_user($role)) 58 | { 59 | removeAvatar($q2); 60 | $db->query("INSERT INTO auditlog (`time`, `action`, `userid`, `victimid`) 61 | VALUES ('" . time() . "', 'delete_avatar', '" . $_SESSION["userid"] . "', '" . $db->real_escape_string($q2) . "')"); 62 | refresh(0); 63 | } 64 | } 65 | 66 | include "header.php"; 67 | 68 | if ($verified == "1") $verified = $lang["user.VerifiedYes"]; 69 | else $verified = $lang["user.VerifiedNo"]; 70 | 71 | $delClass = ""; 72 | 73 | if ($deleted == "1") $delClass = " deleteduser"; 74 | 75 | if ($avatar == "none") $uAvatar = ""; 76 | else $uAvatar = ''; 77 | 78 | echo '

    '.$lang["user.ViewingProfile"].' "' . htmlspecialchars($username) . '"

    '; 79 | echo '
    '; 80 | 81 | drawUserProfile($userid, true); 82 | 83 | if ($avatar != "none" and allowed_to_edit_user($role)) { 84 | echo "
    "; 85 | } 86 | 87 | if ($config["mainAdmin"] != $userid and get_role_permissions() & PERM_EDIT_FORUM) { 88 | echo '' . $lang["panel.Administrate"] . ''; 89 | } 90 | 91 | echo "
    "; 92 | 93 | // Get user statistics 94 | 95 | $posts = $db->query("SELECT 1 FROM posts WHERE user='" . $db->real_escape_string($q2) . "'"); 96 | $uposts = mysqli_num_rows($posts); 97 | 98 | $threads = $db->query("SELECT 1 FROM threads WHERE startuser='" . $db->real_escape_string($q2) . "'"); 99 | $uthreads = mysqli_num_rows($threads); 100 | 101 | echo '

    ' . $lang["user.UserInformation"] . '

    102 | ' . relativeTime($jointime) . ' 103 | ' . relativeTime($lastactive) . ' 104 | ' . $uposts . ' 105 | ' . $uthreads . ' 106 | ' . $verified . ''; 107 | 108 | echo '
    '; 109 | 110 | if ($deleted != "1") { 111 | $bioCheck = $db->query("SELECT bio FROM users WHERE userid='" . $db->real_escape_string($q2) . "'"); 112 | $b = $bioCheck->fetch_assoc(); 113 | if (isset($b["bio"]) && strlen($b["bio"])) { 114 | echo '' . $lang["userpanel.Bio"] . ''; 115 | echo("" . formatPost($b["bio"]) . ""); 116 | } 117 | } 118 | 119 | echo "
    " . $lang["user.RecentPosts"] . ""; 120 | 121 | // Get the user's last 5 recent posts, excluding any draft posts. 122 | $postspre = $db->query("SELECT * FROM posts WHERE user='" . $db->real_escape_string($q2) . "' AND deletedby IS NULL"); 123 | $exclude = ""; 124 | 125 | while ($p = $postspre->fetch_assoc()) { 126 | $threads = $db->query("SELECT threadid FROM threads WHERE threadid='" . $db->real_escape_string($p["thread"]) . "' AND draft='1' AND startuser='" . $db->real_escape_string($q2) . "'"); 127 | 128 | while ($t = $threads->fetch_assoc()) { 129 | $exclude .= " AND thread<>" . $t["threadid"]; 130 | } 131 | } 132 | 133 | $posts = $db->query("SELECT * FROM posts WHERE user='" . $db->real_escape_string($q2) . "' AND deletedby IS NULL" . $exclude . " ORDER BY timestamp DESC LIMIT 5"); 134 | 135 | if($posts->num_rows == 0) 136 | { 137 | message($lang["thread.NoPosts"]); 138 | } 139 | 140 | else 141 | { 142 | while($row = $posts->fetch_assoc()) 143 | { 144 | $userinfo = $db->query("SELECT * FROM users WHERE userid='" . $row["user"] . "'"); 145 | 146 | while($u = $userinfo->fetch_assoc()) 147 | { 148 | echo '
    ' . formatPost($row["content"]) . '
    '; 149 | echo " - " . $lang["user.ViewThread"] . ""; 150 | } 151 | } 152 | } 153 | 154 | echo "
    "; 155 | 156 | if (get_role_from_session() != "Guest") 157 | { 158 | $action = $lang["action.Generic"]. '' . htmlspecialchars($username) . $lang["action.UserProfile"] . ''; 159 | update_last_action($action); 160 | } 161 | 162 | include "footer.php"; 163 | 164 | ?> 165 | -------------------------------------------------------------------------------- /pages/signup.page.php: -------------------------------------------------------------------------------- 1 | ' . $lang["register.Header"] . ''; 12 | message($lang["register.Closed"]); 13 | include "footer.php"; 14 | exit; 15 | } 16 | if (isset($_SESSION["signed_in"]) && $_SESSION["signed_in"] == true) { 17 | include 'header.php'; 18 | echo '

    ' . $lang["register.Header"] . '

    '; 19 | message($lang["nav.AdminsOnly"]); 20 | include "footer.php"; 21 | exit; 22 | } 23 | 24 | if($_SERVER['REQUEST_METHOD'] == 'POST') 25 | { 26 | $errors = array(); 27 | 28 | if (isset($_POST['user_name'])) { 29 | validateUsername($_POST["user_name"]); 30 | } 31 | else { 32 | $errors[] = $lang["error.UsernameNull"]; 33 | } 34 | 35 | if (isset($_POST['user_email'])) { 36 | validateEmail($_POST["user_email"]); 37 | } 38 | else { 39 | $errors[] = $lang["register.EmailEmpty"]; 40 | } 41 | 42 | if (isset($_POST["user_pass"])) { 43 | validatePassword($_POST["user_pass"], $_POST["user_pass_check"]); 44 | } 45 | else { 46 | $errors[] = $lang["register.PasswordEmpty"]; 47 | } 48 | 49 | if (($config["captchaEnabled"] == true) and ($_SESSION["captcha"] != $_POST["captcha"])) { 50 | $errors[] = $lang["register.CaptchaWrong"]; 51 | } 52 | 53 | // Make sure this user hasn't already created the maximum number of accounts. 54 | $altCheck = $db->query("SELECT ip FROM users WHERE ip='" . $db->real_escape_string(hashstring($_SERVER["REMOTE_ADDR"])) . "'"); 55 | 56 | if ($altCheck->num_rows >= $config["maxAccountsPerIP"]) { 57 | $errors[] = $lang["register.TooManyAccounts"]; 58 | } 59 | 60 | if(count($errors) <= 0) { 61 | registerUser(); 62 | } 63 | } 64 | 65 | include 'header.php'; 66 | echo '

    ' . $lang["register.Header"] . '

    '; 67 | 68 | if (isset($errors) and count($errors)) { 69 | echo $lang["error.BadFields"]; 70 | echo ''; 75 | } 76 | 77 | echo "
    78 |
    79 |
    80 |
    81 |
    "; 82 | if ($config["captchaEnabled"] == true) { 83 | echo "
    "; 84 | echo "" . $lang["register.CaptchaHint"] . ""; 85 | $_SESSION["captcha"] = generateCaptcha($config["captchaLength"]); 86 | } 87 | echo "
    88 |
    "; 89 | 90 | include 'footer.php'; 91 | 92 | // Validate usernames. 93 | function validateUsername($username) { 94 | global $db, $lang, $errors, $config; 95 | 96 | $res = $db->query("SELECT salt FROM users WHERE username = '" . $db->real_escape_string($username) . "'"); 97 | 98 | if($res->num_rows) { 99 | $errors[] = $lang["register.UsernameExists"]; 100 | } 101 | if(!checkUsername(htmlspecialchars_decode($username))) { 102 | $errors[] = $lang["error.UsernameAlphNum"]; 103 | } 104 | if(strlen($username) < 3) { 105 | $errors[] = $lang["error.UsernameSmall"]; 106 | } 107 | if(strlen($username) > $config['maxUsernameLength']) { 108 | $errors[] = $lang["error.UsernameBig"]; 109 | } 110 | } 111 | 112 | // Validate email addresses. 113 | function validateEmail($email) { 114 | global $db, $lang, $errors; 115 | 116 | $res = $db->query("SELECT * FROM users WHERE email ='". $db->real_escape_string($email) ."'"); 117 | 118 | if ($res->num_rows) { 119 | $errors[] = $lang["register.EmailExists"]; 120 | } 121 | if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { 122 | $errors[] = $lang["register.InvalidEmailFormat"]; 123 | } 124 | if (strlen($email) < 1) { 125 | $errors[] = $lang["register.EmailShort"]; 126 | } 127 | if (strlen($email) > 254) { 128 | $errors[] = $lang["register.EmailLong"]; 129 | } 130 | } 131 | 132 | // Validate passwords. 133 | function validatePassword($password, $passwordCheck) { 134 | global $lang, $errors; 135 | if (strlen($password) < 6) { 136 | $errors[] = $lang["register.PasswordSmall"]; 137 | } 138 | if (empty($passwordCheck)) { 139 | $errors[] = $lang["register.ConfirmPasswordEmpty"]; 140 | } 141 | if ($password != $passwordCheck) { 142 | $errors[] = $lang["register.ConfirmPasswordWrong"]; 143 | } 144 | } 145 | 146 | // Create a new user account. 147 | function registerUser() { 148 | global $db, $lang, $config; 149 | // Construct the query. 150 | // First we need to generate our salt in order to salt the password. 151 | $salt = ""; 152 | $username = $_POST['user_name']; 153 | $email = $_POST['user_email']; 154 | $password = password_hash($_POST['user_pass'], PASSWORD_DEFAULT); 155 | $role = "Member"; 156 | $jointime = time(); 157 | $lastactive = time(); 158 | $color = '1'; 159 | $ip = hashstring($_SERVER["REMOTE_ADDR"]); 160 | if ($config["registration"] == "open") { 161 | $verified = "1"; 162 | } 163 | elseif ($config["registration"] == "approval") { 164 | $verified = "0"; 165 | } 166 | 167 | $result = $db->query("INSERT INTO users (username, email, password, role, jointime, lastactive, color, ip, salt, verified) VALUES('" . $db->real_escape_string($username) . "', '" . $db->real_escape_string($email) . "', '" . $db->real_escape_string($password) . "', '" . $db->real_escape_string($role) . "', '" . $db->real_escape_string($jointime) . "', '" . $db->real_escape_string($lastactive) . "', '" . $db->real_escape_string($color) . "', '" . $db->real_escape_string($ip) . "', '" . $db->real_escape_string($salt) . "', '" . $db->real_escape_string($verified) . "')"); 168 | 169 | if (!$result) { 170 | echo $lang["error.Database"]; 171 | } 172 | elseif ($config["registration"] == "open") { 173 | $result = $db->query("SELECT userid, username, role FROM users WHERE username='" . $db->real_escape_string($username) . "'"); 174 | 175 | while ($row = $result->fetch_assoc()) { 176 | $_SESSION['signed_in'] = true; 177 | $_SESSION['userid'] = $row["userid"]; 178 | $_SESSION['username'] = $row["username"]; 179 | $_SESSION['role'] = $row["role"]; 180 | } 181 | 182 | redirect("userpanel"); 183 | } 184 | elseif ($config["registration"] == "approval") { 185 | include 'header.php'; 186 | echo '

    ' . $lang["register.Header"] . '

    '; 187 | printf($lang["register.Approval"], genURL("login")); 188 | include "footer.php"; 189 | exit; 190 | } 191 | } 192 | 193 | ?> 194 | -------------------------------------------------------------------------------- /pages/search.page.php: -------------------------------------------------------------------------------- 1 | real_escape_string(urldecode($get["search"])) . "%')", $query, $and); 21 | } 22 | if (isset($get["author"]) && $get["author"] != null) { 23 | $user = $db->query("SELECT * FROM users WHERE username='" . $db->real_escape_string(urldecode($get["author"])) . "'"); 24 | if ($user->num_rows) { 25 | $user_row = $user->fetch_assoc(); 26 | addToQuery("startuser='". $user_row["userid"] . "'", $query, $and); 27 | $author = 1; 28 | } 29 | } 30 | if (isset($get["category"]) && $get["category"] != null) { 31 | $category = $db->query("SELECT 1 FROM categories WHERE categoryid='" . $db->real_escape_string(urldecode($get["category"])) . "'"); 32 | if ($category->num_rows) { 33 | addToQuery("category='". $db->real_escape_string(urldecode($get["category"])) . "'", $query, $and); 34 | } 35 | } 36 | if (isset($get["user"]) && $get["user"] != null) { 37 | $user = $db->query("SELECT * FROM users WHERE username='" . $db->real_escape_string(urldecode($get["user"])) . "'"); 38 | if ($user->num_rows) { 39 | $user_row = $user->fetch_assoc(); 40 | $posts = $db->query("SELECT * FROM posts WHERE user='" . $user_row["userid"] . "'"); 41 | if ($posts->num_rows) { 42 | $threads = array(); 43 | while($row = $posts->fetch_assoc()) 44 | { 45 | if (!in_array($row["thread"],$threads)) array_push($threads,$row["thread"]); 46 | } 47 | if (count($threads)) { 48 | $query_add = "("; 49 | $first = 1; 50 | foreach($threads as $t) { 51 | if (!$first) $query_add .= " OR "; 52 | $query_add .= "threadid='" . $t . "'"; 53 | $first = 0; 54 | } 55 | $query_add .= ")"; 56 | addToQuery($query_add,$query,$and); 57 | } 58 | } 59 | } 60 | } 61 | if (isset($get["label"]) && $get["label"] != null) { 62 | $labels = explode(",", $get["label"]); 63 | if (in_array("locked",$labels)) addToQuery("locked='1'", $query, $and); 64 | else if (in_array("!locked",$labels)) addToQuery("locked='0'", $query, $and); 65 | if (in_array("sticky",$labels)) addToQuery("sticky='1'", $query, $and); 66 | else if (in_array("!sticky",$labels)) addToQuery("sticky='0'", $query, $and); 67 | if (in_array("pinned",$labels)) addToQuery("pinned='1'", $query, $and); 68 | else if (in_array("!pinned",$labels)) addToQuery("pinned='0'", $query, $and); 69 | } 70 | if (isset($get["label"]) && $get["label"] != null && in_array("draft", $labels)) { 71 | if (($_SESSION["signed_in"] && !$author)) { 72 | addToQuery("draft='1'", $query, $and); 73 | addToQuery("startuser='". $_SESSION["userid"] . "'", $query, $and); 74 | } 75 | else if ((($_SESSION["role"] == "Moderator") || ($_SESSION["role"] == "Administrator")) && $author) { 76 | addToQuery("draft='1'", $query, $and); 77 | } 78 | else addToQuery("draft='0'", $query, $and); 79 | } 80 | else addToQuery("draft='0'", $query, $and); 81 | 82 | if ($query == "WHERE draft='0' ") $query = ""; 83 | return $query; 84 | } 85 | 86 | if (isset($q2) && is_numeric($q2)) 87 | { 88 | $currentPage = $q2; 89 | } 90 | else 91 | { 92 | $currentPage = 1; 93 | } 94 | 95 | include "header.php"; 96 | 97 | $data = array 98 | ( 99 | "title" => $lang["search.Button"], 100 | "searchText" => "", 101 | "authorText" => "", 102 | "userText" => "", 103 | "categoryOptions" => "", 104 | "user_placeholder" => $lang["search.UserPlaceholder"], 105 | "title_label" => $lang["search.TitleLabel"], 106 | "author_label" => $lang["search.AuthorLabel"], 107 | "category_label" => $lang["search.CategoryLabel"], 108 | "user_label" => $lang["search.UserLabel"], 109 | "submit" => $lang["search.Submit"], 110 | "table" => "" 111 | ); 112 | if (isset($_GET["search"])) { 113 | $data["searchText"] = htmlspecialchars($_GET["search"]); 114 | } 115 | if (isset($_GET["author"])) { 116 | $data["authorText"] = htmlspecialchars($_GET["author"]); 117 | } 118 | if (isset($_GET["user"])) { 119 | $data["userText"] = htmlspecialchars($_GET["user"]); 120 | } 121 | 122 | $categories = $db->query("SELECT * FROM categories"); 123 | 124 | while($row = $categories->fetch_assoc()) { 125 | if (isset($_GET["category"]) && $_GET["category"] == $row["categoryid"]) $selected = "selected=''"; 126 | else $selected = ""; 127 | 128 | $data["categoryOptions"] .= ''; 129 | } 130 | 131 | if (isset($_GET["search"]) && strlen($_GET["search"]) > 64) 132 | { 133 | $data["table"] = message($lang["search.TooLong"], 1); 134 | echo $template->render("templates/search/search_page.html", $data); 135 | include 'footer.php'; 136 | exit; 137 | } 138 | 139 | $search = buildSearchQuery($_GET); 140 | 141 | if (!$search || strlen($search) < 1) 142 | { 143 | $data["table"] = message($lang["search.EmptySearch"], 1); 144 | echo $template->render("templates/search/search_page.html", $data); 145 | include 'footer.php'; 146 | exit; 147 | } 148 | 149 | // Important details for sorting the threads into pages. 150 | $thread_count = $db->query("SELECT 1 FROM threads " . $search); 151 | 152 | $numThreads = $thread_count->num_rows; 153 | 154 | if (!$numThreads) { 155 | $data["table"] = message($lang["search.NoResults"], 1); 156 | echo $template->render("templates/search/search_page.html", $data); 157 | include 'footer.php'; 158 | exit; 159 | } 160 | 161 | if ($numThreads < 1) $numThreads = 1; 162 | $pages = ceil($numThreads / $config["threadsPerPage"]); 163 | if ($currentPage > $pages) $currentPage = $pages; 164 | if ($currentPage < 1) $currentPage = 1; 165 | 166 | // Calculate the offset for the threads query. 167 | $offset = (($currentPage * $config["threadsPerPage"]) - $config["threadsPerPage"]); 168 | 169 | $threads = $db->query("SELECT * FROM threads " . $search . " ORDER BY lastposttime DESC LIMIT " . $config["threadsPerPage"] . " OFFSET " . $offset . ""); 170 | 171 | $table_data = array( 172 | "title" => $lang["search.Header"], 173 | "pagination" => "", 174 | "threads" => "", 175 | "th_thread" => $lang["category.Thread"], 176 | "th_posts" => $lang["category.Posts"], 177 | "th_lastpost" => $lang["category.LastPost"], 178 | ); 179 | 180 | while($row = $threads->fetch_assoc()) 181 | { 182 | $suinfo = $db->query("SELECT * FROM users WHERE userid='" . $row["startuser"] . "'"); 183 | $su = $suinfo->fetch_assoc(); 184 | if ($su["deleted"] == 1) $susername = $lang["user.Deleted"] . $su["userid"]; 185 | else $susername = $su["username"]; 186 | 187 | $uinfo = $db->query("SELECT * FROM users WHERE userid='" . $row["lastpostuser"] . "'"); 188 | $u = $uinfo->fetch_assoc(); 189 | if ($u["deleted"] == 1) $username = $lang["user.Deleted"] . $u["userid"]; 190 | else $username = $u["username"]; 191 | 192 | $thread_data = array 193 | ( 194 | "labels" => "", 195 | "url" => genURL('thread/' . $row['threadid']), 196 | "title" => htmlspecialchars($row['title']), 197 | "startuser" => sprintf("" .$lang["thread.Info"] . "", $su["role"], genURL("user/" . htmlspecialchars($row["startuser"])), htmlspecialchars($susername), date('m-d-Y h:i:s A', $row['starttime']), relativeTime($row["starttime"])), 198 | "posts" => $row['posts'], 199 | "user" => '' . htmlspecialchars($username) . '', 200 | "date" => date('m-d-Y h:i:s A', $row['lastposttime']), 201 | "reldate" => relativeTime($row["lastposttime"]), 202 | ); 203 | if ($row["locked"]) 204 | $thread_data["labels"] .= $template->render("templates/thread/label.html", ["class"=>"locked","text"=>$lang["label.Locked"]]); 205 | if ($row["sticky"]) 206 | $thread_data["labels"] .= $template->render("templates/thread/label.html", ["class"=>"sticky","text"=>$lang["label.Sticky"]]); 207 | if ($row["draft"]) 208 | $thread_data["labels"] .= $template->render("templates/thread/label.html", ["class"=>"draft","text"=>$lang["label.Draft"]]); 209 | if ($row["pinned"]) 210 | $thread_data["labels"] .= $template->render("templates/thread/label.html", ["class"=>"pinned","text"=>$lang["label.Pinned"]]); 211 | 212 | $table_data["threads"] .= $template->render("templates/thread/thread_display.html", $thread_data); 213 | } 214 | 215 | $table_data["pagination"] = renderPagination(2,1); 216 | 217 | $data["table"] = $template->render("templates/search/search_table.html", $table_data); 218 | 219 | echo $template->render("templates/search/search_page.html", $data); 220 | 221 | include 'footer.php'; 222 | -------------------------------------------------------------------------------- /install/install.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 40 | 43 | 44 | 46 | 49 | 53 | 57 | 58 | 61 | 65 | 69 | 70 | 73 | 77 | 81 | 82 | 90 | 95 | 96 | 106 | 116 | 126 | 136 | 142 | 146 | 150 | 154 | 158 | 162 | 166 | 167 | 175 | 179 | 183 | 187 | 191 | 195 | 199 | 200 | 206 | 210 | 214 | 218 | 222 | 223 | 229 | 233 | 237 | 241 | 245 | 246 | 256 | 257 | 268 | 272 | 277 | 282 | 295 | 300 | 305 | 313 | 321 | 331 | 338 | 355 | 356 | 357 | -------------------------------------------------------------------------------- /pages/panelcategory.page.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM `categories` WHERE `categoryid`='" . $db->real_escape_string($_POST["moveup"]) . "'"); 16 | 17 | // Only proceed if the category exists. 18 | if ($category && $category->num_rows > 0) { 19 | // Get any category information we need. 20 | while ($row = $category->fetch_assoc()) { 21 | $id = $row["categoryid"]; 22 | $order = $row["order"]; 23 | } 24 | 25 | // Only proceed if the category isn't the top one already. 26 | if ($order > 0) { 27 | // Get the id of the category ordered above this one. 28 | $above = $db->query("SELECT * FROM `categories` WHERE `order`='" . $db->real_escape_string(($order - 1)) . "'"); 29 | 30 | if ($above && $above->num_rows > 0) { 31 | 32 | while ($row = $above->fetch_assoc()) { 33 | $aboveid = $row["categoryid"]; 34 | $aboveorder = $row["order"]; 35 | } 36 | 37 | // Change the order of this category. 38 | $db->query("UPDATE `categories` SET `order`='" . $db->real_escape_string($aboveorder) . "' WHERE `categoryid`='" . $db->real_escape_string($id) . "'"); 39 | 40 | // Now change the order of the category formerly above this one. 41 | $db->query("UPDATE `categories` SET `order`='" . $db->real_escape_string($order) . "' WHERE `categoryid`='" . $db->real_escape_string($aboveid) . "'"); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | // Move a category down in order. 48 | if (isset($_POST["movedown"])) { 49 | // Only proceed if the requested category id is valid. 50 | if (is_numeric($_POST["movedown"])) { 51 | // Get the category. 52 | $category = $db->query("SELECT * FROM `categories` WHERE `categoryid`='" . $db->real_escape_string($_POST["movedown"]) . "'"); 53 | 54 | // Only proceed if the category exists. 55 | if ($category && $category->num_rows > 0) { 56 | // Get any category information we need. 57 | while ($row = $category->fetch_assoc()) { 58 | $id = $row["categoryid"]; 59 | $order = $row["order"]; 60 | } 61 | 62 | $getLargest = $db->query("SELECT MAX(`order`) AS 'order' FROM `categories`"); 63 | 64 | while ($l = $getLargest->fetch_assoc()) { 65 | $largest = $l["order"]; 66 | } 67 | 68 | // Only proceed if the category isn't on the bottom. 69 | if ($order < $largest) { 70 | // Get the id of the category ordered below this one. 71 | $below = $db->query("SELECT * FROM `categories` WHERE `order`='" . $db->real_escape_string(($order + 1)) . "'"); 72 | 73 | if ($below && $below->num_rows > 0) { 74 | 75 | while ($row = $below->fetch_assoc()) { 76 | $belowid = $row["categoryid"]; 77 | $beloworder = $row["order"]; 78 | } 79 | 80 | // Change the order of this category. 81 | $db->query("UPDATE `categories` SET `order`='" . $db->real_escape_string($beloworder) . "' WHERE `categoryid`='" . $db->real_escape_string($id) . "'"); 82 | 83 | // Now change the order of the category formerly above this one. 84 | $db->query("UPDATE `categories` SET `order`='" . $db->real_escape_string($order) . "' WHERE `categoryid`='" . $db->real_escape_string($belowid) . "'"); 85 | } 86 | } 87 | } 88 | } 89 | } 90 | if (isset($_POST["edit"]) or isset($_POST["edit_edit_cat_name"]) or isset($_POST["edit_cat_description"])) 91 | { 92 | $id = $_POST["edit"]; 93 | $category = $db->query("SELECT * FROM categories WHERE categoryid='" . $db->real_escape_string($id) . "'"); 94 | 95 | while($row = $category->fetch_assoc()) { 96 | // category information. 97 | $name = $row['categoryname']; 98 | $description = $row['categorydescription']; 99 | $id = $row['categoryid']; 100 | } 101 | 102 | if ($_POST["edit_edit_cat_name"] or $_POST["edit_cat_description"]) 103 | { 104 | $id = $_POST["cat_num"]; 105 | $name = $_POST["edit_edit_cat_name"]; 106 | $description = $_POST["edit_cat_description"]; 107 | 108 | if (!$_POST["edit_edit_cat_name"]) 109 | { 110 | message($lang["panel.CategoryNameBlank"]); 111 | } 112 | elseif (!$_POST["edit_cat_description"]) 113 | { 114 | message($lang["panel.CategoryDescBlank"]); 115 | } 116 | elseif (isset($_POST["edit_edit_cat_name"]) && isset($_POST["edit_cat_description"])) 117 | { 118 | $result = $db->query("UPDATE categories SET categoryname='" . $db->real_escape_string($name) . "',categorydescription='" . $db->real_escape_string($description) . "' WHERE categoryid='" . $db->real_escape_string($id) . "'"); 119 | if (!$result) 120 | { 121 | message($lang["panel.CantUpdateCategory"]); 122 | } 123 | 124 | else 125 | { 126 | message($lang["panel.SuccessUpdateCategory"]); 127 | include "footer.php"; 128 | echo(""); 129 | exit; 130 | } 131 | } 132 | } 133 | echo' 134 |
    135 | 136 |
    137 |
    138 |
    139 | 140 |
    '; 141 | 142 | include "footer.php"; 143 | exit; 144 | } 145 | 146 | if (isset($_POST["delete"]) or isset($_POST["deleteit"])) 147 | { 148 | $id = $_POST["delete"]; 149 | $category = $db->query("SELECT * FROM categories WHERE categoryid='" . $db->real_escape_string($id) . "'"); 150 | 151 | while($row = $category->fetch_assoc()) { 152 | // category information. 153 | $name = $row['categoryname']; 154 | $id = $row['categoryid']; 155 | } 156 | 157 | if ($_POST["deleteit"]) 158 | { 159 | $id = $_POST["deleteit"]; 160 | $result = $db->query("DELETE FROM categories WHERE categoryid='" . $db->real_escape_string($id) . "'"); 161 | 162 | if (!$result) { 163 | message($lang["CantDeleteCategory"]); 164 | } 165 | else 166 | { 167 | $threads = $db->query("SELECT * FROM threads WHERE category='" . $db->real_escape_string($id) . "'"); 168 | while($row = $threads->fetch_assoc()) { 169 | $result = $db->query("DELETE FROM posts WHERE thread='" . $row['threadid'] . "'"); 170 | $result = $db->query("DELETE FROM threads WHERE threadid='" . $row['threadid'] . "'"); 171 | } 172 | message($lang["panel.SuccessDeleteCategory"]); 173 | include "footer.php"; 174 | echo(""); 175 | exit; 176 | } 177 | } 178 | 179 | echo '

    '.$lang["panel.DeleteCategory"].'('.htmlspecialchars($name).')

    '; 180 | echo' 181 |
    182 | 183 |
    '.$lang["panel.CategoryDataWillGone"].'
    184 |
    '.$lang["panel.CategoryDeleteLastCheck"].'

    185 |
    '.$lang["panel.DeleteCategoryBackBtn"].'
    186 |
    '; 187 | 188 | include "footer.php"; 189 | exit; 190 | } 191 | 192 | if (isset($_POST["cat_name"])) 193 | { 194 | // Ensure the name and description aren't empty. 195 | if ($_POST["cat_name"] == "") 196 | { 197 | message($lang["panel.CategoryNameBlank"]); 198 | } 199 | 200 | elseif (!isset($_POST["cat_description"]) or $_POST["cat_description"] == "") 201 | { 202 | message($lang["panel.CategoryDescBlank"]); 203 | } 204 | 205 | elseif (strlen($_POST["cat_description"]) > 255) { 206 | message($lang["panel.CategoryDescTooLong"]); 207 | } 208 | elseif (strlen($_POST["cat_name"]) > 255) { 209 | message($lang["panel.CategoryNameTooLong"]); 210 | } 211 | else { 212 | 213 | // Check if there are any categories at all. 214 | $categoryCheck = $db->query("SELECT 1 FROM `categories`"); 215 | 216 | // If there aren't, set the order index to 0. 217 | if ($categoryCheck->num_rows < 1) { 218 | $largestOrder = 0; 219 | } 220 | // If there are, get the highest order index, and add 1 to it. 221 | else { 222 | $getLargestOrder = $db->query("SELECT MAX(`order`) AS 'order' FROM `categories`"); 223 | 224 | while ($r = $getLargestOrder->fetch_assoc()) { 225 | $largestOrder = $r["order"]; 226 | } 227 | 228 | $largestOrder++; 229 | } 230 | 231 | $result = $db->query("INSERT INTO `categories` (`categoryname`, `categorydescription`, `order`) VALUES ('" . $db->real_escape_string($_POST['cat_name']) . "', '" . $db->real_escape_string($_POST['cat_description']) . "', '" . $db->real_escape_string($largestOrder) . "')"); 232 | 233 | if(!$result) 234 | { 235 | message($lang["error.SomethingWentWrong"]); 236 | } 237 | 238 | else 239 | { 240 | message($lang["panel.SuccessAddedCategory"]); 241 | } 242 | } 243 | } 244 | } 245 | 246 | $result = $db->query("SELECT * FROM categories ORDER BY `order` ASC"); 247 | $getLargest = $db->query("SELECT MAX(`order`) AS 'order' FROM `categories`"); 248 | 249 | while ($l = $getLargest->fetch_assoc()) { 250 | $largest = $l["order"]; 251 | } 252 | 253 | while($row = $result->fetch_assoc()) { 254 | $numthreads = $db->query("SELECT * FROM threads WHERE category='" . $row["categoryid"] . "'"); 255 | $number = $numthreads->num_rows; 256 | echo '
    '; 257 | echo ''; 258 | echo '

    ' . htmlspecialchars($row["categoryname"]) . ' (#' . $row["categoryid"] . ')

    '; 259 | echo '
    ' . formatPost($row["categorydescription"]) . '
    '; 260 | echo '
    '; 261 | 262 | // Only show the move up button if this isn't the top category already. 263 | if ($row["order"] > 0) { 264 | echo '
    '; 265 | } 266 | // Only show the move down button if this isn't the bottom category already. 267 | if ($row["order"] < $largest) { 268 | echo '
    '; 269 | } 270 | 271 | echo '
    272 |
    '; 273 | echo '
    '; 274 | echo $lang["panel.CatThreads"] . $number . '
    '; 275 | echo '
    '; 276 | } 277 | echo ' 278 |

    '.$lang["panel.CreateACategory"].'

    279 |
    280 |
    281 |
    282 |
    283 |
    284 |
    '; 285 | 286 | ?> 287 | -------------------------------------------------------------------------------- /install/install.php: -------------------------------------------------------------------------------- 1 | "; 12 | echo "" . $lang["installer.Title"] . ""; 13 | echo ""; 14 | echo ""; 15 | echo ''; 16 | echo ""; 17 | echo ""; 18 | echo "
    "; 19 | echo "
    "; 20 | 21 | // Make sure directories that need to be written to are writeable. 22 | if (!is_writeable("config")) message($lang["installer.ConfigWarning"]); 23 | if (!is_writeable("avatars")) message($lang["installer.AvatarWarning"]); 24 | 25 | // Handle post requests. 26 | if (($_SERVER["REQUEST_METHOD"] == "POST") && (isset($_POST["MySQLServer"]))) { 27 | // Make sure the MySQL details have been inputted. 28 | if (!$_POST["MySQLServer"] or !$_POST["MySQLUser"] or !$_POST["MySQLPassword"] or !$_POST["MySQLDatabase"] or ($_POST["MySQLServer"] == "") or ($_POST["MySQLUser"] == "") or ($_POST["MySQLPassword"] == "") or ($_POST["MySQLDatabase"] == "")) { 29 | message($lang["installer.SQLMissing"]); 30 | $db = null; 31 | } 32 | else { 33 | // Make sure we can actually establish a connection to the database. 34 | try { 35 | $db = mysqli_connect($_POST["MySQLServer"], $_POST["MySQLUser"], $_POST["MySQLPassword"], $_POST["MySQLDatabase"]); 36 | } 37 | // If the connection failed, print the SQL (or PHP) error. 38 | catch (Exception $e) { 39 | message($e); 40 | $db = null; 41 | } 42 | } 43 | 44 | // Check if this database is already populated with forum-related tables. 45 | if ($db !== null) { 46 | $dbName = $db->real_escape_string($_POST["MySQLDatabase"]); 47 | $tablesExist = $db->query("SHOW TABLES FROM {$dbName} WHERE tables_in_{$dbName} like 'categories' OR 48 | tables_in_{$dbName} like 'posts' OR 49 | tables_in_{$dbName} like 'threads' OR 50 | tables_in_{$dbName} like 'users' OR 51 | tables_in_{$dbName} like 'logins' OR 52 | tables_in_{$dbName} like 'drafts' OR 53 | tables_in_{$dbName} like 'auditlog'"); 54 | } 55 | 56 | // This is here to inform the admin that the MySQL connection failed. 57 | if ($db === null) { 58 | message($lang["installer.SQLConnectFail"]); 59 | } 60 | 61 | // If any forum-related tables (or tables with the same names) exist, print an error. 62 | elseif ($tablesExist->num_rows > 0) { 63 | message($lang["installer.DBAlreadyExists"]); 64 | } 65 | 66 | // Make sure the admin's username isn't too short or empty. 67 | elseif ((strlen($_POST["adminUsername"]) < 1) or (!$_POST["adminUsername"]) or ($_POST["adminUsername"] == "")) { 68 | message($lang["installer.UsernameTooShort"]); 69 | } 70 | 71 | // Make sure the admin's username isn't too long. 72 | elseif (strlen($_POST["adminUsername"]) > 26) { 73 | message($lang["installer.UsernameTooLong"]); 74 | } 75 | 76 | // Make sure the admin's password isn't too short or empty. 77 | elseif ((strlen($_POST["adminPassword"]) < 1) or (!$_POST["adminPassword"]) or ($_POST["adminPassword"] == "")) { 78 | message($lang["installer.PasswordTooShort"]); 79 | } 80 | 81 | // Make sure the admin's email isn't too short or empty. 82 | elseif ((strlen($_POST["adminEmail"]) < 1) or (!$_POST["adminEmail"]) or ($_POST["adminEmail"] == "")) { 83 | message($lang["installer.EmailTooShort"]); 84 | } 85 | 86 | // Make sure the admin's email isn't too long. 87 | elseif (strlen($_POST["adminEmail"]) > 255) { 88 | message($lang["installer.EmailTooLong"]); 89 | } 90 | 91 | // Make sure the admin's password and confirm password entries match. 92 | elseif ($_POST["adminPassword"] != $_POST["adminConfirm"]) { 93 | message($lang["installer.PasswordsMismatch"]); 94 | } 95 | 96 | // If everything checks out, write the database and create the admin's account. 97 | else { 98 | $db->query("CREATE TABLE `categories` ( 99 | `categoryid` int unsigned NOT NULL AUTO_INCREMENT, 100 | `categoryname` varchar(255) NOT NULL, 101 | `categorydescription` varchar(255) NOT NULL, 102 | `order` int unsigned NOT NULL DEFAULT '0', 103 | `permissions` text DEFAULT NULL, 104 | PRIMARY KEY (`categoryid`), 105 | UNIQUE KEY `category_name` (`categoryname`) 106 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); 107 | 108 | $db->query("CREATE TABLE `posts` ( 109 | `postid` int unsigned NOT NULL AUTO_INCREMENT, 110 | `thread` int unsigned NOT NULL, 111 | `user` int unsigned NOT NULL, 112 | `timestamp` int unsigned NOT NULL, 113 | `editedby` int unsigned DEFAULT NULL, 114 | `edittime` int unsigned DEFAULT NULL, 115 | `deletedby` int unsigned DEFAULT NULL, 116 | `content` text NOT NULL, 117 | PRIMARY KEY (`postid`) 118 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); 119 | 120 | $db->query("CREATE TABLE `threads` ( 121 | `threadid` int unsigned NOT NULL AUTO_INCREMENT, 122 | `title` varchar(255) NOT NULL, 123 | `sticky` tinyint(1) NOT NULL DEFAULT '0', 124 | `locked` tinyint(1) NOT NULL DEFAULT '0', 125 | `pinned` tinyint(1) NOT NULL DEFAULT '0', 126 | `posts` int unsigned NOT NULL, 127 | `startuser` int unsigned NOT NULL, 128 | `starttime` int unsigned NOT NULL, 129 | `lastpostuser` int unsigned NOT NULL, 130 | `lastposttime` int unsigned NOT NULL, 131 | `category` int unsigned NOT NULL, 132 | `draft` tinyint(1) NOT NULL DEFAULT '0', 133 | PRIMARY KEY (`threadid`) 134 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); 135 | 136 | $db->query("CREATE TABLE `users` ( 137 | `userid` int unsigned NOT NULL AUTO_INCREMENT, 138 | `username` varchar(26) NOT NULL, 139 | `email` varchar(255) NOT NULL, 140 | `password` varchar(128) NOT NULL, 141 | `role` varchar(255) NOT NULL DEFAULT 'Member', 142 | `jointime` int unsigned NOT NULL, 143 | `lastactive` int unsigned DEFAULT NULL, 144 | `lastaction` varchar(255) DEFAULT NULL, 145 | `color` tinyint unsigned NOT NULL DEFAULT '1', 146 | `ip` varchar(128) NOT NULL, 147 | `salt` char(64) NOT NULL, 148 | `verified` tinyint(1) NOT NULL DEFAULT '0', 149 | `deleted` tinyint(1) NOT NULL DEFAULT '0', 150 | `signature` varchar(512) DEFAULT NULL, 151 | `bio` varchar(2048) DEFAULT NULL, 152 | `avatar` enum('none', 'png', 'jpg', 'gif', 'webp') NOT NULL DEFAULT 'none', 153 | `avataruploadtime` int unsigned DEFAULT NULL, 154 | PRIMARY KEY (`userid`), 155 | UNIQUE KEY `user_name` (`username`), 156 | UNIQUE KEY `user_email` (`email`) 157 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); 158 | 159 | $db->query("CREATE TABLE `logins` ( 160 | `ip` varchar(128) NOT NULL, 161 | `time` int unsigned NOT NULL 162 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); 163 | 164 | $db->query("CREATE TABLE `drafts` ( 165 | `user` int unsigned NOT NULL, 166 | `thread` int unsigned NOT NULL, 167 | `timestamp` int unsigned NOT NULL, 168 | `content` text NOT NULL 169 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); 170 | 171 | $db->query("CREATE TABLE `auditlog` ( 172 | `time` int unsigned DEFAULT NULL, 173 | `actionid` int unsigned NOT NULL AUTO_INCREMENT, 174 | `action` enum('edit_post','delete_post','hide_post','rename_thread','delete_thread','move_thread','edit_labels','delete_avatar','edit_role','delete_user','change_forum_setting') DEFAULT NULL, 175 | `userid` int unsigned NOT NULL, 176 | `victimid` int unsigned NOT NULL, 177 | `before` text DEFAULT NULL, 178 | `after` text DEFAULT NULL, 179 | `context` text DEFAULT NULL, 180 | PRIMARY KEY (`actionid`) 181 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); 182 | 183 | // Create the admin's account, first generating the salt, password hash, and IP address hash. 184 | $adminSalt = ""; 185 | $adminHash = password_hash($_POST["adminPassword"], PASSWORD_DEFAULT); 186 | $adminIP = hashstring($_SERVER["REMOTE_ADDR"]); 187 | $adminEmail = $_POST["adminEmail"]; 188 | $db->query("INSERT INTO `users` (username, email, password, role, jointime, color, ip, salt, verified) VALUES ('" . $db->real_escape_string($_POST["adminUsername"]) . "', '" . $db->real_escape_string($adminEmail) . "', '" . $db->real_escape_string($adminHash) . "', 'Administrator', '" . time() . "', '1', '" . $db->real_escape_string($adminIP) . "', '" . $db->real_escape_string($adminSalt) . "' ,'1')"); 189 | // Create the default category. 190 | $db->query("INSERT INTO `categories` (`categoryname`, `categorydescription`, `order`) VALUES ('" . $db->real_escape_string($lang["installer.GeneralCategoryName"]) . "', '" . $db->real_escape_string($lang["installer.GeneralCategoryDescription"]) . "', '" . 0 . "')"); 191 | 192 | // Now write our MySQL details to the config as well as whether the forum has been installed or not. 193 | $config["installed"] = "yes"; 194 | $config["MySQLServer"] = $_POST["MySQLServer"]; 195 | $config["MySQLDatabase"] = $_POST["MySQLDatabase"]; 196 | $config["MySQLUser"] = $_POST["MySQLUser"]; 197 | $config["MySQLPass"] = $_POST["MySQLPassword"]; 198 | $config["baseURL"] = rtrim((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]", "/"); 199 | $config["modRewriteDisabled"] = 1; 200 | 201 | // Only try to use the mod rewrite if we detect that it's enabled. 202 | if (function_exists("apache_get_modules")) { 203 | if (in_array("mod_rewrite", apache_get_modules())) { 204 | $config["modRewriteDisabled"] = 0; 205 | } 206 | } 207 | 208 | // If everything worked, display a message saying so. 209 | if (saveConfig("./config/config.php", $config)) { 210 | // Log the administrator in. 211 | $_SESSION["signed_in"] = "true"; 212 | $_SESSION["userid"] = "1"; 213 | $_SESSION["username"] = $_POST["adminUsername"]; 214 | $_SESSION["role"] = "Administrator"; 215 | 216 | message($lang["installer.InstallSuccess"]); 217 | echo "
    "; 218 | refresh(4); 219 | exit; 220 | } 221 | // If the config file failed to write, display an error message. 222 | else { 223 | message($lang["installer.ConfigWriteFail"]); 224 | } 225 | } 226 | } 227 | 228 | echo($lang["installer.Welcome"]); 229 | 230 | echo("
    231 |
    232 |

    " . $lang["installer.SQLDetails"] . "


    233 |
    234 |
    235 |
    236 |
    237 |
    238 |
    239 |
    240 |
    241 |

    " . $lang["installer.AdministratorAccount"] . "


    242 |
    243 |
    244 |
    245 |
    246 |
    247 |
    248 |
    249 |
    250 |
    251 | 252 |
    "); 253 | 254 | echo "

    "; 255 | echo($languageSelector); 256 | echo ""; 257 | ?> 258 | --------------------------------------------------------------------------------