452 lines
15 KiB
Perl
Executable File
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;
|
|
}
|
|
}
|
|
}
|