#!/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 <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 => <{admin_root_path}/defs/.
Please make sure this directory exists, and is writeable by the server.
If this is the wrong directory, you will need to manually set the directory
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:
$output
" } ]); } 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; } } }