discourse-legacysite-perl/site/slowtwitch.com/cgi-bin/articles/admin/setup.cgi
2024-06-17 21:49:12 +10:00

452 lines
15 KiB
Perl
Executable File

#!/usr/local/bin/perl
# ==================================================================
# Gossamer Links - enhanced directory management system
#
# Website : http://gossamer-threads.com/
# Support : http://gossamer-threads.com/scripts/support/
# CVS Info : 087,071,086,086,085
# Revision : $Id: setup.cgi,v 1.89 2009/05/08 19:56:50 brewt Exp $
#
# Copyright (c) 2001 Gossamer Threads Inc. All Rights Reserved.
# Redistribution in part or in whole strictly prohibited. Please
# see LICENSE file for full details.
# ==================================================================
use strict;
use lib '/var/home/slowtwitch/slowtwitch.com/cgi-bin/articles/admin';
use Links qw/$IN $CFG $DB %STASH/;
use Links::SQL;
$| = 1;
local $SIG{__DIE__} = \&Links::fatal;
Links::init('/var/home/slowtwitch/slowtwitch.com/cgi-bin/articles/admin');
Links::init_admin();
main();
sub main {
# ------------------------------------------------------------------
# Main admin loop, displays html pages and other admin tasks.
#
# Make sure we are only run from the web.
if (! defined $ENV{REQUEST_METHOD}) {
print "\nThis script can only be accessed from your browser.\n\n";
if ($CFG->{admin_root_url}) {
print "Try visiting:\n\t$CFG->{admin_root_url}/setup.cgi\n\n";
}
return;
}
# If we don't have anything to do, and aren't setup yet, go to setup_first template.
if (! $IN->param('do') and ! $CFG->{setup}) {
$IN->param('do', 'page');
$IN->param('page', 'setup_first.html');
}
# If we can't find the admin templates, perhaps the path is screwed, try to
# reset it.
if (! -e "$CFG->{admin_root_path}/templates/admin") {
die 'Configured admin path does not appear to be valid!';
}
# Otherwise do the command or display the setup frameset.
my $action = $IN->param('do') || 'disp_home';
no strict 'refs'; my %subs = %{__PACKAGE__ . "::"}; use strict 'refs';
if (exists $subs{$action}) {
$subs{$action}->();
}
elsif ($action eq 'page') {
Links::admin_page();
}
else {
die "Invalid Request: '$action'";
}
}
sub setup_sql {
# ------------------------------------------------------------------
# Change the sql server information.
#
my ($host, $port, $output, $action, $ret);
$action = $IN->param('action');
print $IN->header();
if ($action !~ /^create|overwrite|load$/) {
return Links::admin_page('setup_sql.html', [ $IN, { error => "Invalid action: '$action'" }]);
}
$host = $IN->param('host');
($host =~ s/\:(\d+)$//) and ($port = $1);
my $prefix = $IN->param('prefix');
$prefix =~ /^\w*$/ or return Links::admin_page('setup_sql.html', [ $IN, { error => "Invalid prefix: '$prefix'. Can only be letters, numbers and underscore." } ]);
$DB->prefix($prefix);
$ret = $DB->set_connect({
driver => scalar $IN->param('driver'),
host => $host,
port => $port,
database => scalar $IN->param('database'),
login => scalar $IN->param('login'),
password => scalar $IN->param('password'),
RaiseError => 0,
PrintError => 0
});
if (! defined $ret) {
return Links::admin_page('setup_sql.html', [$IN, { error => $GT::SQL::error }]);
}
if ($action eq 'create') {
$output = Links::SQL::tables('check');
}
elsif ($action eq 'overwrite') {
$output = Links::SQL::tables('force');
# Create the admin user.
my $db = $DB->table('Users');
my $pass = join '', map { chr(65 + rand 57) } 1 .. 8;
$db->insert({ Username => 'admin', Password => $pass, Email => $CFG->{db_admin_email}, ReceiveMail => 'No', Status => 'Administrator' });
}
elsif ($action eq 'load') {
$output = Links::SQL::load_from_sql();
}
Links::admin_page('setup_sql.html', [$IN, { message_pre => $output }]);
}
sub setup_path {
# ------------------------------------------------------------------
# Set the path information.
#
print $IN->header();
if ($IN->param('reset_defaults')) {
$CFG->default_path(0);
}
else {
_update_cfg();
if ($IN->param('update_others')) {
$CFG->{build_images_url} = "$CFG->{build_root_url}/images";
$CFG->{build_css_url} = "$CFG->{build_root_url}/links.css";
$CFG->{build_new_path} = "$CFG->{build_root_path}/New";
$CFG->{build_new_url} = "$CFG->{build_root_url}/New";
$CFG->{build_cool_path} = "$CFG->{build_root_path}/Cool";
$CFG->{build_cool_url} = "$CFG->{build_root_url}/Cool";
$CFG->{build_ratings_path} = "$CFG->{build_root_path}/Ratings";
$CFG->{build_ratings_url} = "$CFG->{build_root_url}/Ratings";
$CFG->{build_detail_path} = "$CFG->{build_root_path}/Detailed";
$CFG->{build_detail_url} = "$CFG->{build_root_url}/Detailed";
}
}
$CFG->save();
Links::admin_page('setup_path.html', [$IN, { message => "All paths and URL's have been updated successfully." }]);
}
sub setup_build {
# ------------------------------------------------------------------
# Set the build information.
#
print $IN->header();
if ($IN->param('reset_defaults')) {
$CFG->default_build(1);
}
else {
_update_cfg();
}
$CFG->save();
Links::admin_page('setup_build.html', [$IN, { message => "All build options have been updated successfully." }]);
}
sub setup_user {
# ------------------------------------------------------------------
# Set the user information.
#
print $IN->header();
if ($IN->param('reset_defaults')) {
$CFG->default_user(1);
}
else {
_update_cfg();
}
$CFG->save();
Links::admin_page('setup_user.html', [$IN, { message => "All user options have been updated successfully." }]);
}
sub setup_email {
# ------------------------------------------------------------------
# Set the email information.
#
print $IN->header();
if ($IN->param('db_mail_path') and $IN->param('db_smtp_server')) {
Links::admin_page('setup_email.html', [$IN, { message => "You can not specify both an SMTP server and a path to sendmail!" }]);
return;
}
if ($IN->param('reset_defaults')) {
$CFG->default_email(1);
}
else {
_update_cfg();
}
$CFG->save();
Links::admin_page('setup_email.html', [$IN, { message => "All email options have been updated successfully." }]);
}
sub setup_search {
# ------------------------------------------------------------------
# Set the email information.
#
print $IN->header();
if ($IN->param('reset_defaults')) {
$CFG->default_search(1);
}
else {
_update_cfg();
}
$CFG->save();
Links::admin_page('setup_search.html', [$IN, { message => "All search options have been updated successfully." }]);
}
sub setup_review {
# ------------------------------------------------------------------
# Set the review information.
#
print $IN->header();
if ($IN->param('reset_defaults')) {
$CFG->default_review(1);
}
else {
_update_cfg();
}
$CFG->save();
Links::admin_page('setup_review.html', [$IN, { message => "All review options have been updated successfully. " }]);
}
sub setup_date {
# ------------------------------------------------------------------
# Set the date information.
#
print $IN->header();
if ($IN->param('reset_defaults')) {
$CFG->default_date(1);
}
else {
_update_cfg();
}
$CFG->save();
# Reload the date module.
delete $STASH{date_loaded};
Links::init_date;
Links::admin_page('setup_date.html', [$IN, { message => "All date options have been updated successfully." }]);
}
sub setup_misc {
# ------------------------------------------------------------------
# Set the misc information.
#
print $IN->header();
if ($IN->param('reset_defaults')) {
$CFG->default_misc(1);
}
else {
_update_cfg();
}
$CFG->save();
Links::admin_page('setup_misc.html', [$IN, { message => "All misc options have been updated successfully." }]);
}
sub setup_pass {
# ------------------------------------------------------------------
# Creates the .htaccess/.htpasswd file.
#
print $IN->header();
my $htpasswd = $CFG->{admin_root_path} . "/.htpasswd";
my $htaccess = $CFG->{admin_root_path} . "/.htaccess";
unless (-w $htaccess and -w $htpasswd) {
Links::admin_page('setup_pass.html', [$IN, { error => "Sorry, but we don't have write access to the htaccess files: '$htaccess' and '$htpasswd'." }]);
return;
}
my $username = $IN->param('admin_username');
my $password = $IN->param('admin_password');
my $password2 = $IN->param('admin_password_confirm');
my $to_delete = $IN->param('delete') ? $IN->param('delete_user') : $username;
if ($password and $password ne $password2) {
Links::admin_page('setup_pass.html', [$IN, { error => "Your passwords do not match." }]);
return;
}
my $fh = \do { local *FH; *FH };
open $fh, "< $htpasswd" or die "Unable to open '$htpasswd': $!";
my @lines = <$fh>;
close $fh;
@lines = grep ! /^\Q$to_delete\E:/, @lines if $to_delete;
if ($username and $password) {
require GT::MD5::Crypt;
my $salt = join '', ('A' .. 'Z', 0 .. 9, 'a' .. 'z', '.', '/')[map rand 64, 1 .. 8];
my $crypted = GT::MD5::Crypt::apache_md5_crypt($password, $salt);
push @lines, "$username:$crypted\n";
}
if (@lines and -z $htaccess) {
_create_htaccess($htaccess, $htpasswd);
}
elsif (!@lines and -s $htaccess) {
open $fh, "> $htaccess";
close $fh;
}
open $fh, "> $htpasswd" or die "Unable to open '$htpasswd': $!";
print $fh @lines if @lines;
close $fh;
Links::admin_page('setup_pass.html', [$IN, { message => "Your directory is now password protected. The next screen you visit, you should be prompted for a password." } ]);
}
sub _create_htaccess {
# ------------------------------------------------------------------
# Creates the htaccess file.
#
my ($htaccess, $htpasswd) = @_;
open HTAC, "> $htaccess" or die "Unable to open '$htaccess': $!";
print HTAC <<HTACCESS;
AuthUserFile $htpasswd
AuthGroupFile /dev/null
AuthType Basic
AuthName Protected
require valid-user
HTACCESS
close HTAC;
}
sub init_setup {
# ------------------------------------------------------------------
# Sets the mysql information.
#
my ($host, $port, $overwrite);
print $IN->header();
# Test the ability to create a def file.
unless (open TEST, "> $CFG->{admin_root_path}/defs/database.def") {
return Links::admin_page('setup_second.html', [$IN, { error => <<HTML }]);
Unable to create our def file in $CFG->{admin_root_path}/defs/. <br />
Please make sure this directory exists, and is writeable by the server. <br />
If this is the wrong directory, you will need to manually set the directory <br />
in Links::Config::Data. Error was: $!
HTML
}
close TEST;
unlink "$CFG->{admin_root_path}/defs/database.def";
# Set the connection info.
$overwrite = $IN->param('overwrite') ? 'force' : 'check';
$host = $IN->param('host');
($host =~ s/\:(\d+)$//) and ($port = $1);
my $prefix = $IN->param('prefix');
$prefix =~ /^\w*$/ or return Links::admin_page('setup_sql.html', [ $IN, { error => "Invalid prefix: '$prefix'. Can only be letters, numbers and underscore." } ]);
$DB->prefix($prefix);
my $ret = $DB->set_connect({
driver => scalar $IN->param('driver'),
host => $host,
port => $port,
database => scalar $IN->param('database'),
login => scalar $IN->param('login'),
password => scalar $IN->param('password'),
RaiseError => 0,
PrintError => 0
});
if (! defined $ret) {
return Links::admin_page('setup_second.html', [$IN, { error => $GT::SQL::error }]);
}
# Now let's create the tables.
eval { local $SIG{__DIE__}; require Links::SQL; };
if ($@) { return Links::admin_page('setup_second.html', [ $IN, { error => "Unable to load Links::SQL module: $@\n" }]); }
my $output = Links::SQL::tables($overwrite);
# Update other paths and URL's.
$CFG->{build_css_url} = "$CFG->{build_root_url}/links.css";
$CFG->{build_new_path} = "$CFG->{build_root_path}/New";
$CFG->{build_new_url} = "$CFG->{build_root_url}/New";
$CFG->{build_cool_path} = "$CFG->{build_root_path}/Cool";
$CFG->{build_cool_url} = "$CFG->{build_root_url}/Cool";
$CFG->{build_ratings_path} = "$CFG->{build_root_path}/Ratings";
$CFG->{build_ratings_url} = "$CFG->{build_root_url}/Ratings";
$CFG->{build_detail_path} = "$CFG->{build_root_path}/Detailed";
$CFG->{build_detail_url} = "$CFG->{build_root_url}/Detailed";
$CFG->{build_images_url} = "$CFG->{build_root_url}/images";
# Create the admin user.
my $db = $DB->table('Users');
my $pass = $db->random_pass;
$db->insert({ Username => 'admin', Password => $pass, Email => $CFG->{db_admin_email}, ReceiveMail => 'No', Status => 'Administrator' });
# And lets set sensible defaults for the rest of the config vars.
$CFG->create_defaults();
# And save the config.
$CFG->save();
Links::admin_page('setup_third.html', [ $IN, { message => "The data tables have been setup: <pre>$output</pre>" } ]);
}
sub disp_home {
# ------------------------------------------------------------------
# Display the home page.
#
print $IN->header();
Links::admin_page('setup.html', $IN);
}
sub reset_setup {
# ------------------------------------------------------------------
# Sets the cfg->{setup} to 0, and prints out the setup_first page.
#
print $IN->header();
$CFG->{setup} = 0;
$CFG->save;
Links::admin_page('setup_first.html', $IN);
}
sub _update_cfg {
# ------------------------------------------------------------------
# Updates the config based on the form input.
#
for my $param ($IN->param) {
next unless exists $CFG->{$param};
my $val = $IN->param($param);
if ($val eq 'custom' and my $custom = $IN->param("${param}_custom")) {
$CFG->{$param} = $custom;
}
elsif (ref $CFG->{$param} eq 'ARRAY') {
my @val = split /\s*[,\n]\s*/, $val;
$CFG->{$param} = \@val;
}
elsif (ref $CFG->{$param} eq 'HASH') {
my $h = {};
my @pairs = split /\s*[,\n]\s*/, $val;
foreach my $pair (@pairs) {
my ($k, $v) = split /\s*=>?\s*/, $pair;
$h->{$k} = $v;
}
$CFG->{$param} = $h;
}
else {
$CFG->{$param} = $val;
}
}
}