leilukin-tumbleblog/install.php

1147 lines
42 KiB
PHP

<?php
/**
* File: install
* Creates the SQL tables and builds the site configuration.
*/
header("Content-Type: text/html; charset=UTF-8");
define('DEBUG', true);
define('CHYRP_VERSION', "2024.02");
define('CHYRP_CODENAME', "Miombo");
define('CHYRP_IDENTITY', "Chyrp/".CHYRP_VERSION." (".CHYRP_CODENAME.")");
define('MAIN', false);
define('ADMIN', false);
define('AJAX', false);
define('UPGRADING', false);
define('INSTALLING', true);
define('COOKIE_LIFETIME', 2592000);
define('PASSWORD_RESET_TOKEN_LIFETIME', 3600);
define('MAX_TIME_LIMIT', 600);
define('MAX_MEMORY_LIMIT', "100M");
define('SQL_DATETIME_ZERO', "1000-01-01 00:00:00");
define('SQL_DATETIME_ZERO_VARIANTS',
array(
"0000-00-00 00:00:00",
"0001-01-01 00:00:00",
"1000-01-01 00:00:00"
)
);
define('BOT_UA', false);
define('DIR', DIRECTORY_SEPARATOR);
define('MAIN_DIR', dirname(__FILE__));
define('INCLUDES_DIR', MAIN_DIR.DIR."includes");
define('CACHES_DIR', INCLUDES_DIR.DIR."caches");
define('MODULES_DIR', MAIN_DIR.DIR."modules");
define('FEATHERS_DIR', MAIN_DIR.DIR."feathers");
define('THEMES_DIR', MAIN_DIR.DIR."themes");
define('UPDATE_XML', null);
define('UPDATE_INTERVAL', null);
define('UPDATE_PAGE', null);
define('SESSION_DENY_BOT', true);
define('GET_REMOTE_UNSAFE', false);
define('USE_GETTEXT_SHIM', stripos(PHP_OS, "Win") === 0);
define('USE_OB', true);
define('HTTP_ACCEPT_DEFLATE', false);
define('HTTP_ACCEPT_GZIP', false);
define('CAN_USE_ZLIB', false);
define('USE_ZLIB', false);
define('PREVIEWING', false);
define('THEME_DIR', null);
define('THEME_URL', null);
ob_start();
define('OB_BASE_LEVEL', ob_get_level());
if (version_compare(PHP_VERSION, "8.0", "<"))
exit("Chyrp Lite requires PHP 8.0 or greater. Installation cannot continue.");
# File: error
# Functions for handling and reporting errors.
require_once INCLUDES_DIR.DIR."error.php";
# File: helpers
# Various functions used throughout the codebase.
require_once INCLUDES_DIR.DIR."helpers.php";
# File: Config
# See Also:
# <Config>
require_once INCLUDES_DIR.DIR."class".DIR."Config.php";
# File: SQL
# See Also:
# <SQL>
require INCLUDES_DIR.DIR."class".DIR."SQL.php";
# File: Model
# See Also:
# <Model>
require_once INCLUDES_DIR.DIR."class".DIR."Model.php";
# File: User
# See Also:
# <User>
require_once INCLUDES_DIR.DIR."model".DIR."User.php";
# File: Translation
# See Also:
# <Translation>
require_once INCLUDES_DIR.DIR."class".DIR."Translation.php";
# Register our autoloader.
spl_autoload_register("autoload");
# Boolean: $installed
# Has Chyrp Lite been installed?
$installed = false;
# Prepare the Config interface.
$config = Config::current();
# Get the timezone.
$timezone = get_timezone();
# Get the locale.
$locale = get_locale();
# List of discovered drivers.
$drivers = array();
# Currently selected adapter.
$adapter = isset($_POST['adapter']) ? $_POST['adapter'] : "mysql" ;
# Where are we?
$url = preg_replace("/\/install\.php.*$/i", "", guess_url());
# Set the timezone.
set_timezone($timezone);
# Set the locale.
set_locale($locale);
# Try to load an appropriate translation.
load_translator("chyrp", INCLUDES_DIR.DIR."locale");
# Already installed?
if (file_exists(INCLUDES_DIR.DIR."config.json.php"))
redirect($config->url);
if (class_exists("PDO")) {
$pdo_available_drivers = PDO::getAvailableDrivers();
if (in_array("sqlite", $pdo_available_drivers))
$drivers[] = "sqlite";
if (in_array("mysql", $pdo_available_drivers))
$drivers[] = "mysql";
if (in_array("pgsql", $pdo_available_drivers))
$drivers[] = "pgsql";
}
# Test for basic database access requirements.
if (empty($drivers))
alert(
__("PDO is required for database access."));
# Test if we can write to MAIN_DIR (needed for the .htaccess file).
if (!is_writable(MAIN_DIR))
alert(
__("Please CHMOD or CHOWN the installation directory to make it writable.")
);
# Test if we can write to INCLUDES_DIR (needed for config.json.php).
if (!is_writable(INCLUDES_DIR))
alert(
__("Please CHMOD or CHOWN the <em>includes</em> directory to make it writable.")
);
# Test if we can write to CACHES_DIR (needed by some extensions).
if (!is_writable(CACHES_DIR))
alert(
__("Please CHMOD or CHOWN the <em>caches</em> directory to make it writable.")
);
# Test if we can write to twig cache.
if (!is_writable(CACHES_DIR.DIR."twig"))
alert(
__("Please CHMOD or CHOWN the <em>twig</em> directory to make it writable.")
);
# Test if we can write to thumbs cache.
if (!is_writable(CACHES_DIR.DIR."thumbs"))
alert(
__("Please CHMOD or CHOWN the <em>thumbs</em> directory to make it writable.")
);
/**
* Function: alert
* Logs an alert message and returns the log to date.
*/
function alert($message = null): ?array {
static $log = array();
if (isset($message))
$log[] = (string) $message;
return empty($log) ? null : $log ;
}
/**
* Function: guess_url
* Returns a best guess of the current URL.
*/
function guess_url(): string {
$scheme = (!empty($_SERVER['HTTPS']) and $_SERVER['HTTPS'] !== "off") ?
"https" :
"http" ;
$host = isset($_SERVER['HTTP_HOST']) ?
$_SERVER['HTTP_HOST'] :
$_SERVER['SERVER_NAME'] ;
return $scheme."://".$host.$_SERVER['REQUEST_URI'];
}
/**
* Function: posted
* Echoes a $_POST value if set, otherwise echoes the fallback value.
*
* Parameters:
* $key - The key to test in the $_POST array.
* $fallback - The value to echo if the $_POST value is not set.
*/
function posted($key, $fallback = ""): void {
echo fix(
isset($_POST[$key]) ? $_POST[$key] : $fallback, true
);
}
/**
* Function: selected
* Echoes " selected" HTML attribute if the supplied values are equal.
*
* Parameters:
* $val1 - Compare this value...
* $val2 - ... with this value.
*/
function selected($val1, $val2): void {
if ($val1 == $val2)
echo " selected";
}
#---------------------------------------------
# Output Starts
#---------------------------------------------
?>
<!DOCTYPE html>
<html dir="auto">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=640">
<title><?php echo __("Chyrp Lite Installer"); ?></title>
<style type="text/css">
@font-face {
font-family: 'Open Sans webfont';
src: url('./fonts/OpenSans-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('./fonts/OpenSans-SemiBold.woff') format('woff');
font-weight: 600;
font-style: normal;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('./fonts/OpenSans-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('./fonts/OpenSans-Italic.woff') format('woff');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('./fonts/OpenSans-SemiBoldItalic.woff') format('woff');
font-weight: 600;
font-style: italic;
}
@font-face {
font-family: 'Open Sans webfont';
src: url('./fonts/OpenSans-BoldItalic.woff') format('woff');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: 'Cousine webfont';
src: url('./fonts/Cousine-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Cousine webfont';
src: url('./fonts/Cousine-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'Cousine webfont';
src: url('./fonts/Cousine-Italic.woff') format('woff');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'Cousine webfont';
src: url('./fonts/Cousine-BoldItalic.woff') format('woff');
font-weight: bold;
font-style: italic;
}
:root {
color-scheme: light dark;
}
*::selection {
color: #ffffff;
background-color: #ff7f00;
}
html, body, div, dl, dt, dd, ul, ol, li, p,
h1, h2, h3, h4, h5, h6, img, pre, code,
form, fieldset, input, select, textarea,
table, tbody, tr, th, td, legend, caption,
blockquote, aside, figure, figcaption {
margin: 0em;
padding: 0em;
border: 0em;
}
html {
font-size: 16px;
}
body {
font-size: 1rem;
font-family: "Open Sans webfont", sans-serif;
line-height: 1.5;
color: #1f1f23;
tab-size: 4;
background: #efefef;
margin: 2rem;
}
h1 {
font-size: 2em;
font-weight: bold;
margin: 1rem 0rem;
text-align: center;
}
h2 {
font-size: 1.5em;
text-align: center;
font-weight: bold;
margin: 1rem 0rem;
}
h3 {
font-size: 1em;
font-weight: 600;
margin: 1rem 0rem;
border-bottom: 1px solid #cfcfcf;
}
p {
margin-bottom: 1rem;
}
strong {
font: inherit;
font-weight: bold;
color: #c11600;
}
em, dfn, cite, var {
font: inherit;
font-style: italic;
}
ul, ol {
margin-bottom: 1rem;
margin-inline-start: 2rem;
list-style-position: outside;
}
label {
display: block;
font-weight: 600;
}
textarea {
display: block;
resize: vertical;
}
input, select {
display: inline-block;
}
input[type="text"],
input[type="email"],
input[type="url"],
input[type="number"],
input[type="password"],
select,
textarea {
box-sizing: border-box;
width: 100%;
margin: 0rem;
color: #1f1f23;
font: inherit;
font-size: 1.25em;
padding: 0.5rem;
border-radius: 0em;
border: 1px solid #cfcfcf;
background-color: #ffffff;
}
select {
appearance: none;
padding-right: 1em;
background-image: url(admin/images/icons/select.svg);
background-position: center right 0.1em;
background-repeat: no-repeat;
}
input:invalid,
textarea:invalid {
border-color: #ff7f00;
}
input[type="text"]:focus,
input[type="email"]:focus,
input[type="url"]:focus,
input[type="number"]:focus,
input[type="password"]:focus,
select:focus,
textarea:focus {
border-color: #1e57ba;
outline: #1e57ba solid 2px;
outline-offset: -2px;
}
input[type="text"].error,
input[type="email"].error,
input[type="url"].error,
input[type="number"].error,
input[type="password"].error,
textarea.error {
background-color: #faebe4;
}
input[type="text"].error:focus,
input[type="email"].error:focus,
input[type="url"].error:focus,
input[type="number"].error:focus,
input[type="password"].error:focus,
textarea.error:focus {
border: 1px solid #c11600;
outline-color: #c11600;
}
input[type="password"].strong {
background-color: #ebfae4;
}
input[type="password"].strong:focus {
border: 1px solid #108600;
outline-color: #108600;
}
form:has(#adapter > option[value="sqlite"]:checked) *.not-sqlite {
display: none;
}
form:has(#adapter > option[value="mysql"]:checked) *.not-mysql {
display: none;
}
form:has(#adapter > option[value="pgsql"]:checked) *.not-pgsql {
display: none;
}
pre {
font-family: "Cousine webfont", monospace;
font-size: 0.85em;
background-color: #efefef;
margin: 1rem 0rem;
padding: 1rem;
overflow-x: auto;
white-space: pre;
}
code {
font-family: "Cousine webfont", monospace;
font-size: 0.85em;
background-color: #efefef;
padding: 0px 2px;
border: 1px solid #cfcfcf;
vertical-align: bottom;
white-space: break-spaces;
}
pre > code {
font-size: 0.85rem;
display: block;
border: none;
padding: 0px;
white-space: inherit;
}
pre.pane {
height: 15rem;
overflow: auto;
}
pre.pane:empty {
display: none;
}
pre.pane:empty + h1 {
margin-top: 0rem;
}
a:link,
a:visited {
color: #1f1f23;
text-decoration: underline;
text-underline-offset: 0.125em;
}
a:focus {
outline: #ff7f00 dashed 2px;
outline-offset: 1px;
}
a:hover,
a:focus,
a:active {
color: #1e57ba;
text-decoration: underline;
text-underline-offset: 0.125em;
}
a.big,
button {
box-sizing: border-box;
display: block;
clear: both;
font: inherit;
font-size: 1.25em;
text-align: center;
color: #1f1f23;
text-decoration: none;
margin: 1rem 0rem;
padding: 0.5rem;
background-color: #f2fbff;
border: 2px solid #b8cdd9;
border-radius: 0.25em;
cursor: pointer;
}
button {
width: 100%;
}
a.big:hover,
button:hover,
a.big:focus,
button:focus,
a.big:active,
button:active {
border-color: #1e57ba;
outline: none;
}
hr {
border: none;
clear: both;
border-top: 1px solid #cfcfcf;
margin: 2rem 0rem;
}
aside {
margin-bottom: 1rem;
padding: 0.5rem 1rem;
border: 1px solid #e5d7a1;
border-radius: 0.25em;
background-color: #fffde6;
}
.window {
width: 30rem;
background: #ffffff;
padding: 2rem;
margin: 0rem auto 0rem auto;
border-radius: 2rem;
}
.window > *:first-child,
form > *:first-child {
margin-top: 0rem;
}
.window > *:last-child,
form > *:last-child {
margin-bottom: 0rem;
}
@media (prefers-color-scheme: dark) {
body {
color: #ffffff;
background-color: #1f1f23;
}
.window {
color: #1f1f23;
background-color: #efefef;
}
hr {
border-color: #afafaf;
}
aside {
border-color: #afafaf;
}
pre {
background-color: #dfdfdf;
}
code {
background-color: #dfdfdf;
border-color: #afafaf;
}
select,
textarea,
input[type="text"],
input[type="email"],
input[type="url"],
input[type="number"],
input[type="password"] {
background-color: #dfdfdf;
border-color: #afafaf;
}
input:invalid {
border-color: #ff7f00;
}
}
</style>
<script src="includes/common.js" type="text/javascript" charset="UTF-8"></script>
<script type="text/javascript">
'use strict';
$(function() {
$("#password1").keyup(function(e) {
var password = $(this).val();
if (passwordStrength(password) > 99)
$(this).addClass("strong");
else
$(this).removeClass("strong");
});
$("#password1, #password2").keyup(function(e) {
var password1 = $("#password1").val();
var password2 = $("#password2").val();
if (password1 != "" && password1 != password2)
$("#password2").addClass("error");
else
$("#password2").removeClass("error");
});
$("#installer").on("submit", function(e) {
var password1 = $("#password1").val();
var password2 = $("#password2").val();
if (password1 != password2) {
e.preventDefault();
alert('<?php echo __("Passwords do not match."); ?>');
}
});
$("#url").keyup(function(e) {
var text = $(this).val();
if (text != "" && !isURL(text))
$(this).addClass("error");
else
$(this).removeClass("error");
});
$("#url").on("change", function(e) {
var text = $(this).val();
if (isURL(text))
$(this).val(addScheme(text));
});
$("#email").keyup(function(e) {
var text = $(this).val();
if (text != "" && !isEmail(text))
$(this).addClass("error");
else
$(this).removeClass("error");
});
$("#locale").change(function(e) {
$("#installer").submit();
});
});
</script>
</head>
<body>
<div class="window">
<pre class="pane"><?php
#---------------------------------------------
# Installation Starts
#---------------------------------------------
if (isset($_POST['install']) and $_POST['install'] == "yes") {
if (empty($_POST['database']))
alert(__("Database cannot be blank."));
if (empty($_POST['url']))
alert(__("Chyrp URL cannot be blank."));
elseif (!is_url($_POST['url']))
alert(__("Invalid Chyrp URL."));
if (empty($_POST['name']))
alert(__("Please enter a name for your website."));
if (empty($_POST['timezone']))
alert(__("Time zone cannot be blank."));
if (empty($_POST['locale']))
alert(__("Language cannot be blank."));
if (empty($_POST['login']))
alert(__("Please enter a username for your account."));
if (empty($_POST['password1']) or empty($_POST['password2']))
alert(__("Passwords cannot be blank."));
elseif ($_POST['password1'] != $_POST['password2'])
alert(__("Passwords do not match."));
if (empty($_POST['email']))
alert(__("Email address cannot be blank."));
elseif (!is_email($_POST['email']))
alert(__("Invalid email address."));
if (!alert() and $_POST['adapter'] == "sqlite") {
$realpath = realpath(dirname($_POST['database']));
if ($realpath === false)
alert(__("Could not determine the absolute path to the database."));
else
$_POST['database'] = $realpath.DIR.basename($_POST['database']);
}
if (!alert() and $_POST['adapter'] == "sqlite")
if (!is_writable(dirname($_POST['database'])))
alert(__("Please make the database writable by the server."));
if (!alert() and $_POST['adapter'] != "sqlite")
if (empty($_POST['username']) or empty($_POST['password']))
alert(__("Please enter a username and password for the database."));
if (!alert()) {
# Build the SQL settings based on user input.
$settings = ($_POST['adapter'] == "sqlite") ?
array(
"host" => "",
"port" => "",
"username" => "",
"password" => "",
"database" => $_POST['database'],
"prefix" => "",
"adapter" => $_POST['adapter']
)
:
array(
"host" => $_POST['host'],
"port" => $_POST['port'],
"username" => $_POST['username'],
"password" => $_POST['password'],
"database" => $_POST['database'],
"prefix" => $_POST['prefix'],
"adapter" => $_POST['adapter']
)
;
# Configure the SQL interface.
$sql = SQL::current($settings);
# Test the database connection.
if (!$sql->connect(true))
alert(_f("Database error: %s", fix($sql->error, false, true)));
}
if (!alert()) {
# Reconnect to the database.
$sql->connect();
# Posts table.
$sql->create(
table:"posts",
cols:array(
"id INTEGER PRIMARY KEY AUTO_INCREMENT",
"feather VARCHAR(32) DEFAULT ''",
"clean VARCHAR(128) DEFAULT ''",
"url VARCHAR(128) DEFAULT ''",
"pinned BOOLEAN DEFAULT FALSE",
"status VARCHAR(32) DEFAULT 'public'",
"user_id INTEGER DEFAULT 0",
"created_at DATETIME DEFAULT NULL",
"updated_at DATETIME DEFAULT NULL"
)
);
# Post attributes table.
$sql->create(
table:"post_attributes",
cols:array(
"post_id INTEGER NOT NULL",
"name VARCHAR(100) DEFAULT ''",
"value LONGTEXT",
"PRIMARY KEY (post_id, name)"
)
);
# Pages table.
$sql->create(
table:"pages",
cols:array(
"id INTEGER PRIMARY KEY AUTO_INCREMENT",
"title VARCHAR(250) DEFAULT ''",
"body LONGTEXT",
"public BOOLEAN DEFAULT '1'",
"show_in_list BOOLEAN DEFAULT '1'",
"list_order INTEGER DEFAULT 0",
"clean VARCHAR(128) DEFAULT ''",
"url VARCHAR(128) DEFAULT ''",
"user_id INTEGER DEFAULT 0",
"parent_id INTEGER DEFAULT 0",
"created_at DATETIME DEFAULT NULL",
"updated_at DATETIME DEFAULT NULL"
)
);
# Users table.
$sql->create(
table:"users",
cols:array(
"id INTEGER PRIMARY KEY AUTO_INCREMENT",
"login VARCHAR(64) DEFAULT ''",
"password VARCHAR(128) DEFAULT ''",
"full_name VARCHAR(250) DEFAULT ''",
"email VARCHAR(128) DEFAULT ''",
"website VARCHAR(128) DEFAULT ''",
"group_id INTEGER DEFAULT 0",
"approved BOOLEAN DEFAULT '1'",
"joined_at DATETIME DEFAULT NULL",
"UNIQUE (login)"
)
);
# Groups table.
$sql->create(
table:"groups",
cols:array(
"id INTEGER PRIMARY KEY AUTO_INCREMENT",
"name VARCHAR(100) DEFAULT ''",
"UNIQUE (name)"
)
);
# Permissions table.
$sql->create(
table:"permissions",
cols:array(
"id VARCHAR(100) DEFAULT ''",
"name VARCHAR(100) DEFAULT ''",
"group_id INTEGER DEFAULT 0",
"PRIMARY KEY (id, group_id)"
)
);
# Sessions table.
$sql->create(
table:"sessions",
cols:array(
"id VARCHAR(40) DEFAULT ''",
"data LONGTEXT",
"user_id INTEGER DEFAULT 0",
"created_at DATETIME DEFAULT NULL",
"updated_at DATETIME DEFAULT NULL",
"PRIMARY KEY (id)"
)
);
# Define and insert the default permissions.
$names = array(
"change_settings" => "Change Settings",
"toggle_extensions" => "Toggle Extensions",
"view_site" => "View Site",
"view_private" => "View Private Posts",
"view_scheduled" => "View Scheduled Posts",
"view_draft" => "View Drafts",
"view_own_draft" => "View Own Drafts",
"add_post" => "Add Posts",
"add_draft" => "Add Drafts",
"edit_post" => "Edit Posts",
"edit_draft" => "Edit Drafts",
"edit_own_post" => "Edit Own Posts",
"edit_own_draft" => "Edit Own Drafts",
"delete_post" => "Delete Posts",
"delete_draft" => "Delete Drafts",
"delete_own_post" => "Delete Own Posts",
"delete_own_draft" => "Delete Own Drafts",
"view_page" => "View Pages",
"add_page" => "Add Pages",
"edit_page" => "Edit Pages",
"delete_page" => "Delete Pages",
"add_user" => "Add Users",
"edit_user" => "Edit Users",
"delete_user" => "Delete Users",
"add_group" => "Add Groups",
"edit_group" => "Edit Groups",
"delete_group" => "Delete Groups",
"import_content" => "Import Content",
"export_content" => "Export Content"
);
# Delete all existing permissions.
$sql->delete(
table:"permissions",
conds:false
);
# Insert the new default permissions.
foreach ($names as $id => $name)
$sql->insert(
table:"permissions",
data:array(
"id" => $id,
"name" => $name,
"group_id" => 0
)
);
# Define and insert the default groups.
$groups = array(
"Admin" => array_keys($names),
"Member" => array("view_site"),
"Friend" => array(
"view_site",
"view_private",
"view_scheduled"
),
"Banned" => array(),
"Guest" => array("view_site")
);
$group_id = array();
foreach ($groups as $name => $permissions) {
# Insert the group if it does not exist.
if (
!$sql->count(
tables:"groups",
conds:array("name" => $name)
)
)
$sql->insert(
table:"groups",
data:array("name" => $name)
);
# Fetch the group's ID for permission creation.
$group_id[$name] = $sql->select(
tables:"groups",
fields:"id",
conds:array("name" => $name),
)->fetchColumn();
# Insert the new permissions for this group.
foreach ($permissions as $permission)
$sql->insert(
table:"permissions",
data:array(
"id" => $permission,
"name" => $names[$permission],
"group_id" => $group_id[$name]
)
);
}
# Add the admin user account if it does not exist.
if (
!$sql->count(
tables:"users",
conds:array("login" => $_POST['login'])
)
)
$sql->insert(
table:"users",
data:array(
"login" => $_POST['login'],
"password" => User::hash_password($_POST['password1']),
"email" => $_POST['email'],
"group_id" => $group_id["Admin"],
"approved" => true,
"joined_at" => datetime()
)
);
# Normalize the Chyrp URL.
$chyrp_url = rtrim(add_scheme($_POST['url']), "/");
# Build the configuration file.
$set = array(
$config->set("sql", $settings),
$config->set("name", strip_tags($_POST['name'])),
$config->set("description", strip_tags($_POST['description'])),
$config->set("url", $chyrp_url),
$config->set("chyrp_url", $chyrp_url),
$config->set("email", $_POST['email']),
$config->set("timezone", $_POST['timezone']),
$config->set("locale", $_POST['locale']),
$config->set("monospace_font", false),
$config->set("check_updates", true),
$config->set("check_updates_last", 0),
$config->set("theme", "blossom"),
$config->set("posts_per_page", 5),
$config->set("admin_per_page", 25),
$config->set("feed_format", "AtomFeed"),
$config->set("feed_items", 20),
$config->set("uploads_path", DIR."uploads".DIR),
$config->set("uploads_limit", 10),
$config->set("search_pages", false),
$config->set("send_pingbacks", false),
$config->set("enable_emoji", true),
$config->set("enable_markdown", true),
$config->set("can_register", false),
$config->set("email_activation", false),
$config->set("email_correspondence", true),
$config->set("default_group", $group_id["Member"]),
$config->set("guest_group", $group_id["Guest"]),
$config->set("clean_urls", false),
$config->set("enable_homepage", false),
$config->set("post_url", "(year)/(month)/(day)/(url)/"),
$config->set("enabled_modules", array()),
$config->set("enabled_feathers", array("text")),
$config->set("routes", array()),
$config->set("secure_hashkey", random(32))
);
if (in_array(false, $set, true))
error(
__("Error"),
__("Could not write the configuration file.")
);
@unlink(INCLUDES_DIR.DIR."upgrading.lock");
$installed = true;
}
}
#---------------------------------------------
# Installation Ends
#---------------------------------------------
foreach ((array) alert() as $message)
echo '<span role="alert">'.sanitize_html($message).'</span>'."\n";
?></pre>
<?php if (!$installed): ?>
<form action="install.php" method="post" accept-charset="UTF-8" id="installer">
<h1><?php echo __("Database Setup"); ?></h1>
<p id="adapter_field">
<label for="adapter"><?php echo __("Adapter"); ?></label>
<select name="adapter" id="adapter">
<?php if (in_array("sqlite", $drivers)): ?>
<option value="sqlite"<?php selected("sqlite", $adapter); ?>>SQLite</option>
<?php endif; ?>
<?php if (in_array("mysql", $drivers)): ?>
<option value="mysql"<?php selected("mysql", $adapter); ?>>MySQL</option>
<?php endif; ?>
<?php if (in_array("pgsql", $drivers)): ?>
<option value="pgsql"<?php selected("pgsql", $adapter); ?>>PostgreSQL</option>
<?php endif; ?>
</select>
</p>
<p id="host_field" class="not-sqlite">
<label for="host"><?php echo __("Host"); ?></label>
<input type="text" name="host" value="<?php posted("host", (isset($_ENV['DATABASE_SERVER']) ? $_ENV['DATABASE_SERVER'] : "localhost")); ?>" id="host">
</p>
<p id="port_field" class="not-sqlite">
<label for="port"><?php echo __("Port"); ?> <span class="sub"><?php echo __("(optional)"); ?></span></label>
<input type="text" name="port" value="<?php posted("port"); ?>" id="port">
</p>
<p id="username_field" class="not-sqlite">
<label for="username"><?php echo __("Username"); ?></label>
<input type="text" name="username" value="<?php posted("username"); ?>" id="username">
</p>
<p id="password_field" class="not-sqlite">
<label for="password"><?php echo __("Password"); ?></label>
<input type="password" name="password" value="<?php posted("password"); ?>" id="password">
</p>
<p id="database_field">
<label for="database"><?php echo __("Database"); ?>
<span id="database_sub" class="sub not-mysql not-pgsql">
<?php echo __("(absolute or relative path)"); ?>
</span>
</label>
<input type="text" name="database" value="<?php posted("database"); ?>" id="database">
</p>
<aside id="db_aside_pgsql" class="not-sqlite not-mysql">
<?php echo __("Make sure your PostgreSQL database uses UTF-8 encoding."); ?>
</aside>
<aside id="db_aside_mysql" class="not-sqlite not-pgsql">
<?php echo __("The collation <code>utf8mb4_general_ci</code> is recommended for your MySQL database."); ?>
</aside>
<aside id="db_aside_sqlite" class="not-mysql not-pgsql">
<?php echo __("Be sure to put your SQLite database outside the document root directory, otherwise visitors will be able to download it."); ?>
</aside>
<p id="prefix_field">
<label for="prefix"><?php echo __("Table Prefix"); ?> <span class="sub"><?php echo __("(optional)"); ?></span></label>
<input type="text" name="prefix" value="<?php posted("prefix"); ?>" id="prefix">
</p>
<h1><?php echo __("Website Setup"); ?></h1>
<p id="url_field">
<label for="url"><?php echo __("Chyrp URL"); ?></label>
<input type="url" name="url" value="<?php posted("url", $url); ?>" id="url">
</p>
<p id="name_field">
<label for="name"><?php echo __("Site Name"); ?></label>
<input type="text" name="name" value="<?php posted("name", __("My Awesome Site")); ?>" id="name">
</p>
<p id="description_field">
<label for="description"><?php echo __("Description"); ?></label>
<input type="text" name="description" value="<?php posted("description"); ?>" id="description">
</p>
<p id="timezone_field">
<label for="timezone"><?php echo __("Time Zone"); ?></label>
<select name="timezone" id="timezone">
<?php foreach (timezones() as $timezones): ?>
<option value="<?php echo $timezones['code']; ?>"<?php selected($timezones['code'], $timezone); ?>>
<?php echo $timezones['name']; ?>
</option>
<?php endforeach; ?>
</select>
</p>
<p id="locale_field">
<label for="locale"><?php echo __("Language"); ?></label>
<select name="locale" id="locale">
<?php foreach (locales() as $locales): ?>
<option value="<?php echo $locales['code']; ?>"<?php selected($locales['code'], $locale); ?>>
<?php echo $locales['name']; ?>
</option>
<?php endforeach; ?>
</select>
</p>
<h1><?php echo __("Admin Account"); ?></h1>
<p id="login_field">
<label for="login"><?php echo __("Username"); ?></label>
<input type="text" name="login" value="<?php posted("login", "Admin"); ?>" id="login" maxlength="64">
</p>
<p id="password1_field">
<label for="password1"><?php echo __("Password"); ?></label>
<input type="password" name="password1" value="<?php posted("password1"); ?>" id="password1" maxlength="128">
</p>
<p id="password2_field">
<label for="password2"><?php echo __("Password"); ?> <span class="sub"><?php echo __("(again)"); ?></span></label>
<input type="password" name="password2" value="<?php posted("password2"); ?>" id="password2" maxlength="128">
</p>
<p id="email_field">
<label for="email"><?php echo __("Email Address"); ?></label>
<input type="email" name="email" value="<?php posted("email"); ?>" id="email" maxlength="128">
</p>
<button type="submit" name="install" value="yes"><?php echo __("Install me!"); ?></button>
</form>
<?php else: ?>
<h1><?php echo __("Installation Complete"); ?></h1>
<h2><?php echo __("What now?"); ?></h2>
<ol>
<li><?php echo __("Delete <em>install.php</em>, you won't need it anymore."); ?></li>
<li><?php echo __("Log in to your site and configure things to your liking."); ?></a></li>
</ol>
<hr>
<a class="big" href="<?php echo $config->url.'/'; ?>"><?php echo __("Take me to my site!"); ?></a>
<?php endif; ?>
</div>
</body>
</html>