First pass at adding key files
This commit is contained in:
303
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Add.pm
Normal file
303
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Add.pm
Normal file
@ -0,0 +1,303 @@
|
||||
# ==================================================================
|
||||
# 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;
|
126
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Editor.pm
Normal file
126
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Editor.pm
Normal file
@ -0,0 +1,126 @@
|
||||
# ==================================================================
|
||||
# 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: Editor.pm,v 1.15 2009/05/09 06:40:54 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::Editor;
|
||||
# ==================================================================
|
||||
use strict;
|
||||
use Links qw/:objects/;
|
||||
use Links::Browser::Controller;
|
||||
use Links::Browser;
|
||||
use Links::SiteHTML;
|
||||
|
||||
sub handle {
|
||||
# ------------------------------------------------------------------
|
||||
# This script is only available to users who have logged on.
|
||||
#
|
||||
unless ($USER) {
|
||||
my $url = $IN->url(absolute => 1, query_string => 1);
|
||||
$url = $IN->escape($url);
|
||||
$url = $CFG->{db_cgi_url} . "/user.cgi?url=$url;from=browser";
|
||||
print $IN->redirect($url);
|
||||
return;
|
||||
}
|
||||
my $editors = $DB->table('Editors');
|
||||
my @nodes;
|
||||
my $perms = {};
|
||||
|
||||
# Get a controller to manage access.
|
||||
my $ctrl = Links::Browser::Controller->new(user => $USER);
|
||||
|
||||
if ($USER->{Status} eq 'Administrator') {
|
||||
$ctrl->{admin} = 1;
|
||||
}
|
||||
else {
|
||||
my $sth = $editors->select({ Username => $USER->{Username} });
|
||||
if ($sth->rows) {
|
||||
while (my $ed = $sth->fetchrow_hashref) {
|
||||
push @nodes, $ed->{CategoryID};
|
||||
$perms->{$ed->{CategoryID}} = $ed;
|
||||
}
|
||||
}
|
||||
unless (@nodes) {
|
||||
print $IN->header;
|
||||
print Links::SiteHTML::display('error', { error => Links::language('BROWSER_NOTEDITOR') });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# Handle the special condition which related to viewing
|
||||
# and downloading files. Must remap the passed column
|
||||
# values so Jump functions properly.
|
||||
my $method = $IN->param('do');
|
||||
if ($method and $method =~ m/^(?:(v)iew|(download))_file$/) {
|
||||
$IN->param($+, $IN->param('cn'));
|
||||
$IN->param('ID', $IN->param('link_id') || $IN->param('id'));
|
||||
$IN->param('DB', $IN->param('db'));
|
||||
require Links::User::Jump;
|
||||
return Links::User::Jump::handle();
|
||||
}
|
||||
elsif ($method and $method =~ m/^(?:(v)iew|(download))_tmp_file$/) {
|
||||
my $download = $2;
|
||||
# view_tmp_file doesn't go through Jump because only editors are
|
||||
# allowed to see them - the tmp files are used for pending Changes.
|
||||
my $col = $IN->param('cn');
|
||||
my $id = $IN->param('link_id');
|
||||
my $changes = $DB->table('Changes')->select({ LinkID => $id })->fetchrow_hashref;
|
||||
|
||||
my ($linkinfo, $fh);
|
||||
if ($changes) {
|
||||
$linkinfo = eval $changes->{ChgRequest};
|
||||
if ($linkinfo and -f $linkinfo->{$col}) {
|
||||
my $colfh = \do { local *FH; *FH };
|
||||
if (open $colfh, "<$linkinfo->{$col}") {
|
||||
$fh = $colfh;
|
||||
binmode $fh;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$fh) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('FILE_UNKNOWN', $id) });
|
||||
return;
|
||||
}
|
||||
|
||||
(my $filename = $linkinfo->{"${col}_filename"} || $linkinfo->{$col}) =~ s{.*[/\\]}{};
|
||||
print $IN->header($IN->file_headers(
|
||||
filename => $filename,
|
||||
inline => $download ? 0 : 1,
|
||||
size => -s $linkinfo->{$col}
|
||||
));
|
||||
|
||||
while (read $fh, my $buffer, 64*1024) {
|
||||
print $buffer;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Load the tree if it is under 200 categories.
|
||||
$ctrl->{load_tree} = 1;
|
||||
$ctrl->{user_base_node} = \@nodes;
|
||||
$ctrl->{perms} = $perms;
|
||||
$ctrl->{admin_templates} = 0;
|
||||
|
||||
# Begin the script.
|
||||
print $IN->header(-charset => $CFG->{header_charset});
|
||||
$method = $ctrl->can_run;
|
||||
if ($method) {
|
||||
my $browser = Links::Browser->new(ctrl => $ctrl);
|
||||
$PLG->dispatch("browser_$method", sub { $browser->$method(); }, $browser);
|
||||
}
|
||||
else {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('BROWSER_UNAUTHORIZED') });
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
186
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Jump.pm
Normal file
186
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Jump.pm
Normal file
@ -0,0 +1,186 @@
|
||||
# ==================================================================
|
||||
# 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;
|
263
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Login.pm
Normal file
263
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Login.pm
Normal file
@ -0,0 +1,263 @@
|
||||
# ==================================================================
|
||||
# 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: Login.pm,v 1.19 2005/05/08 09:56:44 brewt Exp $
|
||||
#
|
||||
# Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved.
|
||||
# Redistribution in part or in whole strictly prohibited. Please
|
||||
# see LICENSE file for full details.
|
||||
# ==================================================================
|
||||
|
||||
package Links::User::Login;
|
||||
# ==================================================================
|
||||
use strict;
|
||||
use Links qw/:objects/;
|
||||
use Links::Build;
|
||||
use Links::SiteHTML;
|
||||
|
||||
sub handle {
|
||||
# -------------------------------------------------------------------
|
||||
# Determine what to do.
|
||||
#
|
||||
my $input = $IN->get_hash;
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_LOGIN'), "$CFG->{db_cgi_url}/user.cgi");
|
||||
if ($input->{login}) {
|
||||
$PLG->dispatch('user_login', \&login_user);
|
||||
}
|
||||
elsif ($input->{signup_user}) {
|
||||
$PLG->dispatch('user_signup', \&signup_user);
|
||||
}
|
||||
elsif ($input->{validate_user}) {
|
||||
$PLG->dispatch('user_validate', \&validate_user);
|
||||
}
|
||||
elsif ($input->{send_validate}) {
|
||||
$PLG->dispatch('user_validate_email', \&send_validate);
|
||||
}
|
||||
elsif ($input->{send_pass} and $CFG->{user_allow_pass}) {
|
||||
$PLG->dispatch('user_pass_email', \&send_pass);
|
||||
}
|
||||
elsif ($input->{signup_form}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('signup_form', { Username => $IN->param('Username') || '', Password => '', Email => $IN->param('Email') || '', main_title_loop => Links::Build::build('title', Links::language('LINKS_SIGNUP'), "$CFG->{db_cgi_url}/user.cgi?signup_form=1") });
|
||||
}
|
||||
elsif ($input->{validate}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('validate_form', { main_title_loop => Links::Build::build('title', Links::language('LINKS_VALIDATE'), "$CFG->{db_cgi_url}/user.cgi?validate=1") });
|
||||
}
|
||||
elsif ($input->{logout}) {
|
||||
Links::Authenticate::auth('delete_session');
|
||||
$USER = undef;
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('login', { Username => '', Password => '', Email => '', error => Links::language('USER_LOGOUT'), main_title_loop => $mtl });
|
||||
}
|
||||
elsif ($input->{email_pass} and $CFG->{user_allow_pass}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('login_email', { main_title_loop => Links::Build::build('title', Links::language('LINKS_EMAILPASS'), "$CFG->{db_cgi_url}/user.cgi?email_pass=1") });
|
||||
}
|
||||
else {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('login', { Username => $IN->param('Username') || '', main_title_loop => $mtl });
|
||||
}
|
||||
}
|
||||
# ==============================================================
|
||||
|
||||
sub login_user {
|
||||
# --------------------------------------------------------
|
||||
# Logs a user in, and creates a session ID.
|
||||
#
|
||||
my $username = $IN->param('Username') || shift;
|
||||
my $password = $IN->param('Password') || shift;
|
||||
my $goto = shift || 'login_success';
|
||||
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_LOGIN'), "$CFG->{db_cgi_url}/user.cgi");
|
||||
|
||||
# Make sure we have both a username and password.
|
||||
if (!$username or !$password) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('login', { error => Links::language('USER_BADLOGIN'), Username => $username, main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
|
||||
# Check that the user exists, and that the password is valid.
|
||||
my $user = Links::init_user($username, $password);
|
||||
if (!$user) {
|
||||
print $IN->header();
|
||||
require Links::Authenticate;
|
||||
if (Links::Authenticate::auth_valid_user({ Username => $username, Password => $password })) {
|
||||
print Links::SiteHTML::display('login', { error => Links::language('USER_NOTVAL', $user->{Email}), Username => $user->{Username}, main_title_loop => $mtl });
|
||||
}
|
||||
else {
|
||||
print Links::SiteHTML::display('login', { error => Links::language('USER_BADLOGIN'), main_title_loop => $mtl });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
# Store the session in either a cookie or url based.
|
||||
my $results = Links::Authenticate::auth('create_session', { Username => $user->{Username} });
|
||||
return if $results->{redirect};
|
||||
|
||||
# Get the $USER information.
|
||||
$USER = Links::Authenticate::auth('get_user', { Username => $username, Password => $password, auto_create => 1 });
|
||||
|
||||
print $IN->header(); # In case the session didn't print it.
|
||||
print Links::SiteHTML::display($goto, { %$user, main_title_loop => $mtl });
|
||||
}
|
||||
|
||||
sub signup_user {
|
||||
# --------------------------------------------------------
|
||||
# Signs a new user up.
|
||||
#
|
||||
my $username = $IN->param('Username');
|
||||
my $password = $IN->param('Password');
|
||||
my $email = $IN->param('Email');
|
||||
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_SIGNUP'), "$CFG->{db_cgi_url}/user.cgi?signup_form=1");
|
||||
|
||||
if (!$username or !$password or !$email) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('signup_form', { error => Links::language('USER_INVALIDSIGNUP'), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
unless ($email =~ /.\@.+\../) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('signup_form', { error => Links::language('USER_INVALIDEMAIL', $email), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
|
||||
# Check that the username doesn't already exist.
|
||||
my $db = $DB->table('Users');
|
||||
my $user = $db->get($username);
|
||||
if ($user) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display( 'signup_form', { error => Links::language('USER_NAMETAKEN', $username), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
|
||||
# Check that the email address doesn't already exist.
|
||||
my $hits = $db->count({ Email => $email });
|
||||
if ($hits) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('signup_form', { error => Links::language('USER_EMAILTAKEN', $email), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
my ($code, $msg);
|
||||
|
||||
# Add the user in, set defaults for fields not specified.
|
||||
$user = $IN->get_hash();
|
||||
my $def = $db->default || {};
|
||||
foreach (keys %$def) {
|
||||
$user->{$_} = $def->{$_} unless (exists $user->{$_});
|
||||
}
|
||||
|
||||
# Send validation email if needed.
|
||||
if ($CFG->{user_validation}) {
|
||||
my $code = time . $$ . int rand 1000;
|
||||
$user->{Status} = "Not Validated";
|
||||
$user->{Validation} = $code;
|
||||
my $ret = $db->add($user);
|
||||
if (!$ret) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('signup_form', { error => $db->error, main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$user->{Status} = "Registered";
|
||||
$user->{Validation} = 0;
|
||||
my $ret = $db->add($user);
|
||||
if (!$ret) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('signup_form', { error => $db->error, main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
}
|
||||
# Print the welcome screen.
|
||||
if ($CFG->{user_validation}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('signup_success', { %$user, main_title_loop => $mtl });
|
||||
Links::send_email('validate.eml', $user) or die "Unable to send message: $GT::Mail::error";
|
||||
}
|
||||
else {
|
||||
my $results = Links::Authenticate::auth('create_session', { Username => $user->{Username} });
|
||||
$USER = Links::Authenticate::auth('get_user', { Username => $user->{Username}, Password => $user->{Password}, auto_create => 1 });
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('signup_success', { %$user, main_title_loop => $mtl });
|
||||
}
|
||||
}
|
||||
|
||||
sub validate_user {
|
||||
# --------------------------------------------------------
|
||||
# Validates a user.
|
||||
#
|
||||
my $code = $IN->param('code');
|
||||
$code =~ s/^\s*|\s*$//g;
|
||||
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_VALIDATE'), "$CFG->{db_cgi_url}/user.cgi?validate=1");
|
||||
|
||||
if (!$code) {
|
||||
print $IN->header;
|
||||
print Links::SiteHTML::display('validate_form', { error => Links::language('USER_INVALIDVAL'), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
my $db = $DB->table('Users');
|
||||
my $sth = $db->select({ Validation => $code });
|
||||
my $user = $sth->fetchrow_hashref;
|
||||
|
||||
if (! $user) {
|
||||
print $IN->header;
|
||||
print Links::SiteHTML::display('validate_form', { error => Links::language('USER_INVALIDVAL'), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
$db->update({ Status => 'Registered' }, { Username => $user->{Username} });
|
||||
login_user($user->{Username}, $user->{Password}, 'validate_success');
|
||||
}
|
||||
|
||||
sub send_pass {
|
||||
# -------------------------------------------------------------------
|
||||
# Sends the user a password reminder email.
|
||||
#
|
||||
my $email = $IN->param('Email');
|
||||
my $user_db = $DB->table('Users');
|
||||
my $sth = $user_db->select( { Email => $email } );
|
||||
print $IN->header();
|
||||
my $user = $sth->fetchrow_hashref;
|
||||
if ($user and $email =~ /.+\@.+\..+/) {
|
||||
Links::send_email('password.eml', { %$user, %ENV }) or die "Unable to send message: $GT::Mail::error";
|
||||
print Links::SiteHTML::display('login', { error => Links::language('USER_PASSSENT'), Username => '', Password => '', main_title_loop => Links::Build::build('title', Links::language('LINKS_LOGIN'), "$CFG->{db_cgi_url}/user.cgi") });
|
||||
}
|
||||
else {
|
||||
print Links::SiteHTML::display('login_email', { error => Links::language('USER_NOEMAIL'), main_title_loop => Links::Build::build('title', Links::language('LINKS_EMAILPASS'), "$CFG->{db_cgi_url}/user.cgi?email_pass=1") });
|
||||
}
|
||||
}
|
||||
|
||||
sub send_validate {
|
||||
# -------------------------------------------------------------------
|
||||
# Sends the validation email if the user needs another one.
|
||||
#
|
||||
my $email = $IN->param('Email');
|
||||
my $user_db = $DB->table('Users');
|
||||
my $sth = $user_db->select( { Email => $email } );
|
||||
print $IN->header();
|
||||
if ($sth->rows) {
|
||||
# Prepare the message.
|
||||
my $user = $sth->fetchrow_hashref;
|
||||
|
||||
# Make sure there is a validation code.
|
||||
if (! $user->{Validation}) {
|
||||
$user->{Validation} = (time) . ($$) . (int rand(1000));
|
||||
$user_db->modify($user);
|
||||
}
|
||||
Links::send_email('validate.eml', $user) or die "Unable to send message: $GT::Mail::error";
|
||||
|
||||
print Links::SiteHTML::display('login', { error => Links::language('USER_VALSENT'), Username => '', Password => '', main_title_loop => Links::Build::build('title', Links::language('LINKS_LOGIN'), "$CFG->{db_cgi_url}/user.cgi") });
|
||||
}
|
||||
else {
|
||||
print Links::SiteHTML::display('login_email', { error => Links::language('USER_NOEMAIL'), main_title_loop => Links::Build::build('title', Links::language('LINKS_EMAILPASS'), "$CFG->{db_cgi_url}/user.cgi?email_pass=1") });
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
571
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Modify.pm
Normal file
571
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Modify.pm
Normal file
@ -0,0 +1,571 @@
|
||||
# ==================================================================
|
||||
# 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: Modify.pm,v 1.82 2013/02/01 04:43:56 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::Modify;
|
||||
# ==================================================================
|
||||
use strict;
|
||||
use Links qw/:objects :payment/;
|
||||
use Links::Build;
|
||||
use Links::SiteHTML;
|
||||
|
||||
sub handle {
|
||||
# ---------------------------------------------------
|
||||
# Determine what to do.
|
||||
#
|
||||
my $link_id = $IN->param('LinkID');
|
||||
if ($CFG->{user_required} and !$USER) {
|
||||
print $IN->redirect(Links::redirect_login_url('modify'));
|
||||
return;
|
||||
}
|
||||
|
||||
# Perform the link modification
|
||||
if ($IN->param('modify')) {
|
||||
_modify();
|
||||
}
|
||||
elsif ($USER) {
|
||||
# Display the link modify form (for a specific link)
|
||||
if ($IN->param('LinkID')) {
|
||||
_modify_passed_in();
|
||||
}
|
||||
else {
|
||||
_list_owned_links();
|
||||
}
|
||||
}
|
||||
# Display the link modify form (used when user_required is off)
|
||||
else {
|
||||
_modify_form();
|
||||
}
|
||||
}
|
||||
|
||||
# ==============================================================
|
||||
|
||||
sub _modify {
|
||||
# --------------------------------------------------------
|
||||
# Modifies a link.
|
||||
#
|
||||
# If payment is enabled and we are processing a payment
|
||||
if ($CFG->{payment}->{enabled} and $IN->param('process_payment')) {
|
||||
my $payment_term = $IN->param('payment_term') || '';
|
||||
my $do = $IN->param('do') || '';
|
||||
if ($payment_term eq 'free') {
|
||||
print $IN->header();
|
||||
my $link = $DB->table('Links')->get(scalar $IN->param('link_id'));
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_MODIFY_SUCCESS'), "$CFG->{db_cgi_url}/modify.cgi");
|
||||
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'), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
$link = Links::SiteHTML::tags('link', $link);
|
||||
|
||||
# Add some special tags for formatting.
|
||||
$link->{Category} = $DB->table('Category', 'CatLinks')->select('Category.Full_Name', { 'CatLinks.LinkID' => $link->{ID} })->fetchrow;
|
||||
|
||||
# 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 });
|
||||
|
||||
print Links::SiteHTML::display('modify_success', { %$link, main_title_loop => $mtl });
|
||||
}
|
||||
elsif ($do eq 'payment_linked') {
|
||||
print $IN->header;
|
||||
my $link = $DB->table('Links', 'CatLinks')->select({ ID => scalar $IN->param('ID') })->fetchrow_hashref;
|
||||
if (!$link) {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('MODIFY_NOLINKS') });
|
||||
return;
|
||||
}
|
||||
elsif ($CFG->{user_required} and $link->{LinkOwner} ne $USER->{Username}) {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('PAYMENTERR_NOTOWNER') });
|
||||
return;
|
||||
}
|
||||
$link = Links::SiteHTML::tags('link', $link);
|
||||
|
||||
require Links::Payment;
|
||||
my @cid = $DB->table('CatLinks')->select('CategoryID', { LinkID => $link->{ID} })->fetchall_list;
|
||||
my $opt = Links::Payment::load_cat_price(\@cid);
|
||||
if ($opt->{payment_mode} == NOT_ACCEPTED) {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('PAYMENTERR_NOTACCEPTED') });
|
||||
return;
|
||||
}
|
||||
$link->{link_id} = $link->{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};
|
||||
$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->{link_id}");
|
||||
print Links::SiteHTML::display('payment', { %$link, %$opt });
|
||||
}
|
||||
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'));
|
||||
print $IN->header();
|
||||
if (not $link or $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 $IN->header;
|
||||
print Links::SiteHTML::display('error', { error => "Invalid action" });
|
||||
}
|
||||
}
|
||||
# Otherwise, modify the link
|
||||
else {
|
||||
my $results = $PLG->dispatch('user_modify_link', \&modify_link, {});
|
||||
if (defined $results->{error}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('modify', $results);
|
||||
}
|
||||
else {
|
||||
$results->{main_title_loop} = Links::Build::build('title', Links::language('LINKS_MODIFY_SUCCESS'), "$CFG->{db_cgi_url}/modify.cgi");
|
||||
if ($CFG->{payment}->{enabled}) {
|
||||
require Links::Payment;
|
||||
my @cid = $IN->param('CatLinks.CategoryID');
|
||||
my $opt = Links::Payment::load_cat_price(\@cid);
|
||||
print $IN->header();
|
||||
if (exists $opt->{error}) {
|
||||
print Links::SiteHTML::display('error', $opt);
|
||||
}
|
||||
elsif ($opt->{payment_mode} == NOT_ACCEPTED or ($results->{ExpiryDate} >= time)) {
|
||||
print Links::SiteHTML::display('modify_success', $results);
|
||||
}
|
||||
else {# display payment form if the link is expired or payment mode 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 {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('modify_success', $results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _modify_passed_in {
|
||||
# --------------------------------------------------------
|
||||
# Display link that was passed in.
|
||||
#
|
||||
my $lid = $IN->param('LinkID');
|
||||
my $link_db = $DB->table('Links');
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_MODIFY'), "$CFG->{db_cgi_url}/modify.cgi?LinkID=$lid");
|
||||
my $sth = $link_db->select({ ID => $lid, LinkOwner => $USER->{Username} }, VIEWABLE);
|
||||
if ($sth->rows) {
|
||||
my $link = $sth->fetchrow_hashref;
|
||||
my @ids = $DB->table('CatLinks')->select('CategoryID', { LinkID => $link->{ID} })->fetchall_list;
|
||||
$IN->param('CatLinks.CategoryID', \@ids);
|
||||
|
||||
$link->{Contact_Name} ||= $USER->{Name} || $USER->{Username};
|
||||
$link->{Contact_Email} ||= $USER->{Email};
|
||||
|
||||
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 $IN->header();
|
||||
print Links::SiteHTML::display('modify', {
|
||||
main_title_loop => $mtl,
|
||||
%$link,
|
||||
%$category
|
||||
});
|
||||
}
|
||||
elsif (!$CFG->{user_required}) {
|
||||
_modify_form();
|
||||
}
|
||||
else {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('MODIFY_NOTOWNER'), LinkID => $lid, main_title_loop => $mtl });
|
||||
}
|
||||
}
|
||||
|
||||
sub _list_owned_links {
|
||||
# --------------------------------------------------------
|
||||
# Display a list of links the user owns.
|
||||
#
|
||||
my $link_db = $DB->table('Links');
|
||||
my ($limit, $offset, $nh) = Links::limit_offset();
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_MODIFY'), "$CFG->{db_cgi_url}/modify.cgi");
|
||||
$link_db->select_options("ORDER BY Title ASC", "LIMIT $limit OFFSET $offset");
|
||||
my $sth = $link_db->select({
|
||||
LinkOwner => $USER->{Username},
|
||||
# If payment is enabled, we want to show non-validated links to allow
|
||||
# payment to occur, otherwise only show validated ones
|
||||
($CFG->{payment}->{enabled} ? () : (isValidated => 'Yes'))
|
||||
});
|
||||
my $total = $link_db->hits;
|
||||
if (! $sth->rows) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('MODIFY_NOLINKS'), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
my ($toolbar, %paging);
|
||||
my @links;
|
||||
while (my $hash = $sth->fetchrow_hashref) {
|
||||
push @links, Links::SiteHTML::tags('link', $hash);
|
||||
}
|
||||
if ($total > $limit) {
|
||||
my $url = $CFG->{db_cgi_url} . "/" . $IN->url;
|
||||
$toolbar = $DB->html(['Links'], $IN)->toolbar($nh, $limit, $total, $url);
|
||||
%paging = (
|
||||
url => $url,
|
||||
num_hits => $total,
|
||||
max_hits => $limit,
|
||||
current_page => $nh
|
||||
);
|
||||
}
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('modify_select', {
|
||||
link_results_loop => \@links,
|
||||
main_title_loop => $mtl,
|
||||
total => $total,
|
||||
next => $toolbar,
|
||||
paging => \%paging
|
||||
});
|
||||
}
|
||||
|
||||
sub _modify_form {
|
||||
# --------------------------------------------------------
|
||||
# Just display the regular form.
|
||||
#
|
||||
my @id = $IN->param('ID'); # Category ID.
|
||||
my $link = {};
|
||||
print $IN->header();
|
||||
if ($IN->param('LinkID')) {
|
||||
my $lid = $IN->param('LinkID');
|
||||
$link = $DB->table('Links')->select({ ID => $lid }, VIEWABLE)->fetchrow_hashref;
|
||||
if (!$link) {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('MODIFY_INVALIDLINKID', $lid) });
|
||||
return;
|
||||
}
|
||||
if (!@id) {
|
||||
@id = $DB->table('CatLinks')->select('CategoryID', { LinkID => $lid })->fetchall_list;
|
||||
# Set ID to the categories that the link is in so Links::Tools::category_list
|
||||
# pre-selects them
|
||||
$IN->param(ID => \@id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!@id and !$CFG->{db_gen_category_list}) {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('MODIFY_SELCAT') });
|
||||
}
|
||||
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('modify', {
|
||||
main_title_loop => Links::Build::build('title', Links::language('LINKS_MODIFY'), "$CFG->{db_cgi_url}/modify.cgi" . (@id ? "?ID=" . join(';ID=', @id) : '')),
|
||||
%$category,
|
||||
%$link
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sub modify_link {
|
||||
# --------------------------------------------------------
|
||||
# Change the requested link.
|
||||
#
|
||||
my $args = $IN->get_hash();
|
||||
my $db = $DB->table('Links');
|
||||
my %cols = $db->cols;
|
||||
|
||||
# Make it possible to use any column to find the link we're modifying.
|
||||
# Normally, we use the LinkID to find the link, but in some conditions the URL
|
||||
# is used. Using this isn't recommended as you're not guaranteed to get the
|
||||
# same or unique results.
|
||||
my ($column, $value);
|
||||
foreach my $col (keys %cols) {
|
||||
if (exists $args->{'Current_' . $col} and $args->{'Current_' . $col}) {
|
||||
$column = $col;
|
||||
$value = $args->{'Current_' . $col};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
my $lid = $args->{LinkID};
|
||||
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_MODIFY'), "$CFG->{db_cgi_url}/modify.cgi" . ($lid ? "?LinkID=$lid" : ''));
|
||||
$ret{LinkID} = $lid;
|
||||
unless ($value or ($lid and $USER)) {
|
||||
return { error => Links::language('MODIFY_NOURL'), %ret };
|
||||
}
|
||||
|
||||
# Find the requested link
|
||||
my ($link, $sth);
|
||||
if ($USER and $lid) {
|
||||
#if ($CFG->{user_required}) {
|
||||
# Mod added back on April 10 by Virginia
|
||||
if ($CFG->{user_required} and $USER->{Status} ne 'Administrator') { # mod by Virginia Lo on Oct 29, 2007
|
||||
$sth = $db->select({ ID => $lid, LinkOwner => $USER->{Username} });
|
||||
}
|
||||
else {
|
||||
$sth = $db->select({ ID => $lid });
|
||||
}
|
||||
$sth->rows or return { error => Links::language('MODIFY_INVALIDLINKID', $lid), %ret };
|
||||
}
|
||||
else {
|
||||
$sth = $db->select({ $column => $value });
|
||||
$sth->rows or return { error => Links::language('MODIFY_BADURL', $value), %ret };
|
||||
}
|
||||
$link = $sth->fetchrow_hashref;
|
||||
|
||||
# Make sure to only allow modifications to validated links. We currently allow
|
||||
# the user to modify expired links.
|
||||
unless ($link->{isValidated} eq 'Yes') {
|
||||
return { error => Links::language('MODIFY_NOLINKS'), %ret };
|
||||
}
|
||||
|
||||
my $new = {%$args};
|
||||
|
||||
# Forced system fields (these aren't in the add_system_fields option)
|
||||
my @system = qw/ID LinkOwner Add_Date Mod_Date Timestmp Date_Checked ExpiryDate ExpiryCounted ExpiryNotify LinkExpired/;
|
||||
my %system = map { $_ => 1 } @system;
|
||||
|
||||
for my $key (keys %cols) {
|
||||
# Users can't modify system fields, so remove them so the columns don't get
|
||||
# modified
|
||||
if (exists $system{$key} or exists $CFG->{add_system_fields}->{$key}) {
|
||||
delete $new->{$key};
|
||||
next;
|
||||
}
|
||||
|
||||
# Use the original link value if it hasn't been passed in from cgi. This is
|
||||
# done to make sure all Links columns pass the column checks (not null, regex,
|
||||
# etc checks). It has to be done for all columns, since column definitions may
|
||||
# have changed since the record was originally inserted.
|
||||
$new->{$key} = $link->{$key} unless defined $args->{$key};
|
||||
}
|
||||
|
||||
# Check that the ExpiryDate is valid for the categories the link is in
|
||||
if ($CFG->{payment}->{enabled}) {
|
||||
require Links::Payment;
|
||||
my $expiry = Links::Payment::check_expiry_date($link);
|
||||
$new->{ExpiryDate} = $expiry if $expiry;
|
||||
}
|
||||
|
||||
# modify() needs the primary key to perform the update
|
||||
$new->{ID} = $link->{ID};
|
||||
|
||||
Links::init_date();
|
||||
$new->{Mod_Date} = GT::Date::date_get();
|
||||
|
||||
# Backwards compatibility
|
||||
$new->{Contact_Name} = $args->{Contact_Name} || $args->{'Contact Name'} || ($USER ? $USER->{Name} : '');
|
||||
$new->{Contact_Email} = $args->{Contact_Email} || $args->{'Contact Email'} || ($USER ? $USER->{Email} : '');
|
||||
|
||||
# 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('MODIFY_NOCATEGORY');
|
||||
$Links::Table::Links::ERRORS if 0; # silence -w
|
||||
|
||||
# On error, file column values need to be restored (since they need to get
|
||||
# re-uploaded). This is done so that the templates show the correct fields on
|
||||
# an error.
|
||||
my %fcols = $db->_file_cols();
|
||||
for (keys %fcols) {
|
||||
$ret{$_} = $link->{$_};
|
||||
}
|
||||
|
||||
# Because we store the change request in the Changes table and do not perform
|
||||
# the modify directly, all the column checks that modify() would normally do
|
||||
# need to be done now.
|
||||
my $fset;
|
||||
unless ($USER and $CFG->{user_direct_mod}) {
|
||||
if (keys %fcols) {
|
||||
require GT::SQL::File;
|
||||
my $file = GT::SQL::File->new({ parent_table => $DB->table('Links'), connect => $DB->{connect} });
|
||||
$fset = $file->pre_file_actions(\%fcols, $new, $args, $new->{ID}) or return { error => $GT::SQL::error, %ret };
|
||||
}
|
||||
|
||||
# The following block of code modifies $new (so that _check_update() works
|
||||
# properly), but we don't want that later on, so make a shallow copy of it.
|
||||
my $new_copy = { %$new };
|
||||
|
||||
# This block of code is pulled from GT::SQL::Table::modify (minus the comments)
|
||||
my $cols = $db->{schema}->{cols};
|
||||
for my $col (keys %$cols) {
|
||||
next unless exists $new_copy->{$col};
|
||||
|
||||
if ($cols->{$col}->{type} eq 'TIMESTAMP') {
|
||||
delete $new_copy->{$col};
|
||||
}
|
||||
elsif ($cols->{$col}->{type} =~ /^(?:.*INT|INTEGER|FLOAT|REAL|DOUBLE|DECIMAL|DATE|TIME|DATETIME)$/ and defined $new_copy->{$col} and $new_copy->{$col} eq '') {
|
||||
$new_copy->{$col} = undef;
|
||||
}
|
||||
elsif ($cols->{$col}->{not_null} and not (defined $new_copy->{$col} and length $new_copy->{$col})) {
|
||||
$new_copy->{$col} = undef;
|
||||
}
|
||||
}
|
||||
|
||||
$db->_check_update($new_copy, { ID => $new_copy->{ID} }) or return { error => $GT::SQL::error, %ret };
|
||||
}
|
||||
|
||||
# Make sure the category id's are valid
|
||||
$IN->param('CatLinks.CategoryID')
|
||||
or return { error => Links::language('MODIFY_NOCATEGORY'), %ret };
|
||||
|
||||
# Set the Category ID's
|
||||
my @c_ids = $IN->param('CatLinks.CategoryID');
|
||||
$new->{'CatLinks.CategoryID'} = $db->clean_category_ids(\@c_ids)
|
||||
or return { error => $GT::SQL::error, %ret };
|
||||
|
||||
# Check if the link is valid
|
||||
if ($CFG->{user_link_validation}) {
|
||||
require Links::Tools;
|
||||
my $status = Links::Tools::link_status($new->{URL});
|
||||
if ($status and $Links::Tools::STATUS_BAD{$status}) {
|
||||
return { error => Links::language('MODIFY_BADSTATUS', $Links::Tools::STATUS_BAD{$status}), %ret };
|
||||
}
|
||||
}
|
||||
|
||||
my $orig_cats = $db->get_categories($new->{ID});
|
||||
my $new_cats;
|
||||
|
||||
# Add the link either directly in, or into the change request table.
|
||||
if ($USER and $CFG->{user_direct_mod}) {
|
||||
if ($USER->{Status} ne 'Administrator' and $link->{LinkOwner} ne $USER->{Username}) {
|
||||
return { error => Links::language('MODIFY_NOTOWNER'), %ret };
|
||||
}
|
||||
|
||||
my $res = $db->modify($new) or return { error => $GT::SQL::error, %ret };
|
||||
$new_cats = $db->get_categories($new->{ID});
|
||||
}
|
||||
else {
|
||||
require GT::Dumper;
|
||||
my $chg_db = $DB->table('Changes');
|
||||
|
||||
# Remove any columns which haven't changed
|
||||
for my $key (keys %cols) {
|
||||
next if not exists $new->{$key} or $key eq 'ID';
|
||||
|
||||
delete $new->{$key} if $new->{$key} eq (defined $link->{$key} ? $link->{$key} : '');
|
||||
}
|
||||
|
||||
# Handle updating the expiry date later on (when the admin does the change
|
||||
# validation). It can't be done here because payments can be made to the link
|
||||
# before the change validation occurs, losing the user's updated expiry date.
|
||||
delete $new->{ExpiryDate};
|
||||
|
||||
# pre_file_actions() pulls the file columns out of the $new hash; put them back
|
||||
# in and save the uploaded file(s) in a temporary location for processing upon
|
||||
# change validation.
|
||||
foreach my $col (keys %fcols) {
|
||||
if (exists $fset->{$col}) {
|
||||
my $fh = $fset->{$col};
|
||||
my $fname = GT::CGI->escape(get_filename($fh));
|
||||
my $fpath = "$CFG->{admin_root_path}/tmp/$new->{ID}-$fname";
|
||||
|
||||
open F, ">$fpath";
|
||||
binmode F; binmode $fh;
|
||||
my $buf;
|
||||
while (read $fh, $buf, 4096) { print F $buf; };
|
||||
close F;
|
||||
|
||||
$new->{$col} = $fpath;
|
||||
$new->{"${col}_filename"} = $fset->{"${col}_filename"} || get_filename($fh);
|
||||
}
|
||||
elsif (exists $fset->{"${col}_del"}) {
|
||||
$new->{"${col}_del"} = $fset->{"${col}_del"};
|
||||
}
|
||||
}
|
||||
|
||||
my $count = $chg_db->count({ LinkID => $new->{ID} });
|
||||
if ($count) {
|
||||
my $href = $chg_db->select('ChgRequest', { LinkID => $new->{ID} })->fetchrow;
|
||||
$href = eval $href;
|
||||
foreach (keys %fcols) {
|
||||
my $fpath = $href->{$_} or next;
|
||||
$fpath ne $new->{$_} or next;
|
||||
$fpath !~ /\.\./ or next;
|
||||
$fpath =~ /^[\w\\\/\-\.%]+$/ or next;
|
||||
-e $fpath or next;
|
||||
$fpath =~ m,^\Q$CFG->{admin_root_path}\E/tmp/, or next;
|
||||
unlink $fpath;
|
||||
}
|
||||
$chg_db->update({ LinkID => $new->{ID}, Username => $link->{LinkOwner}, ChgRequest => GT::Dumper->dump({ data => $new, var => '' }) }, { LinkID => $new->{ID} })
|
||||
or return { error => $GT::SQL::error, %ret };
|
||||
}
|
||||
else {
|
||||
$chg_db->insert({ LinkID => $new->{ID}, Username => $link->{LinkOwner}, ChgRequest => GT::Dumper->dump({ data => $new, var => '' }) })
|
||||
or return { error => $GT::SQL::error, %ret };
|
||||
}
|
||||
my $cdb = $DB->table('Category');
|
||||
foreach my $id (@c_ids) {
|
||||
my $cat = $cdb->get($id, 'HASH', ['Full_Name']);
|
||||
$new_cats->{$id} = $cat->{Full_Name};
|
||||
}
|
||||
}
|
||||
|
||||
# Now email the site admin.
|
||||
if ($CFG->{admin_email_mod}) {
|
||||
my %tags;
|
||||
for my $key (keys %$link) {
|
||||
$tags{"Original_" . $key} = $link->{$key};
|
||||
$tags{"New_" . $key} = exists $new->{$key} ? $new->{$key} : $link->{$key};
|
||||
}
|
||||
# Pull in the extra fields that might be in $new (eg. extra file data)
|
||||
for my $key (keys %$new) {
|
||||
next if exists $tags{"New_" . $key};
|
||||
$tags{"New_" . $key} = $new->{$key};
|
||||
}
|
||||
$tags{Original_Category} = join "\n", sort values %$orig_cats;
|
||||
$tags{Original_Category_loop} = [sort values %$orig_cats];
|
||||
$tags{New_Category} = join "\n", sort values %$new_cats;
|
||||
$tags{New_Category_loop} = [sort values %$new_cats];
|
||||
|
||||
$GT::Mail::error ||= '';
|
||||
Links::send_email('link_modified.eml', \%tags, { admin_email => 1 }) or die "Unable to send message: $GT::Mail::error";
|
||||
}
|
||||
$new->{Category} = join("\n", sort values %$new_cats);
|
||||
$new->{Category_loop} = [sort values %$new_cats];
|
||||
|
||||
# All done!
|
||||
return { %$args, %$link, %$new };
|
||||
}
|
||||
|
||||
sub get_filename {
|
||||
# -------------------------------------------------------------------
|
||||
my $fpath = shift;
|
||||
my @path = split /[\\\/]/, $fpath;
|
||||
return pop @path;
|
||||
}
|
||||
|
||||
1;
|
250
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Page.pm
Normal file
250
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Page.pm
Normal file
@ -0,0 +1,250 @@
|
||||
# ==================================================================
|
||||
# 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: Page.pm,v 1.33 2007/12/19 06:59:12 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::Page;
|
||||
# ==================================================================
|
||||
use strict;
|
||||
use Links qw/:objects/;
|
||||
use Links::Build;
|
||||
use Links::SiteHTML;
|
||||
|
||||
sub handle {
|
||||
# --------------------------------------------------------------
|
||||
# Wrap in a subroutine to prevent possible mod_perl probs.
|
||||
#
|
||||
$ENV{PATH_INFO} and ($ENV{PATH_INFO} =~ s/.*page\.cgi//);
|
||||
my $page = $IN->param('g') || $ENV{PATH_INFO} || '';
|
||||
|
||||
# We can display a custom template by passing in p=template (the p is for
|
||||
# page).
|
||||
my $custom = $IN->param('p') || '';
|
||||
return generate_custom_page($custom) if $custom;
|
||||
|
||||
# Clean up page a little.
|
||||
$page =~ s|^/+||;
|
||||
$page =~ s|/+$||;
|
||||
|
||||
# Reset the grand total.
|
||||
$Links::Build::GRAND_TOTAL = 0;
|
||||
|
||||
# Figure out what to look for.
|
||||
my ($new_match) = $CFG->{build_new_url} =~ m{^\Q$CFG->{build_root_url}\E/(.+)};
|
||||
my ($cool_match) = $CFG->{build_cool_url} =~ m{^\Q$CFG->{build_root_url}\E/(.+)};
|
||||
my ($rate_match) = $CFG->{build_ratings_url} =~ m{^\Q$CFG->{build_root_url}\E/(.+)};
|
||||
|
||||
# Strip out the index.html/more*.html if it is there.
|
||||
$page =~ s{/*(?:\Q$CFG->{build_home}\E|\Q$CFG->{build_index}\E|\Q$CFG->{build_more}\E\d+\Q$CFG->{build_extension}\E)$}{};
|
||||
|
||||
if ($new_match and $page =~ m{^\Q$new_match\E(?:/|$)}) {
|
||||
$PLG->dispatch('generate_new', \&generate_new_page);
|
||||
}
|
||||
elsif ($cool_match and $page =~ m{^\Q$cool_match\E(?:/|$)}) {
|
||||
$PLG->dispatch('generate_cool', \&generate_cool_page);
|
||||
}
|
||||
elsif ($rate_match and $page =~ m{^\Q$rate_match\E/?$}) {
|
||||
$PLG->dispatch('generate_rate', \&generate_rate_page);
|
||||
}
|
||||
# By default the detailed page format in dynamic mode will be
|
||||
# "<%config.build_detailed_url%>/<%ID%>.<%build_extension%>", but other certain
|
||||
# formats can be used without breaking other URLs.
|
||||
elsif ($page =~ /\d+\Q$CFG->{build_extension}\E$/) {
|
||||
$PLG->dispatch('generate_detailed', \&generate_detailed_page);
|
||||
}
|
||||
elsif ($page !~ /\S/) {
|
||||
$PLG->dispatch('generate_home', \&generate_home_page);
|
||||
}
|
||||
elsif ($page =~ /(\w+\.cgi)/) {
|
||||
print $IN->redirect("$CFG->{db_cgi_url}/$1");
|
||||
}
|
||||
else {
|
||||
$PLG->dispatch('generate_category', \&generate_category_page);
|
||||
}
|
||||
}
|
||||
|
||||
sub generate_custom_page {
|
||||
# --------------------------------------------------------
|
||||
# Displays a custom template.
|
||||
#
|
||||
my $page = shift;
|
||||
if ($CFG->{dynamic_404_status}) {
|
||||
my $template_set = Links::template_set();
|
||||
if (! Links::template_exists($template_set, "$page.html")) {
|
||||
print "Status: 404" . $GT::CGI::EOL;
|
||||
}
|
||||
}
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display($page, {});
|
||||
}
|
||||
|
||||
sub generate_home_page {
|
||||
# --------------------------------------------------------
|
||||
# Display the home page.
|
||||
#
|
||||
print $IN->header();
|
||||
print Links::Build::build(home => {});
|
||||
}
|
||||
|
||||
sub generate_category_page {
|
||||
# --------------------------------------------------------
|
||||
# This routine will display a category, first thing we need
|
||||
# to do is figure out what category we've been asked for.
|
||||
#
|
||||
my $page_num = 1;
|
||||
my $page = $IN->param('g') || $ENV{PATH_INFO} || '';
|
||||
$page_num = $1 if $page =~ s{/\Q$CFG->{build_more}\E(\d+)\Q$CFG->{build_extension}\E$}{};
|
||||
$page =~ s/\Q$CFG->{build_index}\E$//;
|
||||
$page =~ s|^/+||;
|
||||
$page =~ s|/+$||;
|
||||
my $like = $page;
|
||||
$page =~ y/_/ /;
|
||||
|
||||
# Now we get the ID number of the category based on the URL.
|
||||
my $cat_db = $DB->table('Category');
|
||||
my $id;
|
||||
if ($CFG->{build_category_dynamic} eq 'ID' or $page =~ /^\d+$/) {
|
||||
($id) = $page =~ /(\d+)$/;
|
||||
# Make sure the ID is valid
|
||||
$id = $cat_db->select(ID => { ID => $id })->fetchrow;
|
||||
}
|
||||
else {
|
||||
$id = $cat_db->select(ID => { ($CFG->{build_category_dynamic} || 'Full_Name') => $page })->fetchrow;
|
||||
}
|
||||
|
||||
if (!$id) {
|
||||
# Oops, we may have had a escaped character '_' that wasn't a space. We need
|
||||
# to look it up manually.
|
||||
$like =~ y/'"//d;
|
||||
$id = $cat_db->select(ID => GT::SQL::Condition->new(($CFG->{build_category_dynamic} || 'Full_Name') => LIKE => $like))->fetchrow;
|
||||
}
|
||||
|
||||
# Check for valid sort order.
|
||||
my %opts;
|
||||
$opts{id} = $id;
|
||||
$opts{nh} = $page_num;
|
||||
$opts{sb} = $IN->param('sb');
|
||||
$opts{so} = $IN->param('so');
|
||||
$opts{cat_sb} = $IN->param('cat_sb');
|
||||
$opts{cat_so} = $IN->param('cat_so');
|
||||
unless ($opts{sb} and exists $DB->table('Links')->cols->{$opts{sb}} and (not $opts{so} or $opts{so} =~ /^(?:desc|asc)$/i)) {
|
||||
delete $opts{sb};
|
||||
delete $opts{so};
|
||||
}
|
||||
unless ($opts{cat_sb} and exists $DB->table('Category')->cols->{$opts{cat_sb}} and (not $opts{cat_so} or $opts{cat_so} =~ /^(?:desc|asc)$/i)) {
|
||||
delete $opts{cat_sb};
|
||||
delete $opts{cat_so};
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
print $IN->header();
|
||||
print Links::Build::build('category', \%opts);
|
||||
}
|
||||
else {
|
||||
print "Status: 404" . $GT::CGI::EOL if $CFG->{dynamic_404_status};
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('PAGE_INVALIDCAT', $page) });
|
||||
}
|
||||
}
|
||||
|
||||
sub generate_new_page {
|
||||
# --------------------------------------------------------
|
||||
# Creates a "What's New" page. Set build_span_pages to 1 in setup
|
||||
# and it will create a seperate page for each date.
|
||||
#
|
||||
my ($page, $date);
|
||||
|
||||
$page = $IN->param('g') || $ENV{PATH_INFO} || '';
|
||||
if ($page =~ /\Q$CFG->{build_index}\E$/) {
|
||||
$date = '';
|
||||
}
|
||||
else {
|
||||
($date) = $page =~ m{/([^/]+)\Q$CFG->{build_extension}\E$};
|
||||
}
|
||||
|
||||
if ($date) {
|
||||
my $nh = 1;
|
||||
my $lpp = $CFG->{build_links_per_page} || 25;
|
||||
if ($date =~ s/_(\d+)//) {
|
||||
$nh = $1;
|
||||
}
|
||||
print $IN->header();
|
||||
print Links::Build::build('new_subpage', { date => $date, mh => $lpp, nh => $nh });
|
||||
}
|
||||
elsif ($CFG->{build_new_date_span_pages}) {
|
||||
print $IN->header();
|
||||
print Links::Build::build('new_index', {});
|
||||
}
|
||||
else {
|
||||
print $IN->header();
|
||||
print Links::Build::build('new', {});
|
||||
}
|
||||
}
|
||||
|
||||
sub generate_cool_page {
|
||||
# --------------------------------------------------------
|
||||
# Creates a "What's Cool" page.
|
||||
#
|
||||
my $page = $IN->param('g') || $ENV{PATH_INFO} || '';
|
||||
my $nh = 1;
|
||||
my $mh = $CFG->{build_span_pages} ? $CFG->{build_links_per_page} : 1000;
|
||||
if ($page =~ /\Q$CFG->{build_more}\E(\d+)\Q$CFG->{build_extension}\E$/) {
|
||||
$nh = $1;
|
||||
}
|
||||
print $IN->header();
|
||||
print Links::Build::build('cool', { mh => $mh, nh => $nh });
|
||||
}
|
||||
|
||||
sub generate_rate_page {
|
||||
# --------------------------------------------------------
|
||||
# Creates a Top 10 ratings page.
|
||||
#
|
||||
print $IN->header();
|
||||
print Links::Build::build('rating', {});
|
||||
}
|
||||
|
||||
sub generate_detailed_page {
|
||||
# --------------------------------------------------------
|
||||
# This routine build a single page for every link.
|
||||
#
|
||||
my ($page, $id, $link, $detail_match);
|
||||
|
||||
$page = $IN->param('g') || $ENV{PATH_INFO} || '';
|
||||
($id) = $page =~ /(\d+)\Q$CFG->{build_extension}\E$/;
|
||||
|
||||
# Fetch the category info if the link is in multiple categories and the category
|
||||
# the detailed page was accessed from was passed in. This is done so the next
|
||||
# and previous links are correct.
|
||||
# Note that due to the URL transformation (Links::clean_output), it isn't
|
||||
# possible to pass in the CategoryID unless the detailed url is self generated
|
||||
# (ie. <%detailed_url%> isn't used).
|
||||
if ($id) {
|
||||
my $cat_id = $IN->param('CategoryID');
|
||||
if ($cat_id and $DB->table('CatLinks')->count({ LinkID => $id, CategoryID => $cat_id })) {
|
||||
$link = $DB->table(qw/Links CatLinks Category/)->select({ LinkID => $id, CategoryID => $cat_id })->fetchrow_hashref;
|
||||
}
|
||||
else {
|
||||
$link = $DB->table('Links')->get($id, 'HASH');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$link) {
|
||||
print "Status: 404" . $GT::CGI::EOL if $CFG->{dynamic_404_status};
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('PAGE_INVALIDDETAIL', $page) });
|
||||
return;
|
||||
}
|
||||
|
||||
print $IN->header();
|
||||
print Links::Build::build('detailed', $link);
|
||||
}
|
||||
|
||||
1;
|
@ -0,0 +1,96 @@
|
||||
# ==================================================================
|
||||
# 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: Rate.pm,v 1.20 2007/12/19 06:59:12 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::Rate;
|
||||
# ==================================================================
|
||||
use strict;
|
||||
use Links qw/:objects/;
|
||||
use Links::Build;
|
||||
use Links::SiteHTML;
|
||||
|
||||
sub handle {
|
||||
# ---------------------------------------------------
|
||||
# Determine what to do.
|
||||
#
|
||||
my $id = $IN->param('ID');
|
||||
|
||||
# Make sure we are allowed to rate it.
|
||||
if ($CFG->{user_rate_required} and not $USER) {
|
||||
print $IN->redirect(Links::redirect_login_url('rate'));
|
||||
return;
|
||||
}
|
||||
|
||||
# Now figure out what to do.
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_RATE'), "$CFG->{db_cgi_url}/rate.cgi");
|
||||
if ($IN->param('rate')) {
|
||||
my $results = $PLG->dispatch('rate_link', \&rate_it, {});
|
||||
$results->{main_title_loop} = $mtl;
|
||||
if (defined $results->{error}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('rate', $results);
|
||||
}
|
||||
else {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('rate_success', $results);
|
||||
}
|
||||
}
|
||||
elsif (defined $id and ($id =~ /^\d+$/)) {
|
||||
print $IN->header();
|
||||
my $rec = $DB->table('Links')->get($id);
|
||||
unless ($rec) {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('RATE_INVALIDID', $id), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
$rec->{detailed_url} = $CFG->{build_detail_url} . '/' . $DB->table('Links')->detailed_url($rec->{ID}) if $CFG->{build_detailed};
|
||||
print Links::SiteHTML::display('rate', { %$rec, main_title_loop => $mtl });
|
||||
}
|
||||
else {
|
||||
print $IN->redirect($IN->param('d') ? "$CFG->{db_cgi_url}/page.cgi?d=1" : $CFG->{build_root_url} . "/" . ($CFG->{build_home} || ($CFG->{build_index_include} ? $CFG->{build_index} : '')));
|
||||
}
|
||||
}
|
||||
|
||||
sub rate_it {
|
||||
# --------------------------------------------------------
|
||||
# Give this link a rating.
|
||||
#
|
||||
my $id = $IN->param('ID');
|
||||
my $rating = $IN->param('rate');
|
||||
|
||||
# Let's get the link information.
|
||||
my $links = $DB->table('Links');
|
||||
my $rec = $links->get($id);
|
||||
$rec or return { error => Links::language('RATE_INVALIDID', $id) };
|
||||
|
||||
# Make sure we have a valid rating.
|
||||
unless ($rating =~ /^\d\d?$/ and $rating >= 1 and $rating <= 10) {
|
||||
return { error => Links::language('RATE_INVALIDRATE', $rating), %$rec };
|
||||
}
|
||||
|
||||
# Update the rating unless they have already voted.
|
||||
my $clicktrack = $DB->table('ClickTrack');
|
||||
my $rows = $clicktrack->count({ LinkID => $id, IP => $ENV{REMOTE_ADDR}, ClickType => 'Rate' });
|
||||
if ($rows) {
|
||||
return { error => Links::language('RATE_VOTED', $id), %$rec };
|
||||
}
|
||||
else {
|
||||
eval {
|
||||
$clicktrack->insert({ LinkID => $id, IP => $ENV{REMOTE_ADDR}, ClickType => 'Rate', Created => \'NOW()' });
|
||||
|
||||
$rec->{Rating} = ($rec->{Rating} * $rec->{Votes} + $rating) / ++$rec->{Votes};
|
||||
$links->update({ Rating => $rec->{Rating}, Votes => $rec->{Votes} }, { ID => $rec->{ID} });
|
||||
};
|
||||
return $rec;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
605
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Review.pm
Normal file
605
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Review.pm
Normal file
@ -0,0 +1,605 @@
|
||||
# ==================================================================
|
||||
# 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: Review.pm,v 1.78 2007/11/16 07:12:57 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::Review;
|
||||
# ==================================================================
|
||||
use strict;
|
||||
use Links qw/:objects/;
|
||||
use Links::Build;
|
||||
use Links::SiteHTML;
|
||||
|
||||
sub handle {
|
||||
# ------------------------------------------------------------------
|
||||
# Determine what to do.
|
||||
#
|
||||
my $input = $IN->get_hash;
|
||||
if ($input->{add_review}) { $PLG->dispatch('review_add', \&add_review) }
|
||||
elsif ($input->{edit_review}) { $PLG->dispatch('review_edit', \&edit_review) }
|
||||
elsif ($input->{helpful}) { $PLG->dispatch('review_helpful', \&helpful_review) }
|
||||
else { $PLG->dispatch('review_search', \&review_search_results) }
|
||||
return;
|
||||
}
|
||||
# ==================================================================
|
||||
|
||||
sub review_search_results {
|
||||
# ------------------------------------------------------------------
|
||||
# Display a list of validated reviews for a link
|
||||
#
|
||||
my $id = shift;
|
||||
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_REVIEW'), "$CFG->{db_cgi_url}/review.cgi");
|
||||
|
||||
# Get our form data and prepare some default data.
|
||||
my $args = $IN->get_hash;
|
||||
$id ||= $args->{ID};
|
||||
$args->{username} = '\*' if $args->{username} eq '*';
|
||||
|
||||
# Return error if no action
|
||||
unless ($args->{keyword} or $args->{ReviewID} or $id) {
|
||||
if ($USER) {
|
||||
$args->{username} ||= $USER->{Username};
|
||||
$IN->param(username => $args->{username});
|
||||
}
|
||||
elsif (!$args->{username} and !$args->{helpful}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALID_ACTION'), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# Reset ReviewID to null
|
||||
my $from_helpful = ($args->{helpful}) ? $args->{ReviewID} : '';
|
||||
$args->{ReviewID} = '';
|
||||
|
||||
# Review must be validated to list
|
||||
$args->{Review_Validated} = 'Yes';
|
||||
$args->{nh} = (defined $args->{nh} and $args->{nh} =~ /^(\d+)$/) ? $1 : 1;
|
||||
$args->{mh} = (defined $args->{mh} and $args->{mh} =~ /^(\d+)$/) ? $1 : $CFG->{reviews_per_page};
|
||||
$args->{so} = (defined $args->{so} and $args->{so} =~ /^(asc|desc)$/i) ? $1 : $CFG->{review_sort_order};
|
||||
($args->{sb} and ($args->{sb} =~ /^[\w\s,]+$/) or ($args->{sb} = $CFG->{review_sort_by}));
|
||||
delete $args->{ma};
|
||||
|
||||
my $rec = { noLink => 1 };
|
||||
# If we are listing reviews of a link
|
||||
if ($id) {
|
||||
$id and $args->{ID} = $id;
|
||||
|
||||
# Check if ID is valid
|
||||
$rec = $DB->table('Links')->get($args->{ID});
|
||||
$rec or do {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALIDID', $args->{ID}), main_title_loop => $mtl });
|
||||
return;
|
||||
};
|
||||
$rec = Links::SiteHTML::tags('link', $rec);
|
||||
$args->{Review_LinkID} = $args->{ID};
|
||||
$args->{ww} = 1;
|
||||
}
|
||||
# If we have a user to list
|
||||
elsif ($args->{username}) {
|
||||
$args->{Review_LinkID} = '';
|
||||
$args->{Review_Owner} = $args->{username};
|
||||
$args->{'Review_Owner-opt'} = '=';
|
||||
}
|
||||
elsif ($IN->param('ReviewID')) {
|
||||
$args->{ReviewID} = $IN->param('ReviewID');
|
||||
$args->{'ReviewID-opt'} = '=';
|
||||
}
|
||||
|
||||
my $reviews = $DB->table('Reviews');
|
||||
my $review_sth = $reviews->query_sth($args);
|
||||
my $review_hits = $reviews->hits;
|
||||
|
||||
# Return if no results.
|
||||
unless ($review_hits) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_NORESULTS', $args->{ID} || $args->{username}), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
|
||||
my @review_results_loop;
|
||||
Links::init_date();
|
||||
my $today = GT::Date::date_get(time, GT::Date::FORMAT_DATETIME);
|
||||
my %review_cache;
|
||||
my $last_review = 0;
|
||||
while (my $review = $review_sth->fetchrow_hashref) {
|
||||
$review->{Review_Count} = $reviews->count({ Review_LinkID => $review->{Review_LinkID}, Review_Validated => 'Yes' });
|
||||
$review->{Review_IsNew} = (GT::Date::date_diff($today, $review->{Review_Date}) < $CFG->{review_days_old});
|
||||
if ($CFG->{review_allow_modify} and $USER->{Username} eq $review->{Review_Owner}) {
|
||||
if ($CFG->{review_modify_timeout}) {
|
||||
my $oldfmt = GT::Date::date_get_format();
|
||||
GT::Date::date_set_format(GT::Date::FORMAT_DATETIME);
|
||||
my $timeout = GT::Date::date_get(time - $CFG->{review_modify_timeout} * 60);
|
||||
my $date = $review->{Review_ModifyDate} =~ /^0000-00-00 00:00:00/ ? $review->{Review_Date} : $review->{Review_ModifyDate};
|
||||
if (GT::Date::date_is_greater($date, $timeout)) {
|
||||
$review->{Review_CanModify} = 1;
|
||||
}
|
||||
GT::Date::date_set_format($oldfmt);
|
||||
}
|
||||
else {
|
||||
$review->{Review_CanModify} = 1;
|
||||
}
|
||||
}
|
||||
if ($review->{Review_ModifyDate} ne $review->{Review_Date} and $review->{Review_ModifyDate} !~ /^0000-00-00 00:00:00/) {
|
||||
$review->{Review_ModifyDate} = GT::Date::date_transform($review->{Review_ModifyDate}, GT::Date::FORMAT_DATETIME, $CFG->{date_review_format});
|
||||
}
|
||||
else {
|
||||
delete $review->{Review_ModifyDate};
|
||||
}
|
||||
$review->{Review_Date} = GT::Date::date_transform($review->{Review_Date}, GT::Date::FORMAT_DATETIME, $CFG->{date_review_format});
|
||||
$review->{Num} = $review->{Review_WasHelpful} + $review->{Review_WasNotHelpful};
|
||||
($from_helpful eq $review->{ReviewID}) and $review->{last_helpful} = 1;
|
||||
$CFG->{review_convert_br_tags} and $review->{Review_Contents} = _translate_html($review->{Review_Contents});
|
||||
|
||||
# Add the link info to the review
|
||||
if ($args->{username} or $args->{ReviewID} or $args->{keyword}) {
|
||||
my $catlink = $DB->table('CatLinks', 'Category', 'Links');
|
||||
unless (exists $review_cache{$review->{Review_LinkID}}) {
|
||||
$review_cache{$review->{Review_LinkID}} = $catlink->get({ LinkID => $review->{Review_LinkID} });
|
||||
}
|
||||
if ($last_review != $review->{Review_LinkID}) {
|
||||
my $names = $review_cache{$review->{Review_LinkID}};
|
||||
$review->{LinkID} = $names->{ID};
|
||||
$review->{cat_linked} = sub { Links::Build::build('title_linked', { name => $names->{Full_Name}, complete => 1 }) };
|
||||
$review->{cat_loop} = Links::Build::build('title', $names->{Full_Name});
|
||||
foreach my $key (keys %$names) {
|
||||
next if ($key eq 'ID');
|
||||
exists $review->{$key} or ($review->{$key} = $names->{$key});
|
||||
}
|
||||
}
|
||||
$last_review = $review->{Review_LinkID};
|
||||
}
|
||||
push @review_results_loop, $review;
|
||||
}
|
||||
|
||||
my ($toolbar, %paging);
|
||||
if ($review_hits > $args->{mh}) {
|
||||
my $url = $CFG->{db_cgi_url} . "/" . $IN->url;
|
||||
$url =~ s/([;&?]?)nh=(\d+)/($1 and $1 eq '?') ? '?' : ''/eg;
|
||||
$url =~ s/[;&]helpful=1//eg;
|
||||
$toolbar = $DB->html($reviews, $args)->toolbar($args->{nh} || 1, $args->{mh} || 25, $review_hits, $url);
|
||||
%paging = (
|
||||
url => $url,
|
||||
num_hits => $review_hits,
|
||||
max_hits => $args->{mh} || 25,
|
||||
current_page => $args->{nh} || 1
|
||||
);
|
||||
}
|
||||
else {
|
||||
$toolbar = '';
|
||||
}
|
||||
|
||||
# Some statistics for review list
|
||||
my ($review_stats,$review_count);
|
||||
if (!defined $args->{keyword}) {
|
||||
if ($args->{username}) {
|
||||
%$review_stats = map { $_ => $reviews->count({ Review_Owner => $args->{username}, Review_Rating => $_, Review_Validated => 'Yes' }) } (1 .. 5);
|
||||
$review_count = $reviews->count({ Review_Owner => $args->{username}, Review_Validated => 'Yes'} );
|
||||
}
|
||||
else {
|
||||
%$review_stats = map { $_ => $reviews->count({ Review_LinkID => $args->{ID}, Review_Rating => $_, Review_Validated => 'Yes' }) } (1 .. 5);
|
||||
$review_count = $reviews->count({ Review_LinkID => $args->{ID}, Review_Validated => 'Yes'});
|
||||
}
|
||||
if ($review_count) {
|
||||
for (1 .. 5) {
|
||||
$review_stats->{'p' . $_} = $review_stats->{$_} * 150 / $review_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
$review_stats ||= { noStats => 1 };
|
||||
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('review_search_results', {
|
||||
%$review_stats,
|
||||
%$rec,
|
||||
show_link_info => ($args->{username} or $args->{ReviewID} or $args->{keyword}),
|
||||
main_title_loop => $mtl,
|
||||
Review_Count => $review_hits,
|
||||
Review_Loop => \@review_results_loop,
|
||||
Review_SpeedBar => $toolbar,
|
||||
paging => \%paging
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
sub add_review {
|
||||
# ------------------------------------------------------------------
|
||||
# Add a review (only logged in users can add reviews if required)
|
||||
#
|
||||
my $id = $IN->param('ID') || '';
|
||||
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_REVIEW_ADD'), "$CFG->{db_cgi_url}/review.cgi");
|
||||
|
||||
# Check if we have a valid ID
|
||||
my $db = $DB->table('Links');
|
||||
my $rec = $db->get($id);
|
||||
unless ($id =~ /^\d+$/ and $rec) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALIDID', $id), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
$rec = Links::SiteHTML::tags('link', $rec);
|
||||
$rec->{anonymous} = !$CFG->{user_review_required};
|
||||
|
||||
# Only logged in users can add reviews (if required) or must redirect to the login page
|
||||
if ($CFG->{user_review_required} and !$USER) {
|
||||
print $IN->redirect(Links::redirect_login_url('review'));
|
||||
return;
|
||||
}
|
||||
|
||||
my ($cat_id, $cat_name) = each %{$db->get_categories($id)};
|
||||
my %title = (
|
||||
title_loop => Links::Build::build('title', "$cat_name/$rec->{Title}"),
|
||||
title => sub { Links::Build::build('title_unlinked', "$cat_name/$rec->{Title}") },
|
||||
title_linked => sub { Links::Build::build('title_linked', "$cat_name/$rec->{Title}") }
|
||||
);
|
||||
|
||||
print $IN->header();
|
||||
# If we have a review to add from a form
|
||||
if ($IN->param('add_this_review')) {
|
||||
my $results = $PLG->dispatch('add_this_review', \&_add_this_review, $rec);
|
||||
|
||||
# If we have error
|
||||
if (defined $results->{error}) {
|
||||
print Links::SiteHTML::display('review_add', { %$results, %$rec, %title, main_title_loop => $mtl });
|
||||
}
|
||||
# Return to add success page
|
||||
else {
|
||||
print Links::SiteHTML::display('review_add_success', { %$results, %$rec, %title, main_title_loop => $mtl });
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($USER) {
|
||||
my $reviews = $DB->table('Reviews');
|
||||
my $rc = $reviews->count({ Review_LinkID => $id, Review_Owner => $USER->{Username} });
|
||||
# Keep pre 3.2.0 behaviour of allowing the user to edit their existing review
|
||||
if ($rc == 1 and $CFG->{review_max_reviews} == 1) {
|
||||
my $review = $reviews->select({ Review_LinkID => $id, Review_Owner => $USER->{Username} })->fetchrow_hashref;
|
||||
my $oldfmt = GT::Date::date_get_format();
|
||||
GT::Date::date_set_format(GT::Date::FORMAT_DATETIME);
|
||||
my $timeout = GT::Date::date_get(time - $CFG->{review_modify_timeout} * 60);
|
||||
my $date = $review->{Review_ModifyDate} =~ /^0000-00-00 00:00:00/ ? $review->{Review_Date} : $review->{Review_ModifyDate};
|
||||
if (not $CFG->{review_allow_modify} or $review->{Review_Validated} eq 'No' or ($CFG->{review_modify_timeout} and GT::Date::date_is_smaller($date, $timeout))) {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_MAX_REVIEWS', $CFG->{review_max_reviews}), main_title_loop => $mtl });
|
||||
}
|
||||
else {
|
||||
print Links::SiteHTML::display('review_edit', {
|
||||
%$rec, %title, confirm => 1,
|
||||
main_title_loop => Links::Build::build('title', Links::language('LINKS_REVIEW_EDIT'), "$CFG->{db_cgi_url}/review.cgi")
|
||||
});
|
||||
}
|
||||
GT::Date::date_set_format($oldfmt);
|
||||
return;
|
||||
}
|
||||
elsif ($CFG->{review_max_reviews} and $rc + 1 > $CFG->{review_max_reviews}) {
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_MAX_REVIEWS', $CFG->{review_max_reviews}), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
}
|
||||
# We are displaying an add review form
|
||||
print Links::SiteHTML::display('review_add', { %$rec, %title, main_title_loop => $mtl });
|
||||
}
|
||||
}
|
||||
|
||||
sub _add_this_review {
|
||||
# ------------------------------------------------------------------
|
||||
# Add this review
|
||||
#
|
||||
|
||||
# Get our form data and some default data.
|
||||
my $rec = shift;
|
||||
my $reviews = $DB->table('Reviews');
|
||||
my $id = $IN->param('ID');
|
||||
my $input = $IN->get_hash;
|
||||
$input->{Review_LinkID} = $id;
|
||||
$input->{Review_Validated} = ($CFG->{review_auto_validate} == 1 and $USER or $CFG->{review_auto_validate} == 2) ? 'Yes' : 'No';
|
||||
$input->{Review_WasHelpful} = 0 ;
|
||||
$input->{Review_WasNotHelpful} = 0 ;
|
||||
$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';
|
||||
|
||||
# Get the review owner
|
||||
$input->{Review_Owner} = $USER ? $USER->{Username} : 'admin';
|
||||
|
||||
if (not $CFG->{user_review_required} and not $USER) {
|
||||
$input->{Review_GuestName} or return { error => Links::language('REVIEW_GUEST_NAME_REQUIRED') };
|
||||
$input->{Review_GuestEmail} or return { error => Links::language('REVIEW_GUEST_EMAIL_REQUIRED') };
|
||||
}
|
||||
|
||||
# Make sure we have a valid rating.
|
||||
my $cols = $reviews->cols;
|
||||
if (exists $cols->{Review_Rating} and $cols->{Review_Rating}->{not_null} and ($input->{Review_Rating} !~ /^\d$/ or $input->{Review_Rating} < 1 or $input->{Review_Rating} > 5)) {
|
||||
return { error => Links::language('REVIEW_RATING', $input->{Review_Rating}) };
|
||||
}
|
||||
|
||||
# Set date review to today's date.
|
||||
Links::init_date();
|
||||
$input->{Review_Date} = GT::Date::date_get(time, GT::Date::FORMAT_DATETIME);
|
||||
$input->{Review_ModifyDate} = $input->{Review_Date};
|
||||
|
||||
# Check that the number of reviews the user owns is under the limit.
|
||||
if ($USER and $CFG->{review_max_reviews} and
|
||||
$CFG->{review_max_reviews} < $reviews->count({ Review_LinkID => $id, Review_Owner => $USER->{Username} }) + 1) {
|
||||
return { error => Links::language('REVIEW_MAX_REVIEWS', $CFG->{review_max_reviews}) };
|
||||
}
|
||||
|
||||
# Change the language.
|
||||
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');
|
||||
|
||||
# Add the review.
|
||||
# The review will be added only if Review_email_2 is blank
|
||||
my $added_id = $input->{Review_email_2} ? 1 : $reviews->add($input);
|
||||
$input->{ReviewID} = $added_id;
|
||||
unless ($added_id) {
|
||||
my $error = "<ul><li>" . join("</li><li>", $reviews->error) . "</li></ul>";
|
||||
return { error => $error };
|
||||
}
|
||||
|
||||
# Format the date for sending email
|
||||
$input->{Review_Date} = GT::Date::date_transform($input->{Review_Date}, GT::Date::FORMAT_DATETIME, $CFG->{date_review_format});
|
||||
|
||||
# Mail the email.
|
||||
if ($CFG->{admin_email_review_add}) {
|
||||
Links::send_email('review_added.eml', { %{$USER || {}}, %$input, %$rec }, { admin_email => 1 }) or die "Unable to send mail: $GT::Mail::error";
|
||||
}
|
||||
|
||||
# Review added successfully, return to review_add_success page
|
||||
$CFG->{review_convert_br_tags} and $input->{Review_Contents} = _translate_html($input->{Review_Contents});
|
||||
return $input;
|
||||
}
|
||||
|
||||
sub edit_review {
|
||||
# ------------------------------------------------------------------
|
||||
# Edit a review (only logged in users can edit their reviews)
|
||||
#
|
||||
my $id = $IN->param('ID') || '';
|
||||
my $rid = $IN->param('ReviewID');
|
||||
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_REVIEW_EDIT'), "$CFG->{db_cgi_url}/review.cgi");
|
||||
|
||||
if (!$CFG->{review_allow_modify}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_MODIFY_DENIED'), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
|
||||
# Only logged in users can update their reviews or must redirect to the login page
|
||||
if (!$USER) {
|
||||
print $IN->redirect(Links::redirect_login_url('review'));
|
||||
return;
|
||||
}
|
||||
|
||||
# Check if we have a valid ID
|
||||
my $db = $DB->table('Links');
|
||||
my $rec = $db->get($id);
|
||||
unless (($id =~ /^\d+$/) and $rec) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALIDID', $id), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
$rec = Links::SiteHTML::tags('link', $rec);
|
||||
|
||||
# If a ReviewID isn't passed in and they have more than one review, then just edit the first review
|
||||
my $review = $DB->table('Reviews')->select({ Review_LinkID => $id, Review_Owner => $USER->{Username}, $rid ? (ReviewID => $rid) : () })->fetchrow_hashref;
|
||||
if (!$review) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_NOT_EXISTS', $id), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
elsif ($review->{Review_Validated} eq 'No') {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_ADD_WAIT', $id), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
|
||||
# Has the review modify period passed?
|
||||
if ($CFG->{review_modify_timeout}) {
|
||||
my $oldfmt = GT::Date::date_get_format();
|
||||
GT::Date::date_set_format(GT::Date::FORMAT_DATETIME);
|
||||
my $timeout = GT::Date::date_get(time - $CFG->{review_modify_timeout} * 60);
|
||||
my $date = $review->{Review_ModifyDate} =~ /^0000-00-00 00:00:00/ ? $review->{Review_Date} : $review->{Review_ModifyDate};
|
||||
my $smaller = GT::Date::date_is_smaller($date, $timeout);
|
||||
GT::Date::date_set_format($oldfmt);
|
||||
if ($smaller) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_MODIFY_TIMEOUT', $CFG->{review_modify_timeout}), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
my ($cat_id, $cat_name) = each %{$db->get_categories($id)};
|
||||
my %title = (
|
||||
title_loop => Links::Build::build('title', "$cat_name/$rec->{Title}"),
|
||||
title => sub { Links::Build::build('title_unlinked', "$cat_name/$rec->{Title}") },
|
||||
title_linked => sub { Links::Build::build('title_linked', "$cat_name/$rec->{Title}") }
|
||||
);
|
||||
|
||||
# If we have a review to update from a form
|
||||
if ($IN->param('update_this_review')) {
|
||||
my $results = $PLG->dispatch('update_this_review', \&_update_this_review, $rec);
|
||||
|
||||
# If we have error
|
||||
if (defined $results->{error}) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('review_edit', { %$results, %$rec, %title, main_title_loop => $mtl });
|
||||
}
|
||||
# Return to edit success page
|
||||
else {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('review_edit_success', { %$results, %$rec, %title, main_title_loop => $mtl });
|
||||
}
|
||||
}
|
||||
# We are displaying an edit review form
|
||||
elsif ($IN->param('confirmed')) {
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('review_edit', { %$rec, %$review, %title, main_title_loop => $mtl });
|
||||
}
|
||||
|
||||
# Else invalid action
|
||||
else {
|
||||
return review_search_results();
|
||||
}
|
||||
}
|
||||
|
||||
sub _update_this_review {
|
||||
# ------------------------------------------------------------------
|
||||
# Edit this review
|
||||
#
|
||||
# Get our link record.
|
||||
my $rec = shift;
|
||||
|
||||
# Get our form data and some default data.
|
||||
my $input = $IN->get_hash;
|
||||
my $reviews = $DB->table('Reviews');
|
||||
my $id = $IN->param('ID');
|
||||
$input->{Review_LinkID} = $id;
|
||||
$input->{Review_Validated} = ($CFG->{review_auto_validate} == 1 and $USER or $CFG->{review_auto_validate} == 2) ? 'Yes' : 'No';
|
||||
$input->{Review_WasHelpful} = 0 ;
|
||||
$input->{Review_WasNotHelpful} = 0 ;
|
||||
$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';
|
||||
|
||||
# Get the review owner
|
||||
$input->{Review_Owner} = $USER->{Username};
|
||||
|
||||
# Check if this review is valid for this user
|
||||
my $rows = $reviews->get({ Review_LinkID => $id, Review_Owner => $USER->{Username}, Review_Validated => 'Yes' });
|
||||
return { error => Links::language('REVIEW_INVALID_UPDATE') } unless $rows;
|
||||
|
||||
# Make sure we have a valid rating.
|
||||
my $cols = $reviews->cols;
|
||||
if (exists $cols->{Review_Rating} and $cols->{Review_Rating}->{not_null} and ($input->{Review_Rating} !~ /^\d$/ or $input->{Review_Rating} < 1 or $input->{Review_Rating} > 5)) {
|
||||
return { error => Links::language('REVIEW_RATING', $input->{Review_Rating}) };
|
||||
}
|
||||
|
||||
# Has the review modify period passed?
|
||||
if ($CFG->{review_modify_timeout}) {
|
||||
my $oldfmt = GT::Date::date_get_format();
|
||||
GT::Date::date_set_format(GT::Date::FORMAT_DATETIME);
|
||||
my $timeout = GT::Date::date_get(time - $CFG->{review_modify_timeout} * 60);
|
||||
my $date = $rows->{Review_ModifyDate} =~ /^0000-00-00 00:00:00/ ? $rows->{Review_Date} : $rows->{Review_ModifyDate};
|
||||
my $smaller = GT::Date::date_is_smaller($date, $timeout);
|
||||
GT::Date::date_set_format($oldfmt);
|
||||
if ($smaller) {
|
||||
return { error => Links::language('REVIEW_MODIFY_TIMEOUT', $CFG->{review_modify_timeout}) };
|
||||
}
|
||||
}
|
||||
|
||||
# Set date review to today's date.
|
||||
Links::init_date();
|
||||
delete $input->{Review_Date};
|
||||
$input->{Review_ModifyDate} = GT::Date::date_get(time, GT::Date::FORMAT_DATETIME);
|
||||
|
||||
# Change the language.
|
||||
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');
|
||||
|
||||
# Update the record.
|
||||
$reviews->modify($input, { ReviewID => $input->{ReviewID} }) or return { error => $GT::SQL::error };
|
||||
|
||||
# Delete the review track from this ReviewID
|
||||
$DB->table('ClickTrack')->delete({ ReviewID => $input->{ReviewID}, ClickType => 'Review' }) or return { error => $GT::SQL::error };
|
||||
|
||||
# Format the date for sending email
|
||||
$input->{Review_Date} = GT::Date::date_transform($input->{Review_ModifyDate}, GT::Date::FORMAT_DATETIME, $CFG->{date_review_format});
|
||||
|
||||
# Mail the email.
|
||||
if ($CFG->{admin_email_review_mod}) {
|
||||
my %tags;
|
||||
foreach my $key (keys %$rows) {
|
||||
$tags{"Original_$key"} = $rows->{$key};
|
||||
}
|
||||
foreach my $key (keys %$input) {
|
||||
$tags{"New_$key"} = $input->{$key};
|
||||
}
|
||||
|
||||
Links::send_email('review_modified.eml', { %$USER, %tags, %$rec }, { admin_email => 1 }) or die "Unable to send mail: $GT::Mail::error";
|
||||
}
|
||||
|
||||
# Review added successfully, return to review_add_success page
|
||||
$CFG->{review_convert_br_tags} and $input->{Review_Contents} = _translate_html($input->{Review_Contents});
|
||||
return $input;
|
||||
|
||||
}
|
||||
|
||||
sub helpful_review {
|
||||
# ------------------------------------------------------------------
|
||||
# Review was helpful or not
|
||||
#
|
||||
my $reviewID = $IN->param('ReviewID');
|
||||
|
||||
my $mtl = Links::Build::build('title', Links::language('LINKS_REVIEW'), "$CFG->{db_cgi_url}/review.cgi");
|
||||
|
||||
# Get our Reviews db object
|
||||
my $db = $DB->table('Reviews');
|
||||
my $rec = $db->get($reviewID);
|
||||
|
||||
if (!$rec) {
|
||||
print $IN->header;
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_INVALIDID', $rec->{Review_Subject}), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
|
||||
# Update the rating unless they have already voted.
|
||||
my $click_db = $DB->table('ClickTrack');
|
||||
my $rows = $click_db->count({ ReviewID => $rec->{ReviewID}, IP => $ENV{REMOTE_ADDR}, ClickType => 'Review' });
|
||||
if ($rows) {
|
||||
print $IN->header;
|
||||
print Links::SiteHTML::display('error', { error => Links::language('REVIEW_VOTED', $rec->{Review_Subject}), main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
else {
|
||||
eval {
|
||||
$click_db->insert({ LinkID => $rec->{Review_LinkID}, ReviewID => $rec->{ReviewID}, IP => $ENV{REMOTE_ADDR}, ClickType => 'Review', Created => \"NOW()" });
|
||||
# Update the Timestmp for the link so that the detailed page gets rebuilt with build changed
|
||||
$DB->table('Links')->update({ Timestmp => \'NOW()' }, { ID => $rec->{Review_LinkID} });
|
||||
};
|
||||
}
|
||||
|
||||
# Change the language.
|
||||
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');
|
||||
|
||||
# If this review was helpful
|
||||
if ($IN->param('yes')) {
|
||||
if (!$db->update({ Review_WasHelpful => $rec->{Review_WasHelpful} + 1 }, { ReviewID => $reviewID })) {
|
||||
print $IN->header;
|
||||
print Links::SiteHTML::display('error', { error => $db->error, main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!$db->update({ Review_WasNotHelpful => $rec->{Review_WasNotHelpful} + 1 }, { ReviewID => $reviewID })) {
|
||||
print $IN->header;
|
||||
print Links::SiteHTML::display('error', { error => $db->error, main_title_loop => $mtl });
|
||||
return;
|
||||
}
|
||||
}
|
||||
return review_search_results();
|
||||
}
|
||||
|
||||
sub _translate_html {
|
||||
# -------------------------------------------------------------------
|
||||
# Translate contents to html format
|
||||
#
|
||||
my $html = shift;
|
||||
$html = GT::CGI::html_escape($html);
|
||||
$html =~ s,\r?\n,<br />,g;
|
||||
return $html;
|
||||
}
|
||||
|
||||
1;
|
359
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Search.pm
Normal file
359
site/slowtwitch.com/cgi-bin/articles/admin/Links/User/Search.pm
Normal file
@ -0,0 +1,359 @@
|
||||
# ==================================================================
|
||||
# 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: Search.pm,v 1.48 2006/08/08 23:30:09 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::Search;
|
||||
# ==================================================================
|
||||
use strict;
|
||||
use Links qw/:objects/;
|
||||
use Links::SiteHTML;
|
||||
use Links::Build;
|
||||
|
||||
my $time_hires;
|
||||
|
||||
sub handle {
|
||||
#--------------------------------------------------------------------------------
|
||||
# Determine whether we are displaying the search form, or doing a
|
||||
# search.
|
||||
#
|
||||
my $db = $DB->table('Links');
|
||||
my $results = {};
|
||||
my $args = $IN->get_hash;
|
||||
|
||||
# Remove search fields we aren't allowed to search on.
|
||||
my @bad = (@{$CFG->{search_blocked}}, qw/isValidated ExpiryDate/);
|
||||
for my $col (@bad) {
|
||||
$col =~ s/^\s*|\s*$//g;
|
||||
if ($args->{$col}) {
|
||||
delete $args->{$col};
|
||||
$IN->delete($col);
|
||||
}
|
||||
for (qw(lt gt opt le ge ne)) {
|
||||
delete $args->{"$col-$_"};
|
||||
$IN->delete("$col-$_");
|
||||
}
|
||||
}
|
||||
|
||||
# If query is set we know we are searching.
|
||||
return search() if defined $args->{query} and $args->{query} =~ /\S/;
|
||||
|
||||
# Otherwise, if we pass in a field name, we can search on that too.
|
||||
foreach (keys %{$db->cols}) {
|
||||
for my $opt ('', qw/-lt -gt -le -ge -ne/) {
|
||||
return search() if defined $args->{"$_$opt"} and length $args->{"$_$opt"};
|
||||
}
|
||||
}
|
||||
|
||||
print $IN->header();
|
||||
print Links::SiteHTML::display('search', { main_title_loop => Links::Build::build('title', Links::language('LINKS_SEARCH'), "$CFG->{db_cgi_url}/search.cgi") });
|
||||
}
|
||||
|
||||
sub search {
|
||||
# ------------------------------------------------------------------
|
||||
# Do the search and print out the results.
|
||||
#
|
||||
my $results = $PLG->dispatch('search_results', \&query, {});
|
||||
if (defined $results->{error}) {
|
||||
print $IN->header();
|
||||
$results->{main_title_loop} = Links::Build::build('title', Links::language('LINKS_SEARCH'), "$CFG->{db_cgi_url}/search.cgi");
|
||||
print Links::SiteHTML::display('search', $results);
|
||||
}
|
||||
else {
|
||||
print $IN->header();
|
||||
$results->{main_title_loop} = Links::Build::build('title', Links::language('LINKS_SEARCH_RESULTS'), "$CFG->{db_cgi_url}/search.cgi");
|
||||
print Links::SiteHTML::display('search_results', $results);
|
||||
}
|
||||
if ($CFG->{debug_level} > 1) {
|
||||
print "<blockquote><pre>", GT::SQL->query_stack_disp , "</pre></blockquote>";
|
||||
}
|
||||
}
|
||||
|
||||
sub query {
|
||||
# ------------------------------------------------------------------
|
||||
# Query the database.
|
||||
#
|
||||
# First get our search options.
|
||||
my $args = $IN->get_hash;
|
||||
if ($args->{query}) {
|
||||
$args->{query} =~ s/^\s+//;
|
||||
$args->{query} =~ s/\s+$//;
|
||||
}
|
||||
$args->{bool} = (defined $args->{bool} and $args->{bool} =~ /^(and|or)$/i) ? uc $1 : $CFG->{search_bool};
|
||||
$args->{nh} = (defined $args->{nh} and $args->{nh} =~ /^(\d+)$/) ? $1 : 1;
|
||||
$args->{mh} = (defined $args->{mh} and $args->{mh} =~ /^\d+$/) ? $args->{mh} : $CFG->{search_maxhits};
|
||||
$args->{mh} = 200 if $args->{mh} > 200; # Safety limit
|
||||
$args->{substring} = defined $args->{substring} ? $args->{substring} : $CFG->{search_substring};
|
||||
$args->{so} = (defined $args->{so} and $args->{so} =~ /^(asc|desc)$/i) ? $1 : '';
|
||||
$args->{sb} and ($args->{sb} =~ /^[\w\s,]+$/ or ($args->{sb} = ''));
|
||||
delete $args->{ma};
|
||||
|
||||
# Make sure we only search on validated links.
|
||||
$args->{isValidated} = 'Yes';
|
||||
$args->{ExpiryDate} = '>=' . time if $CFG->{payment}->{enabled};
|
||||
|
||||
my $query = $args->{query} || '';
|
||||
my $term = $IN->escape($query);
|
||||
|
||||
my $links = $DB->table('Links');
|
||||
my $categories = $DB->table('Category');
|
||||
|
||||
# We don't do a category search if we only have a filters.
|
||||
my $filter = 0;
|
||||
if (!defined $query or $query eq '') {
|
||||
$filter = 1;
|
||||
}
|
||||
$args->{filter} = $filter;
|
||||
|
||||
# Note: if you use this or the search_set_link_callback, remember to $PLG->action(STOP) or your callback won't be used
|
||||
$args->{callback} = $PLG->dispatch('search_set_cat_callback', sub { return \&_cat_search_subcat if shift }, $args->{catid});
|
||||
my $orig_sb = $args->{sb};
|
||||
my $orig_so = $args->{so};
|
||||
$args->{sb} = $CFG->{build_sort_order_search_cat};
|
||||
$args->{so} = '';
|
||||
$filter and $args->{sb} =~ s/\s*,?\s*score//;
|
||||
|
||||
my $started;
|
||||
if (length $query and $CFG->{search_logging} and $args->{nh} == 1) {
|
||||
if (!defined $time_hires) {
|
||||
$time_hires = eval { require Time::HiRes } || 0;
|
||||
}
|
||||
$started = $time_hires ? Time::HiRes::time() : time;
|
||||
}
|
||||
|
||||
my $cat_sth;
|
||||
$cat_sth = $categories->query_sth($args) unless $filter;
|
||||
my $cat_count = $filter ? 0 : $categories->hits();
|
||||
|
||||
$args->{callback} = $PLG->dispatch('search_set_link_callback', sub { return \&_search_subcat if shift }, $args->{catid});
|
||||
$args->{sb} = $orig_sb ? $orig_sb : $CFG->{build_sort_order_search} || '';
|
||||
$args->{so} = (defined $orig_so and $orig_so =~ /^(asc|desc)$/i) ? $1 : 'ASC';
|
||||
$filter and $args->{sb} =~ s/\s*,?\s*score//;
|
||||
|
||||
# Don't force sorting by whether or not a link is paid, as that would make
|
||||
# searching almost useless w.r.t. unpaid links since a 1% paid match would be
|
||||
# higher than a 99% unpaid match.
|
||||
|
||||
my $link_sth = $links->query_sth($args);
|
||||
my $link_count = $links->hits;
|
||||
|
||||
# Log the search if it's a new query
|
||||
if (length $query and $CFG->{search_logging} and $args->{nh} == 1) {
|
||||
my $elapsed = ($time_hires ? Time::HiRes::time() : time) - $started;
|
||||
my $results = $link_count || 0;
|
||||
my $sl = $DB->table('SearchLogs');
|
||||
my $q = lc $query;
|
||||
substr($q, 255) = '' if length $q > 255;
|
||||
if (my $row = $sl->select({ slog_query => $q })->fetchrow_hashref) {
|
||||
my $slog_time = defined $row->{slog_time}
|
||||
? ($row->{slog_time} * $row->{slog_count} + $elapsed) / ($row->{slog_count} + 1)
|
||||
: $elapsed;
|
||||
$sl->update({
|
||||
slog_count => $row->{slog_count} + 1,
|
||||
slog_time => sprintf('%.6f', $slog_time),
|
||||
slog_last => time,
|
||||
slog_hits => $results
|
||||
}, {
|
||||
slog_query => $q
|
||||
});
|
||||
}
|
||||
else {
|
||||
$sl->insert({
|
||||
slog_query => $q,
|
||||
slog_count => 1,
|
||||
slog_time => sprintf('%.6f', $elapsed),
|
||||
slog_last => time,
|
||||
slog_hits => $results
|
||||
}) or die "$GT::SQL::error";
|
||||
}
|
||||
}
|
||||
|
||||
# Return if no results.
|
||||
unless ($link_count or $cat_count) {
|
||||
return { error => Links::language('SEARCH_NOLINKS', $term), term => $term };
|
||||
}
|
||||
|
||||
# Now format the category results.
|
||||
my $count = 0;
|
||||
my ($category_results, @category_results_loop);
|
||||
if (!$filter and $cat_count) {
|
||||
while (my $cat = $cat_sth->fetchrow_hashref) {
|
||||
last if ($count++ > $args->{mh});
|
||||
my $title = Links::Build::build('title_linked', { name => $cat->{Full_Name}, complete => 1, home => 0 });
|
||||
$category_results .= "<li>$title\n";
|
||||
$cat->{title_linked} = $title;
|
||||
$cat->{title_loop} = Links::Build::build('title', $cat->{Full_Name});
|
||||
push @category_results_loop, $cat;
|
||||
}
|
||||
}
|
||||
|
||||
# And format the link results.
|
||||
my (@link_results_loop, $link_results, %link_output);
|
||||
if ($link_count) {
|
||||
my $results = $link_sth->fetchall_hashref;
|
||||
$links->add_reviews($results);
|
||||
@link_results_loop = map Links::SiteHTML::tags('link', $_) => @$results unless $CFG->{build_search_gb};
|
||||
if ($CFG->{build_search_gb}) {
|
||||
my @ids = map { $_->{ID} } @$results;
|
||||
my $catlink = $DB->table('CatLinks','Category');
|
||||
my %names = $catlink->select('LinkID', 'Full_Name', { LinkID => \@ids })->fetchall_list;
|
||||
foreach my $link (@$results) {
|
||||
push @{$link_output{$names{$link->{ID}}}}, Links::SiteHTML::tags('link', $link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Join the link results by category if we are grouping.
|
||||
if ($CFG->{build_search_gb}) {
|
||||
foreach my $cat (sort keys %link_output) {
|
||||
$link_output{$cat}->[0]->{title_linked} = sub { Links::Build::build('title_linked', { name => $cat, complete => 1, home => 0 }) };
|
||||
$link_output{$cat}->[0]->{title_loop} = Links::Build::build('title', $cat);
|
||||
push @link_results_loop, @{$link_output{$cat}};
|
||||
}
|
||||
}
|
||||
$link_results = sub {
|
||||
my $links;
|
||||
$CFG->{build_search_gb} or return join("", map { Links::SiteHTML::display('link', $_) } @link_results_loop);
|
||||
foreach my $cat (sort keys %link_output) {
|
||||
my $title = Links::Build::build('title_linked', { name => $cat, complete => 1, home => 0 });
|
||||
$links .= "<p>$title" . join("", map { Links::SiteHTML::display('link', $_) } @{$link_output{$cat}});
|
||||
}
|
||||
return $links;
|
||||
};
|
||||
|
||||
# Generate a toolbar if requested.
|
||||
my ($toolbar, %paging);
|
||||
if ($link_count > $args->{mh} or $cat_count > $args->{mh}) {
|
||||
my $url = $CFG->{db_cgi_url} . "/" . $IN->url;
|
||||
$url =~ s/([;&?]?)nh=(\d+)/($1 and $1 eq '?') ? '?' : ''/eg;
|
||||
$toolbar = Links::Build::build(search_toolbar => {
|
||||
url => $url,
|
||||
numlinks => $link_count > $cat_count ? $link_count : $cat_count,
|
||||
nh => $args->{nh},
|
||||
mh => $args->{mh}
|
||||
});
|
||||
%paging = (
|
||||
url => $url,
|
||||
num_hits => $link_count > $cat_count ? $link_count : $cat_count,
|
||||
max_hits => $args->{mh},
|
||||
current_page => $args->{nh}
|
||||
);
|
||||
}
|
||||
else {
|
||||
$toolbar = '';
|
||||
}
|
||||
|
||||
# Print the output.
|
||||
my $results = {
|
||||
link_results => $link_results,
|
||||
link_results_loop => \@link_results_loop,
|
||||
category_results => $category_results,
|
||||
category_results_loop => \@category_results_loop,
|
||||
link_hits => $link_count,
|
||||
cat_hits => $cat_count,
|
||||
next => $toolbar,
|
||||
paging => \%paging,
|
||||
term => $term,
|
||||
highlight => $CFG->{search_highlighting}
|
||||
};
|
||||
return $results;
|
||||
}
|
||||
|
||||
sub _search_subcat {
|
||||
# -------------------------------------------------------------------
|
||||
# First argument is the query/table object, second argument is the current
|
||||
# result set (note: can be quite large). Must return a new result set.
|
||||
#
|
||||
my ($query, $results) = @_;
|
||||
return $results unless (keys %$results); # No matches.
|
||||
|
||||
my $cat_db = $DB->table('Category');
|
||||
my $catlink_db = $DB->table('CatLinks', 'Category');
|
||||
|
||||
# We need the full name of the category.
|
||||
my @cat_ids = $IN->param('catid') or return $results;
|
||||
my (@children, %seen);
|
||||
foreach my $id (@cat_ids) {
|
||||
next if ($id !~ /^\d+$/);
|
||||
my $child = $cat_db->children($id) or next;
|
||||
push @children, @$child, $id;
|
||||
}
|
||||
@children or return $results;
|
||||
@children = grep !$seen{$_}++, @children;
|
||||
|
||||
# Now do the joined query.
|
||||
my %filtered = map { $_ => $results->{$_} }
|
||||
$catlink_db->select(LinkID => { CategoryID => \@children, LinkID => [keys %$results] })->fetchall_list;
|
||||
|
||||
return \%filtered;
|
||||
}
|
||||
|
||||
sub _search_subcat_and {
|
||||
# -------------------------------------------------------------------
|
||||
# Search subcategories using AND.
|
||||
#
|
||||
my ($query, $results) = @_;
|
||||
return $results unless (keys %$results); # No matches
|
||||
|
||||
my $cat_db = $DB->table('Category');
|
||||
my $catlink_db = $DB->table('CatLinks', 'Category');
|
||||
|
||||
# We need the full name of the category.
|
||||
my @cat_ids = $IN->param('catid') or return $results;
|
||||
my %final = %$results;
|
||||
foreach my $id (@cat_ids) {
|
||||
next unless ($id =~ /^\d+$/);
|
||||
my @children;
|
||||
my $childs = $cat_db->children($id);
|
||||
push @children, @$childs, $id;
|
||||
my $cond = GT::SQL::Condition->new(
|
||||
CategoryID => 'IN' => \@children,
|
||||
LinkID => 'IN' => [ keys %final ]
|
||||
);
|
||||
%final = ();
|
||||
my $sth = $catlink_db->select($cond, ['LinkID']);
|
||||
while (my $link_id = $sth->fetchrow_array) {
|
||||
$final{$link_id} = $results->{$link_id};
|
||||
}
|
||||
last unless keys %final;
|
||||
}
|
||||
return \%final;
|
||||
}
|
||||
|
||||
sub _cat_search_subcat {
|
||||
# -------------------------------------------------------------------
|
||||
# First argument is the query/table object, second argument is the current
|
||||
# result set (note: can be quite large). Must return a new result set.
|
||||
#
|
||||
my ($query, $results) = @_;
|
||||
return $results unless (keys %$results); # No matches.
|
||||
|
||||
my $cat_db = $DB->table('Category');
|
||||
my @cat_ids = $IN->param('catid') or return $results;
|
||||
my (@children, %seen);
|
||||
foreach my $id (@cat_ids) {
|
||||
next if ($id !~ /^\d+$/);
|
||||
my $child = $cat_db->children($id) or next;
|
||||
push @children, @$child, $id;
|
||||
}
|
||||
@children or return $results;
|
||||
@children = grep { ! $seen{$_}++ } @children;
|
||||
|
||||
my %subcats = map { $_ => 1 } @children;
|
||||
my $filtered = {};
|
||||
while (my ($k, $s) = each %$results) {
|
||||
$filtered->{$k} = $s if (exists $subcats{$k});
|
||||
}
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -0,0 +1,119 @@
|
||||
# ==================================================================
|
||||
# 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: Treecats.pm,v 1.3 2006/09/12 06:07:12 brewt Exp $
|
||||
#
|
||||
# Copyright (c) 2006 Gossamer Threads Inc. All Rights Reserved.
|
||||
# Redistribution in part or in whole strictly prohibited. Please
|
||||
# see LICENSE file for full details.
|
||||
# ==================================================================
|
||||
|
||||
package Links::User::Treecats;
|
||||
# ==================================================================
|
||||
use strict;
|
||||
use Links qw/:objects/;
|
||||
|
||||
sub handle {
|
||||
# Fetch these categories (and select them)
|
||||
my @cid = $IN->param('cid');
|
||||
# Fetch these links (and select them)
|
||||
my @lid = $IN->param('lid');
|
||||
# Fetch these categories
|
||||
my @id = $IN->param('id');
|
||||
# Fetch links as well as Categories
|
||||
my $fetchlinks = $IN->param('links');
|
||||
|
||||
my $category = $DB->table('Category');
|
||||
my $catlinks = $DB->table('CatLinks', 'Links');
|
||||
|
||||
# Fetching selected categories
|
||||
if (@cid) {
|
||||
@lid = ();
|
||||
@id = @cid;
|
||||
$fetchlinks = 0;
|
||||
}
|
||||
# Fetching selected links
|
||||
elsif (@lid) {
|
||||
# Get all the categories that the links are in
|
||||
@id = $catlinks->select('CategoryID', { LinkID => \@lid }, VIEWABLE)->fetchall_list;
|
||||
$fetchlinks = 1;
|
||||
}
|
||||
# Fetching categories/links
|
||||
else {
|
||||
@cid = ();
|
||||
@lid = ();
|
||||
@id = (0) unless @id;
|
||||
}
|
||||
|
||||
my %vars;
|
||||
# Only allow the use of treecats.cgi if db_gen_category_list == 2 or if
|
||||
# treecats_enabled (hidden config option) is true
|
||||
if ($CFG->{db_gen_category_list} != 2 and not $CFG->{treecats_enabled}) {
|
||||
$vars{error} = 'Permission denied - treecats is currently disabled.';
|
||||
}
|
||||
else {
|
||||
my @fetchlinks;
|
||||
my $cond;
|
||||
if (@cid or @lid) {
|
||||
my $parents = $category->parents(\@id);
|
||||
my @ids;
|
||||
my @fids = (0);
|
||||
for (keys %$parents) {
|
||||
# Fetch all the parents and their children
|
||||
push @ids, @{$parents->{$_}};
|
||||
push @fids, @{$parents->{$_}};
|
||||
# Fetch the category itself
|
||||
push @ids, $_;
|
||||
# When pre-selecting links, @id contains the category the link(s) are in. To
|
||||
# completely draw the tree, the children of those categories need to be
|
||||
# retreived as well.
|
||||
if (@lid) {
|
||||
push @fids, $_;
|
||||
push @fetchlinks, $_;
|
||||
}
|
||||
push @fetchlinks, @{$parents->{$_}};
|
||||
}
|
||||
$cond = GT::SQL::Condition->new(ID => IN => \@ids, FatherID => IN => \@fids);
|
||||
$cond->bool('OR');
|
||||
}
|
||||
else {
|
||||
push @fetchlinks, @id;
|
||||
$cond = GT::SQL::Condition->new(FatherID => IN => \@id);
|
||||
}
|
||||
$category->select_options("ORDER BY Full_Name");
|
||||
$vars{categories} = $category->select($cond)->fetchall_hashref;
|
||||
|
||||
# Find the children counts of all the categories and check if they should be selected or not
|
||||
my @cats;
|
||||
for (@{$vars{categories}}) {
|
||||
push @cats, $_->{ID};
|
||||
}
|
||||
$category->select_options("GROUP BY FatherID");
|
||||
my %children = $category->select('FatherID', 'COUNT(*)', { FatherID => \@cats })->fetchall_list;
|
||||
my %selected = map { $_ => 1 } @cid;
|
||||
for (@{$vars{categories}}) {
|
||||
$_->{children} = $children{$_->{ID}} || 0;
|
||||
$_->{selected} = $selected{$_->{ID}} || 0;
|
||||
}
|
||||
|
||||
if ($fetchlinks and @fetchlinks) {
|
||||
# Remove CategoryID = 0 (shouldn't normally happen)
|
||||
@fetchlinks = grep $_, @fetchlinks;
|
||||
$catlinks->select_options("ORDER BY CategoryID, Title");
|
||||
$vars{links} = $catlinks->select({ CategoryID => \@fetchlinks }, VIEWABLE)->fetchall_hashref;
|
||||
|
||||
%selected = map { $_ => 1 } @lid;
|
||||
for (@{$vars{links}}) {
|
||||
$_->{selected} = $selected{$_->{ID}} || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print $IN->header('text/xml');
|
||||
print Links::user_page('treecats.xml', \%vars);
|
||||
}
|
||||
|
||||
1;
|
Reference in New Issue
Block a user