# ==================================================================
# 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: Add.pm,v 1.59 2007/12/20 20:31:35 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.
# ==================================================================

package Links::User::Add;
# ==================================================================
use strict;
use Links qw/:objects :payment/;
use Links::Build;
use Links::SiteHTML;

sub handle {
# -------------------------------------------------------------------
# Display either an add form or process an add request.
#
    if ($CFG->{user_required} and !$USER) {
        print $IN->redirect(Links::redirect_login_url('add'));
        return;
    }

    my $custom;
    if (exists $CFG->{payment}->{remote}->{used}->{PayPal} and $custom = $IN->param('custom') and substr($custom, 0, 3) eq 'do;') {
        substr($custom, 0, 3) = '';
        my @pairs = split /;/, $custom;
        for (@pairs) {
            my ($key, $val) = split /=/, $_;
            next unless $key and $val;
            $IN->param($key => $val) unless $IN->param($key);
        }
    }

    print $IN->header;

# We are processing an add request.
    if ($IN->param('add')) {
        my $results = $PLG->dispatch('user_add_link', \&add_link);
        if (defined $results->{error}) {
            print Links::SiteHTML::display('add', $results);
        }
        else {
            $results = Links::SiteHTML::tags('link', $results);
            $results->{main_title_loop} = Links::Build::build('title', Links::language('LINKS_ADD_SUCCESS'), "$CFG->{db_cgi_url}/add.cgi");
            if ($CFG->{payment}->{enabled}) {
                require Links::Payment;
                my @cats = $IN->param('CatLinks.CategoryID');
                my $opt = Links::Payment::load_cat_price(\@cats);
                if (exists $opt->{error}) {
                    print Links::SiteHTML::display('error', $opt);
                }
                elsif ($opt->{payment_mode} == NOT_ACCEPTED) {
                    if ($CFG->{admin_email_add}) {
                        Links::send_email('link_added.eml', $results, { admin_email => 1 }) or die "Unable to send mail: $GT::Mail::error";
                    }
                    print Links::SiteHTML::display('add_success', $results);
                }
                else {# payment option for this category is required or optional
                    $results->{link_id} = $results->{ID}; # we need a different tag since both Category and Link have ID
                    $opt->{CategoryID} = delete $opt->{ID}; # remove category id
                    $opt->{CategoryDescription} = delete $opt->{Description};
                    $results->{main_title_loop} = Links::Build::build('title', Links::language('LINKS_PAYMENT'), "$CFG->{db_cgi_url}/modify.cgi?do=payment_linked;process_payment=1;modify=1;ID=$results->{link_id}");
                    print Links::SiteHTML::display('payment', { %$results, %$opt });
                }
            }
            else {
                if ($CFG->{admin_email_add}) {
                    Links::send_email('link_added.eml', $results, { admin_email => 1 }) or die "Unable to send mail: $GT::Mail::error";
                }
                print Links::SiteHTML::display('add_success', $results);
            }
        }
    }
# We are processing a payment request.
    elsif ($IN->param('process_payment') and $CFG->{payment}->{enabled}) {
        my $payment_term = $IN->param('payment_term') || '';
        my $do = $IN->param('do');
        if ($payment_term eq 'free') {
            my $link = $DB->table('Links')->get($IN->param('link_id'));
            if (not $link or ($CFG->{user_required} and $link->{LinkOwner} ne $USER->{Username})) {
                print Links::SiteHTML::display('error', { error => !$link ? $GT::SQL::ERRORS : Links::language('PAYMENTERR_NOTOWNER') });
                return;
            };
            $link = Links::SiteHTML::tags('link', $link);

# Set ExpiryDate to free
            $link->{'CatLinks.CategoryID'} = $IN->param('cat_id');
            $link->{ExpiryDate} = FREE;
            $link->{ExpiryNotify}= 0;
# Update the link
            $DB->table('Links')->update({ ExpiryDate => FREE, ExpiryNotify => 0 }, { ID => $link->{ID} });
# Update the Timestmp for link's categories so they get rebuilt with build changed
            my @cats = $DB->table('Links', 'CatLinks')->select('CategoryID', { LinkID => $link->{ID} })->fetchall_list;
            $DB->table('Category')->update({ Timestmp => \'NOW()' }, { ID => \@cats });

# Add some special tags for formatting.
            @cats = $DB->table('Category', 'CatLinks')->select('Category.Full_Name', { 'CatLinks.LinkID' => $link->{ID} })->fetchall_list;
            $link->{Category}      = join "\n", sort @cats;
            $link->{Category_loop} = [sort @cats];
            $link->{Host}          = $ENV{REMOTE_HOST}  ? "$ENV{REMOTE_HOST} ($ENV{REMOTE_ADDR})" : $ENV{REMOTE_ADDR} ? $ENV{REMOTE_ADDR} : 'none';
            $link->{Referer}       = $ENV{HTTP_REFERER} ? $ENV{HTTP_REFERER} : 'none';
            $link->{AutoValidate}  = $CFG->{build_auto_validate};
            if ($CFG->{admin_email_add}) {
                Links::send_email('link_added.eml', $link, { admin_email => 1 }) or die "Unable to send mail: $GT::Mail::error";
            }
            $link->{main_title_loop} = Links::Build::build('title', Links::language('LINKS_ADD_SUCCESS'), "$CFG->{db_cgi_url}/add.cgi");
            print Links::SiteHTML::display('add_success', $link);
        }
        elsif ($IN->param('payment_success')) {
            print Links::SiteHTML::display('payment_success', { main_title_loop => Links::Build::build('title', Links::language('LINKS_PAYMENT_SUCCESS'), $CFG->{build_root_url} . "/" . ($CFG->{build_home} || ($CFG->{build_index_include} ? $CFG->{build_index} : ''))) });
        }
        elsif ($do =~ /^payment_(method|form|direct)$/) {
            require Links::Payment;
            my $vars = Links::Payment->$1();
            my $page = $IN->param('page') || $IN->param('do');
            my $opt = Links::Payment::load_cat_price($IN->param('cat_id'));
            if ($opt->{payment_mode} == NOT_ACCEPTED) {
                print Links::SiteHTML::display('error', { error => Links::language('PAYMENTERR_NOTACCEPTED') });
                return;
            }
            my $link = $DB->table('Links')->get($IN->param('link_id'));
            if (not $link or ($CFG->{user_required} and $link->{LinkOwner} ne $USER->{Username})) {
                print Links::SiteHTML::display('error', { error => !$link ? $GT::SQL::ERRORS : Links::language('PAYMENTERR_NOTOWNER') });
                return;
            }
            $link = Links::SiteHTML::tags('link', $link);

            $link->{main_title_loop} = Links::Build::build('title', Links::language('LINKS_PAYMENT'), "$CFG->{db_cgi_url}/modify.cgi?do=payment_linked;process_payment=1;modify=1;ID=$link->{ID}");
            print Links::SiteHTML::display($page, { %$vars, %$opt, %$link });
        }
        else {
            print Links::SiteHTML::display('error', { error => "Invalid action" });
        }
    }
# We are displaying an add form.
    else {
        my @id = grep { /^\d+$/ } $IN->param('ID');

# If we don't have an id, and can't generate a list, let's send the user a message.
        if (!@id and !$CFG->{db_gen_category_list}) {
            print Links::SiteHTML::display('error', { error => Links::language('ADD_SELCAT') });
        }
        else {
# Otherwise display the add form.
            if ($USER) {
                $IN->param('Contact_Name')  or ($IN->param('Contact_Name', $USER->{Name} || $USER->{Username}));
                $IN->param('Contact_Email') or ($IN->param('Contact_Email', $USER->{Email}));
            }

            if ($DB->table('Category')->count == 0) {
                print Links::SiteHTML::display('error', { error => Links::language('ADD_NOCATEGORIES') });
            }
# If we're not generating a category list, the add form can't be shown without a valid category ID.
            elsif (!$CFG->{db_gen_category_list} and $DB->table('Category')->count({ ID => \@id }) == 0) {
                print Links::SiteHTML::display('error', { error => Links::language('ADD_INVALIDCAT', join(', ', @id)) });
            }
            else {
                my $category = {};
                if ($CFG->{db_gen_category_list} < 2) {
                    require Links::Tools;
                    $category = Links::Tools::category_list();
                    $category->{Category} = sub { Links::Tools::category_list_html() };
                }
                print Links::SiteHTML::display('add', {
                    main_title_loop => Links::Build::build('title', Links::language('LINKS_ADD'), "$CFG->{db_cgi_url}/add.cgi" . (@id ? "?ID=" . join(';ID=', @id) : '')),
                    %$category
                });
            }
        }
    }
}

sub add_link {
# --------------------------------------------------------
# Add the link to the database.
#
    my $class = shift;
    my @id = $IN->param('CatLinks.CategoryID');
    my %ret;
    if ($CFG->{db_gen_category_list} < 2) {
        require Links::Tools;
        %ret = %{Links::Tools::category_list()};
        $ret{Category} = sub { Links::Tools::category_list_html() };
    }
    $ret{main_title_loop} = Links::Build::build('title', Links::language('LINKS_ADD'), "$CFG->{db_cgi_url}/add.cgi" . (@id ? "?ID=" . join(';ID=', @id) : ''));

# Check the referer.
    if (@{$CFG->{db_referers}}) {
        my $found = 0;
        if ($ENV{'HTTP_REFERER'}) {
            foreach (@{$CFG->{db_referers}}) { $ENV{'HTTP_REFERER'} =~ /\Q$_\E/i and $found++ and last; }
        }
        unless ($found) {
            return { error => Links::language('ADD_BADREFER', $ENV{'HTTP_REFERER'}), %ret };
        }
    }

# Get our form data.
    my $input = $IN->get_hash;

# Check if the link is valid
    if ($CFG->{user_link_validation}) {
        require Links::Tools;
        my $status = Links::Tools::link_status($input->{URL});
        if ($status and $Links::Tools::STATUS_BAD{$status}) {
            return { error => Links::language('ADD_BADSTATUS', $Links::Tools::STATUS_BAD{$status}), %ret };
        }
    }

    my $db  = $DB->table('Links');
    my $cdb = $DB->table('Category');

# Columns the user should not be passing in
    for my $key (qw/ID LinkOwner Add_Date Mod_Date Timestmp Date_Checked ExpiryDate ExpiryCounted ExpiryNotify LinkExpired/) {
        delete $input->{$key};
    }

    for my $key (keys %{$CFG->{add_system_fields}}) {
        $input->{$key} = $CFG->{add_system_fields}->{$key};
    }

# Set the LinkOwner
    $input->{LinkOwner} = $USER ? $USER->{Username} : 'admin';

# Set date variable to today's date.
    Links::init_date();
    my $today = GT::Date::date_get();
    $input->{Add_Date} = $today;
    $input->{Mod_Date} = $today;

# Backward compatibility
    $input->{Contact_Name}  = $input->{'Contact_Name'}  || $input->{'Contact Name'}  || ($USER ? $USER->{Name}  : '');
    $input->{Contact_Email} = $input->{'Contact_Email'} || $input->{'Contact Email'} || ($USER ? $USER->{Email} : '');

    $input->{isValidated} = ($CFG->{build_auto_validate} == 1 and $USER or $CFG->{build_auto_validate} == 2) ? 'Yes' : 'No';

# Check the category
    my @cids = $IN->param('CatLinks.CategoryID');
    my @name;
    if (@cids) {
        foreach my $cid (@cids) {
            next if (! $cid);
            my $sth = $cdb->select('Full_Name', { ID => $cid });
            $sth->rows or return { error => Links::language('ADD_INVALIDCAT', $cid), %ret };
            push @name, $sth->fetchrow;
        }
        if (@name) {
            $input->{'CatLinks.CategoryID'} = \@cids;
        }
    }

    my $take_payments = (
        $CFG->{payment}->{enabled}
            and
        (
            $cdb->count(GT::SQL::Condition->new(Payment_Mode => '>=' => OPTIONAL, ID => '=' => \@cids))
                or
            (
                $CFG->{payment}->{mode} >= OPTIONAL and
                $cdb->count(GT::SQL::Condition->new(Payment_Mode => '=' => GLOBAL, ID => '=' => \@cids))
            )
        )
    );

# Set the payment expiry
# Set this to unlimited when payment is turned off so that if payment is turned on
# at a later date, those users aren't forced to pay.
    $input->{ExpiryDate} = $CFG->{payment}->{enabled} && $take_payments ? UNPAID : FREE;

# Setup the language for GT::SQL.
    local $GT::SQL::ERRORS->{ILLEGALVAL}     = Links::language('ADD_ILLEGALVAL');
    local $GT::SQL::ERRORS->{UNIQUE}         = Links::language('ADD_UNIQUE');
    local $GT::SQL::ERRORS->{NOTNULL}        = Links::language('ADD_NOTNULL');
    local $Links::Table::Links::ERRORS->{NOCATEGORY} = Links::language('ADD_NOCATEGORY');
    $Links::Table::Links::ERRORS if 0; # silence -w

# Add the record.
    my $id = $db->add($input);
    $input->{ID} = $id;
    if (! $id) {
        my $error = "<ul>" . join('', map "<li>$_</li>", $db->error) . "</ul>";
        return { error => $error, %ret };
    }

# Add some special tags for formatting.
    $input->{Category}      = join "\n", sort @name;
    $input->{Category_loop} = [sort @name];
    $input->{Host}          = $ENV{REMOTE_HOST}  ? "$ENV{REMOTE_HOST} ($ENV{REMOTE_ADDR})" : $ENV{REMOTE_ADDR} ? $ENV{REMOTE_ADDR} : 'none';
    $input->{Referer}       = $ENV{HTTP_REFERER} ? $ENV{HTTP_REFERER} : 'none';
    $input->{AutoValidate}  = $CFG->{build_auto_validate};

# Send the visitor to the success page.
    return $input;
}

1;
