# ================================================================== # Links SQL - enhanced directory management system # # Website : http://gossamer-threads.com/ # Support : http://gossamer-threads.com/scripts/support/ # CVS Info : 087,071,085,089,084 # Revision : $Id: Modify.pm,v 1.11 2002/04/04 20:40:32 alex 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/$DB $IN $USER $CFG/; 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; } # If we have been asked to modify a link, let's do it. CASE: { $IN->param('modify') and do { _modify(); last CASE; }; $USER and $IN->param('LinkID') and do { _modify_passed_in(); last CASE; }; $USER and do { _list_owned_links(); last CASE; }; # Otherwise display the modify form. _modify_form(); } } # ============================================================== sub _modify { # -------------------------------------------------------- # Modifies a link. # my $results = GT::Plugins->dispatch ($CFG->{admin_root_path} . '/Plugins', 'user_modify_link', \&modify_link, {}); if (defined $results->{error}) { print $IN->header(); print Links::SiteHTML::display ('modify', $results); } else { print $IN->header(); print Links::SiteHTML::display ('modify_success', $results); } } sub _modify_passed_in { # -------------------------------------------------------- # Display link that was passed in. # my ($name, $category); my $lid = $IN->param('LinkID'); my $link_db = $DB->table('Links'); my $sth = $link_db->select ( { ID => $lid, LinkOwner => $USER->{Username} }); if ($sth->rows) { my $link = $sth->fetchrow_hashref; my $catlink_db = $DB->table('CatLinks'); $sth = $catlink_db->select ( { LinkID => $link->{ID} }, ['CategoryID'] ); my @catid = $sth->fetchall_list; $IN->param ('CatLinks.CategoryID', \@catid); $link->{Contact_Name} ||= $USER->{Name} || $USER->{Username}; $link->{Contact_Email} ||= $USER->{Email}; my $category = _category_list(); $link->{Category} = $category; print $IN->header(); print Links::SiteHTML::display('modify', $link); } else { print $IN->header(); print Links::SiteHTML::display('error', { error => Links::language('MODIFY_NOTOWNER'), LinkID => $lid }); } } sub _list_owned_links { # -------------------------------------------------------- # Display a list of links the user owns. # my $link_db = $DB->table('Links'); my $mh = $IN->param('mh') || 25; my $nh = $IN->param('nh') || 1; $link_db->select_options ("LIMIT " . (($nh-1)*$mh) . ",$mh"); my $sth = $link_db->select ( { LinkOwner => $USER->{Username}, isValidated => 'Yes' }); my $total = $link_db->hits; if (! $sth->rows) { print $IN->header(); print Links::SiteHTML::display('error', { error => Links::language('MODIFY_NOLINKS') }); return; } my $toolbar; my @links; while (my $hash = $sth->fetchrow_hashref) { push @links, $hash; } if ($total > $mh) { my $url = $CFG->{db_cgi_url} . "/" . $IN->url( query_string => 1, absolute => 0 ); $toolbar = $DB->html(['Links'], $IN)->toolbar ($nh, $mh, $total, $url); } print $IN->header(); print Links::SiteHTML::display ('modify_select', { link_results_loop => \@links, total => $total, next => $toolbar }); } sub _modify_form { # -------------------------------------------------------- # Just display the regular form. # my $id = $IN->param('ID'); # Category ID. if (! $id and ! $CFG->{db_gen_category_list}) { print $IN->header(); print Links::SiteHTML::display('error', { error => Links::language('MODIFY_SELCAT') }); } else { my $category = _category_list(); print $IN->header(); if (! $category) { print Links::SiteHTML::display('error', { error => Links::language('ADD_INVALIDCAT', $IN->param('ID')) }); } else { print Links::SiteHTML::display('modify', { Category => $category }); } } } sub modify_link { # -------------------------------------------------------- # Change the requested link. # my $category = _category_list(); my $args = $IN->get_hash(); my $db = $DB->table ('Links'); my $cols = $db->cols; my ($column, $value); foreach my $col (keys %$cols) { if (exists $args->{'Current_' . $col}) { $column = $col; $value = $args->{'Current_' . $col}; last; } } my $lid = $args->{'LinkID'}; if (! ($value or $lid)) { return { error => Links::language('MODIFY_NOURL'), Category => $category, LinkID => $lid }; } # Find the URL requested. my ($link, $sth); if ($USER and $lid) { $sth = $db->select ( { ID => $lid, LinkOwner => $USER->{Username} }); $sth->rows or return { error => Links::language('MODIFY_BADURL', $lid), Category => $category, LinkID => $lid }; } else { $sth = $db->select ( { $column => $value } ); $sth->rows or return { error => Links::language('MODIFY_BADURL', $value), Category => $category, LinkID => $lid }; } $link = $sth->fetchrow_hashref; # Preserve any system fields. my $new = {}; my %cols = $db->cols; foreach my $key (keys %cols) { (exists $CFG->{add_system_fields}->{$key}) ? ($new->{$key} = $link->{$key}) : ($new->{$key} = defined $args->{$key} ? $args->{$key} : $link->{$key}); } # Make sure we have the ID set properly. $new->{ID} = $link->{ID}; $new->{LinkOwner} = $link->{LinkOwner}; # Set the dates properly. Links::init_date(); $new->{'Add_Date'} = $link->{'Add_Date'}; $new->{'Mod_Date'} = GT::Date::date_get(); # 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::Link::ERRORS->{NOCATEGORY} = Links::language('MODIFY_NOCATEGORY'); $Links::Link::ERRORS ||= {}; # silence -w # Make sure not nulls are not null (check update doesn't handle this anymore). my %not_null_cols = $db->not_null; foreach my $col (keys %not_null_cols) { if ($not_null_cols{$col}) { unless (defined $new->{$col} and ($new->{$col} ne '')) { return { error => Links::language('ADD_NOTNULL', $col), Category => $category, LinkID => $lid }; } } } # Check that it's valid: $db->_check_update ($new, { ID => $new->{ID} }) or return { error => $GT::SQL::error, Category => $category, LinkID => $lid }; # Make sure the category id's are valid. $IN->param('CatLinks.CategoryID') or return { error => Links::language('MODIFY_NOCATEGORY'), Category => $category, LinkID => $lid }; # Set the ID's and Category ID's and remove timestamp field. my @c_ids = $IN->param('CatLinks.CategoryID'); $new->{'CatLinks.CategoryID'} = \@c_ids; $new->{'CatLinks.CategoryID'} = $db->clean_category_ids ( $new->{'CatLinks.CategoryID'} ) or return { error => $GT::SQL::error, Category => $category, LinkID => $lid }; # Backward compatibility.. my $name = $args->{'Contact_Name'} || $args->{'Contact Name'} || ($USER ? $USER->{Name} : ''); my $email = $args->{'Contact_Email'} || $args->{'Contact Email'} || ($USER ? $USER->{Email} : ''); $new->{'Contact_Name'} = $name; $new->{'Contact_Email'} = $email; # Make sure a contact name and email were entered and are valid. my $user_db = $DB->table ('Users'); my $user_cols = $user_db->cols; $name or $db->error ('NOTNULL', 'WARN', $user_cols->{Name}->{form_display} || 'Contact Name'); $email or $db->error ('NOTNULL', 'WARN', $user_cols->{Email}->{form_display} || 'Contact Email'); $email =~ /^.+\@.+\..+$/ or $db->error ('ILLEGALVAL', 'WARN', $user_cols->{Email}->{form_display} || 'Contact Email', $email); if ($db->error) { return { error => $GT::SQL::error, Category => $category, LinkID => $lid }; } # Remove the timestamp. delete $new->{Timestmp}; my $orig_cats = $db->get_categories ($new->{ID}); my $new_cats; my $save = {}; foreach my $k (keys %$new) { $save->{$k} = $new->{$k}; } foreach my $k (keys %$args) { $save->{$k} = $args->{$k} unless (exists $save->{$k}); } # Add the link either directly in, or into the change request table. if ($USER and $CFG->{user_direct_mod}) { if ($USER->{Status} ne 'Administrator') { if ($link->{LinkOwner} ne $USER->{Username}) { return { error => Links::language('MODIFY_NOTOWNER'), Category => $category, LinkID => $lid }; } } if ( my %fcols = $db->_file_cols() ) { foreach my $col_name ( keys %fcols ) { if ( $args->{$col_name."_del"} ) { $save->{$col_name."_del"} = ''; next }; my $fh = $args->{$col_name}; ref $fh or ( $save->{$col_name} = '', next ); $save->{$col_name} = $fh; } } my $res = $db->modify ($new) or return { error => $GT::SQL::error, Category => $category, LinkID => $lid }; $new_cats = $db->get_categories ($new->{ID}); } else { require GT::Dumper; my $chg_db = $DB->table ('Changes'); # ... handle files if ( my %fcols = $db->_file_cols() ) { foreach my $col_name ( keys %fcols ) { if ( $args->{$col_name."_del"} ) { $save->{$col_name."_del"} = ''; next }; my $fh = $args->{$col_name}; ref $fh or ( $save->{$col_name} = '', next ); my $fname = GT::CGI->escape(get_filename("$fh")); my $fpath = "$CFG->{admin_root_path}/tmp/$save->{ID}-$fname"; open F, ">$fpath"; binmode F; binmode $fh; my $buf; while( read $fh, $buf, 4096 ){ print F $buf; }; close F; $save->{$col_name} = $fpath; $save->{$col_name."_filename"} = get_filename("$fh"); } }; my $sth = $chg_db->select ( { LinkID => $new->{ID} }, ['LinkID']); if ($sth->rows) { my $href = $chg_db->get({ LinkID => $new->{ID} }) || {}; $href = eval $href->{ChgRequest}; my %fcols = $db->_file_cols(); foreach ( keys %fcols ) { my $fpath = $href->{$_} or next; ( $fpath ne $save->{$_} ) or next; ( $fpath !~ /\.\./) or next; ( $fpath =~ /^[\w\\\/\-\.%]+$/) or next; ( -e $fpath ) or next; ( $fpath =~ m,^$CFG->{admin_root_path}/tmp/,) or next; unlink $fpath; } $chg_db->update ( { LinkID => $new->{ID}, Username => $new->{LinkOwner}, ChgRequest => GT::Dumper->dump ( { data => $save, var => '' }) }, { LinkID => $new->{ID} } ) or return { error => $GT::SQL::error, Category => $category, LinkID => $lid }; } else { $chg_db->insert ( { LinkID => $new->{ID}, Username => $new->{LinkOwner}, ChgRequest => GT::Dumper->dump ( { data => $save, var => '' }) }) or return { error => $GT::SQL::error, Category => $category, LinkID => $lid }; } 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}) { send_email ($link, $new, $orig_cats, $new_cats); } $save->{Category} = join ("\n", values %$new_cats); # All done! return $save; } sub send_email { # -------------------------------------------------------- # Sends an email to the admin, letting him know that there is # a new link waiting to be validated. # my ($original, $new, $orig_cats, $new_cats) = @_; my ($to, $from, $subject, $msg, $text, $mailer, $c_origname, $c_newname, $host, $refer); # Check to make sure that there is an admin email address defined. $to = $CFG->{db_admin_email} || return; $from = $new->{'Contact_Email'}; $subject = "Modification to Database: $new->{Title}"; $c_origname = join ("\n", values %$orig_cats); $c_newname = join ("\n", values %$new_cats); $host = $ENV{REMOTE_HOST} ? "$ENV{REMOTE_HOST} ($ENV{REMOTE_ADDR})" : $ENV{REMOTE_ADDR} ? $ENV{REMOTE_ADDR} : 'none'; $refer = $ENV{HTTP_REFERER} ? $ENV{HTTP_REFERER} : 'none'; my %tags; foreach my $key (keys %$original) { $tags{"Original_" . $key} = $original->{$key}; } foreach my $key (keys %$new) { $tags{"New_" . $key} = $new->{$key}; } $tags{"Original_Category"} = $c_origname; $tags{"New_Category"} = $c_newname; $tags{"Host"} = $host; $tags{"Referer"} = $refer; my $cfg = Links::Config::load_vars(); $msg = GT::Template->parse ( 'email-mod.txt', { %tags, %$cfg }, { compress => 0, root => $CFG->{admin_root_path} . '/templates/admin' } ); # Then mail it away! require GT::Mail; $GT::Mail::error ||= ''; GT::Mail->send ( smtp => $CFG->{db_smtp_server}, sendmail => $CFG->{db_mail_path}, from => $from, subject => $subject, to => $to, msg => $msg, debug => $Links::DEBUG ) or die "Unable to send message: $GT::Mail::error"; } sub _category_list { # ------------------------------------------------------------------- # Return a list of all the categories. # my $category; if ($CFG->{db_gen_category_list}) { my $db = $DB->table('Links'); my $html = $DB->html($db, $IN); my @ids = $IN->param('CatLinks.CategoryID'); @ids or push @ids, $IN->param('ID'); $category = $html->get_all_categories(\@ids, 'CatLinks.CategoryID', 5); } else { my $db = $DB->table('Category'); my @ids = $IN->param('CatLinks.CategoryID'); @ids or push @ids, $IN->param('ID'); $db->select_options ('ORDER by Full_Name'); my $sth = $db->select ( { ID => \@ids }, ['ID','Full_Name'] ); my $names = $sth->fetchall_hashref(); for (@$names) { $category .= qq|$_->{Full_Name}
|; } } return $category; } sub get_filename { # ------------------------------------------------------------------- my $fpath = shift; my @path = split /[\\\/]/, $fpath; return pop @path; } 1;