# ==================================================================
# 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: Jump.pm,v 1.26 2006/02/20 22:38:31 jagerman 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::Jump;
# ==================================================================
use strict;
use Links qw/:objects :payment/;
use Links::SiteHTML;

sub handle {
# --------------------------------------------------------------
# Jump to a given ID.
#
    $PLG->dispatch('jump_link', \&_plg_jump, {});
}

sub _plg_jump {
# --------------------------------------------------------------
# Jump to a given link.
#
    my $links = $DB->table('Links');
    my $id = $IN->param('ID') || $IN->param('Detailed');
    my $action = $IN->param('action') || '';
    my $goto = '';
    my $rec = {};

    if ($CFG->{framed_jump} and $id and $action eq 'jump_frame') {
        my $error;
        if ($id !~ /^\d+$/) {
            $error = Links::language('JUMP_INVALIDID', $id);
        }
        else {
            $rec = $links->select({ ID => $id }, VIEWABLE)->fetchrow_hashref;
            unless ($rec) {
                $error = Links::language('JUMP_INVALIDID', $id);
                $rec = {};
            }
            elsif ($CFG->{build_detailed}) {
                $rec->{detailed_url} = "$CFG->{build_detail_url}/" . $links->detailed_url($id);
            }
        }
        print $IN->header();
        print Links::SiteHTML::display('jump_frame', { error => $error, %$rec });
        return;
    }

# If we are chosing a random link, then get the total and go to one at random.
    if (lc $id eq "random") {
        my $offset = int rand $links->count(VIEWABLE);
        $links->select_options("LIMIT 1 OFFSET $offset");
        my $sth = $links->select(qw/ID URL/ => VIEWABLE);
        ($id, $goto) = $sth->fetchrow_array;
    }
    elsif (defined $id) {
        if ($id !~ /^\d+$/) {
            print $IN->header();
            print Links::SiteHTML::display('error', { error => Links::language('JUMP_INVALIDID', $id) });
            return;
        }

# Find out if we're going to be displaying a file
        my $col = $IN->param('v') || $IN->param('dl') || $IN->param('view') || $IN->param('download');

        if ($col) {
# in this case, we need to know from what table we want to load our data from.
# It will by default pull information from the Links table, however if the
# DB=tablename option is used, it will apply the request to that table instead
            my $table_name = $IN->param('DB') || 'Links';

            unless ($table_name =~ m/^\w+$/) {
                print $IN->header();
                print Links::SiteHTML::display('error', { error => Links::language('FILE_TABLEFORMAT' ) });
                return;
            };

            if ($table_name ne 'Links') {
                eval { $links = $DB->table($table_name) };
                if ($@) {
                    print $IN->header();
                    print Links::SiteHTML::display('error', { error => Links::language('FILE_TABLE', $table_name, $GT::SQL::error) });
                    return;
                }
            }

            my $fh;
            eval { $fh = $links->file_info($col, $id); };
            if ($fh) {
                if ($IN->param('v') or $IN->param('view')) {    # Viewing
                    print $IN->header($IN->file_headers(
                        filename => $fh->File_Name,
                        mimetype => $fh->File_MimeType,
                        inline   => 1,
                        size     => $fh->File_Size
                    ));
                }
                else {                                          # Downloading
                    print $IN->header($IN->file_headers(
                        filename => $fh->File_Name,
                        mimetype => $fh->File_MimeType,
                        inline   => 0,
                        size     => $fh->File_Size
                    ));
                }
                binmode $fh;
                while (read($fh, my $buffer, 65536)) {
                    print $buffer;
                }
                return 1;
            }
            else {
                print $IN->header();
                print Links::SiteHTML::display('error', { error => Links::language('FILE_UNKNOWN', $id) });
                return;
            }
        }
# Jump to a URL, bump the hit counter.
        else {
            $rec = $links->select({ ID => $id }, VIEWABLE)->fetchrow_hashref;
            unless ($rec) {
                print $IN->header();
                print Links::SiteHTML::display('error', { error => Links::language('JUMP_INVALIDID', $id) });
                return;
            }
            $goto = $rec->{URL};

            my $clicktrack = $DB->table('ClickTrack');
            my $rows = $clicktrack->count({ LinkID => $id, IP => $ENV{REMOTE_ADDR}, ClickType => 'Hits' });
            unless ($rows) {
                eval {
                    $clicktrack->insert({ LinkID => $id, IP => $ENV{REMOTE_ADDR}, ClickType => 'Hits', Created => \"NOW()" });
                    $links->update({ Hits => \"Hits + 1" }, { ID => $id }, { GT_SQL_SKIP_INDEX => 1 });
                };
            }
        }
    }
# Oops, no link.
    else {
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('JUMP_INVALIDID', $id) });
        return;
    }

    unless (defined $goto) {
        my $error = ($IN->param('ID') eq 'random') ? Links::language('RANDOM_NOLINKS') : Links::language('JUMP_INVALIDID', $id);
        print $IN->header();
        print Links::SiteHTML::display('error', { error => $error });
        return;
    }

# Redirect to a detailed page if requested.
    if ($CFG->{build_detailed} and $IN->param('Detailed')) {
        $goto = Links::transform_url("$CFG->{build_detail_url}/" . $links->detailed_url($id));
    }
    ($goto =~ m,^\w+://,) or ($goto = "http://$goto");
    if ($goto) {
        if ($CFG->{framed_jump} and not ($CFG->{build_detailed} and $IN->param('Detailed'))) {
            unless (keys %$rec) {
                $rec = $links->select({ ID => $id }, VIEWABLE)->fetchrow_hashref;
            }
            $rec->{detailed_url} = "$CFG->{build_detail_url}/" . $links->detailed_url($id) if $CFG->{build_detailed};
            print $IN->header();
            print Links::SiteHTML::display('jump', { destination => $goto, %$rec });
            return;
        }
        else {
            print $IN->redirect($goto);
        }
    }
    else {
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('JUMP_INVALIDID', $id) });
        return;
    }
}

1;
