#!/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: admin.cgi,v 1.94 2009/05/12 01:09:13 brewt Exp $
#
# Copyright (c) 2005 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/:objects/;

$| = 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.
#
    if (! $CFG->{setup}) {
        $IN->param('do', 'page');
        $IN->param('page', 'setup_first.html');
    }
    my $do     = $IN->param('do')       || '';
    my $action = $IN->param('action')   || '';

# Default to home page.
    unless ($do or $action) {
        if ($IN->param('page')) {
            $do = 'page';
        }
        else {
            $IN->param('page', 'home.html');
            $do = 'page';
        }
    }

# Otherwise, try some common cases.
    CASE: {
        ($do eq 'page')             and Links::admin_page(),    last CASE;
        ($do eq 'help')             and help(),                 last CASE;
        ($do eq 'plugin')           and plugin(),               last CASE;
        ($do eq 'fileman')          and fileman(),              last CASE;
        ($do eq 'fileman_diff')     and fileman_diff(),         last CASE;

# Database Browser
        $do and db_request()                                and last CASE;

# Category Browser.
        $action and brow_request()                          and last CASE;

# Mass Mailer
        $action and mailer_request()                        and last CASE;

# Invalid method.
        die "Invalid Request: '$do' '$action'";
    }
}

sub db_request {
# ------------------------------------------------------------------
# Handles a GT::SQL::Admin request.
#
    require Links::Admin;
    my $admin = new Links::Admin;

    if ($admin->for_me($IN)) {
        $admin->debug_level( $CFG->{debug_level} );
        $admin->process ( db => $DB, cgi => $IN );
        return 1;
    }
    else {
        return;
    }
}

sub brow_request {
# ------------------------------------------------------------------
# Handle the browser request.
#
    $IN->delete('anticache');

# Get a controller to manage access.
    require Links::Browser;
    my $crtl = new Links::Browser::Controller;

# Load the tree if it is under 200 categories.
    $crtl->{load_tree}       = 1;
    $crtl->{admin}           = 1;
    $crtl->{admin_templates} = 1;

# Begin the script.
    my $method = $crtl->can_run;
    if ($method) {
        my $browser = new Links::Browser(ctrl => $crtl);
        $PLG->dispatch("browser_$method", sub { $browser->$method(); }, $browser);
        return 1;
    }
    else {
        return;
    }
}

sub mailer_request {
# ------------------------------------------------------------------
# Determine if this is for the Links::MassMailer.
#
    require Links::MassMailer;
    my $action;
    my @actions = $IN->param('action');
    if (@actions > 1) {
        @actions = grep ! /^(?:Send|selected_(?:users|links)_send)$/, @actions;
    }
    $action = $actions[0];

    $action = "SaveAs" if $action eq "Save as..."; # No spaces or .'s allowed in subroutine names!
    if (exists $ACTIONS::{$action} and ref *{$ACTIONS::{$action}}{CODE} eq 'CODE') {
        *{$ACTIONS::{$action}}{CODE}->();
        return 1;
    }
    else {
        return;
    }
}

sub help {
# ------------------------------------------------------------------
# Print the help pages.
#
    my $help_path  = "$CFG->{admin_root_path}/templates/admin/help";
    my $topic      = $IN->param('topic');
    if (! $topic) {
        my $url    = $IN->param('topic_url');
        my ($do)   = $url =~ /do=([^&]+)/;
        my ($page) = $url =~ /page=([^&]+)/;
        my ($cgi)  = $url =~ /([^\/]+)\.cgi/;

        if ($do and $do eq 'plugin') {
            my ($plugin) = $url =~ /plugin=([^&]+)/;
            my ($func)   = $url =~ /func=([^&]+)/;
            if ($topic = _plugin_help($plugin, $func)) {
                $help_path .= "/$plugin";
            }
        }
        else {
            $topic   = _parse_topic($page || '');
            $topic ||= _parse_topic($do   || '');
            $topic ||= _parse_topic($cgi  || '');
        }
    }
    $topic   ||= 'help_toc.html';
    $topic =~ s,^/|/$,,;

# Check the topic file.
    unless ($topic =~ /^[\w\/]+\.[\w]+$/) {
        die "Invalid topic: $topic";
    }
    if ($topic =~ /\.(gif|jpg)$/ and -e "$help_path/$topic") {
        print $IN->header("image/$1");
        open IMG, "< $help_path/$topic" or die "Unable to open image help: $help_path/$topic ($!)";
        binmode IMG;
        binmode STDOUT;
        while (read (IMG, my $buffer, 65356)) {
            print $buffer;
        }
        close IMG;
    }
    else {
        print $IN->header;
        GT::Template->parse($topic, $IN, { root => $help_path, print => 1 });
    }
}

sub plugin {
# ------------------------------------------------------------------
# Run a plugin function.
#
    my $plugin = $IN->param('plugin');
    if ($IN->param('download') and ($plugin =~ /^[\w\-]+$/)) {
        my $path = "$CFG->{admin_root_path}/Plugins/Uninstalled/$plugin.tar";
        -e $path or die "No plugin ($path) found.";
        open FH, $path or die "Could not open $path for reading";
        print $IN->header($IN->file_headers(
            filename => "$plugin.tar",
            mimetype => 'application/x-tar',
            inline   => 0,
            size     => -s $path
        ));
        print while <FH>;
        close FH;
        return 1;
    }
    my $func   = $IN->param('func');
    {
        eval { require "Plugins/$plugin.pm"; };
        if ($@) {
            die "Unable to load plugin: $plugin ($@)";
        }
    }
    no strict 'refs';
    my $code = ${"Plugins::" . $plugin . "::"}{$func};
    use strict 'refs';

    if (!defined $code) {
        die "Invalid plugin function: $func";
    }
    $code->();
}

sub fileman {
# ------------------------------------------------------------------
# Load our file manager.
#

    require GT::FileMan;
    my $fileman = GT::FileMan->new(
        cfg => {
            template_root => "$CFG->{admin_root_path}/templates/admin/fileman",
            tmp_path      => "$CFG->{admin_root_path}/tmp",
            root_path     => $CFG->{fileman_root_dir} || $CFG->{admin_root_path},
            cgi_url       => "$CFG->{admin_root_url}/admin.cgi",
            static_url    => "$CFG->{build_static_url}/fileman",
            debug_level   => $CFG->{debug_level},
        },
        url_opts => 'do=fileman'
    );
    $fileman->process;
}

sub fileman_diff {
# ------------------------------------------------------------------
# Load fileman, but just for the purposes of displaying a diff.
#
    my $template = $IN->param('template');
    my $file = $IN->param('file');

    require GT::FileMan::Diff;
    my $diff = GT::FileMan::Diff::html_diff("$CFG->{admin_root_path}/templates/$template/$file", "$CFG->{admin_root_path}/templates/$template/local/$file", 3);

    print $IN->header();
    print '<html><title>' . $IN->html_escape($template) . ' template diffs: ' . $IN->html_escape($file) . '</title><body>';
    if (ref $diff) {
        print $$diff;
    }
    else {
        print "File(s) not found.";
    }
    print '</body></html>';
}

sub _parse_topic {
# ------------------------------------------------------------------
# Takes a keyword and tries to find a help page for it.
#
    local $_ = shift;
    CASE: {
        /browse/        and return 'help_browse.html';
        /build/         and return 'help_build.html';
        /email/         and return 'help_email.html';
        /mailer/        and return 'help_email.html';
        /payment/       and return 'help_payments.html';
        /plugin_editor/ and return 'help_plugin_guide.html';
        /plugin_list/   and return 'help_plugin_manager.html';
        /plugin/        and return 'help_plugins.html';
        /db/            and return 'help_database.html';
    }
    return;
}

sub _plugin_help {
# ------------------------------------------------------------------
    my ( $plugin, $func ) = @_;
    my $help_path = "$CFG->{admin_root_path}/templates/help/$plugin";

    -e $help_path or return;

    if ( -e "$help_path/$func.html" ) {
        return "$func.html";
    }
    elsif ( -e "$help_path/help.html" ) {
        return "help.html";
    }

    return;
}


