# ================================================================== # Gossamer Forum - Advanced web community # # Website : http://gossamer-threads.com/ # Support : http://gossamer-threads.com/scripts/support/ # Revision : $Id: Tools.pm,v 1.28 2002/10/30 00:09:57 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 GForum::Tools; # ================================================================== use strict; use GForum qw/$IN $DB $CFG/; use vars qw/$TPLDIR $MASK/; sub language_editor { # ------------------------------------------------------------------ # Loads the language file editor. # my ($dir, $font, $file, $message, $table); my $selected_dir = $IN->param('tpl_dir') || $CFG->{default_template_set} || 'default'; $dir = "$CFG->{admin_root_path}/templates/$selected_dir"; $file = 'language.txt'; $font = 'face="Tahoma,Arial,Helvetica" size="2"'; # Load the language file my $language = GT::Config->load("$dir/$file", { create_ok => 1, inheritance => 1, local => 1, debug => $CFG->{debug_level}, header => <
param('save')) { if (-e "$dir/$file" and ! -w _) { $message = "Unable to overwrite file: $file (permission denied). Please set permissions properly and save again."; } elsif (! -e _ and ! -w $dir) { $message = "Unable to create new files in directory $selected_dir. Please set permissions properly and save again."; } else { foreach my $code ($IN->param()) { next unless ($code =~ /^save-(.*)/); my $key = $1; if ($IN->param("del-$key")) { delete $language->{$key}; next; } my $val = $IN->param($code); $val =~ s/\r?\n/\n/g; # Remove windows linefeeds. $language->{$key} = $val; } if (my $var = $IN->param('new') and my $val = $IN->param('new-val')) { $val =~ s/\r?\n/\n/g; $language->{$var} = $val; } $language->save(); $message = "Changes saved successfully."; } } my $prefix = $IN->param('prefix'); my %prefix_list; $table = ""; foreach my $code (sort keys %$language) { if ($code =~ /^(.+?)_/) { $prefix_list{$1}++; } next if ($prefix and $code !~ /^$prefix(?=_|\b)/); my $lang = $IN->html_escape($language->{$code}); $table .= qq~~; } $table .= qq~
CodeDescriptionDelete
$code
New:  
~; my $prefix_output; foreach my $prefix (sort keys %prefix_list) { $prefix_output .= qq~ $prefix ($prefix_list{$prefix}) |~; } chop $prefix_output if ($prefix_output); my $d_select_list = template_dir_select($selected_dir)->{dir_select}; my @prefix_list = sort keys %prefix_list; my $prefix_list = sub { my $prefix = shift @prefix_list or return; return { prefix => $prefix, num_vars => $prefix_list{$prefix} }; }; return { language_table => $table, dir_select => $d_select_list, tpl_dir => $selected_dir, message => $message, prefix_list => $prefix_list }; } sub global_editor { # ------------------------------------------------------------------ # Loads the global template vars. # my ($font, $message, $table); my $selected_dir = $IN->param('tpl_dir') || $CFG->{default_template_set} || 'default'; my $dir = "$CFG->{admin_root_path}/templates/$selected_dir"; my $file = "globals.txt"; $font = qq{face="Tahoma,Arial,Helvetica" size="2"}; if ($IN->param('save')) { # Load the globals file. my $globals = GT::Config->load("$dir/$file", { create_ok => 1, inheritance => 1, local => 1, debug => $CFG->{debug_level}, header => <
param()) { next unless ($code =~ /^save-(.*)/); my $key = $1; if ($IN->param("del-$key")) { delete $globals->{$key}; next; } my $val = $IN->param($code); $val =~ s/\r?\n/\n/g; # Remove windows linefeeds. $globals->{$key} = $val unless $globals->{$key} eq $val; } if (my $key = $IN->param('new') and my $val = $IN->param('new-val')) { $val =~ s/\r?\n/\n/g; $globals->{$key} = $val; } $globals->save(); $message = "Changes saved successfully."; } } # Load the globals file. If saving, load it again to take into account any deleted keys. my $globals = GT::Config->load("$dir/$file", { create_ok => 1, inheritance => 1, local => 1, debug => $CFG->{debug_level}, header => <
html_escape($globals->{$code}); $table .= qq~$codeDelete
~; } $table .= qq~New:  ~; my $d_select_list = template_dir_select($selected_dir)->{dir_select}; return { global_table => $table, dir_select => $d_select_list, message => $message }; } sub template_editor { # ------------------------------------------------------------------ # Loads the template editor. # require GT::Template::Editor; my $editor = new GT::Template::Editor( root => $CFG->{admin_root_path} . '/templates', backup => $CFG->{template_backups}, cgi => $IN ); return $editor->process; } sub editor_size { # ------------------------------------------------------------------ # Sets the editor default size. # my $editor_rows = $IN->param('cookie-editor_rows') || $IN->cookie('editor_rows') || 15; my $editor_cols = $IN->param('cookie-editor_cols') || $IN->cookie('editor_cols') || 60; return { editor_rows => $editor_rows, editor_cols => $editor_cols }; } sub template_dir_select { # ---------------------------------------------------------------------- # Returns the template loop variable 'dir_select' with iteration value: # directory - the name of the directory # my $selected_dir = shift || 'default'; my @dirs; my $dir = "$CFG->{admin_root_path}/templates"; local *TPL; opendir TPL, $dir or die "unable to open directory: '$dir' ($!)"; for (sort { lc $a cmp lc $b } readdir TPL) { next if $_ eq '.' or $_ eq '..' or $_ eq 'admin' or $_ eq 'CVS' or not -d "$dir/$_"; my $h = { directory => $_ }; $h->{dir_selected} = 1 if $_ eq $selected_dir; push @dirs, $h; } closedir TPL; return { dir_select => \@dirs }; } # Returns 0 or 1 - 1 means the template is okay. Takes full path, filename, and # mask (optional) as arguments. sub _is_template { my ($dir, $file, $mask) = @_; return 0 if substr($file, -4) eq '.bak' or not -f "$dir/$file" or not -r _ or $file eq 'README' or $file eq 'language.txt' or $file eq 'globals.txt' or ($mask ne '.*\.eml' and substr($_, -4) eq '.eml') or $mask and $file !~ /^$mask$/i; return 1; } sub template_file_select { # ------------------------------------------------------------------------- # Returns the template loop variable 'file_select' with iteration values: # filename - the filename # local - Indicates a 'local' file. # If local set: new_local - Indicates a local file without a system file # my $selected_dir = shift || $CFG->{default_template_set} || 'default'; my $mask = shift || ''; ($mask = quotemeta $mask) =~ s/\\\*/.*/g; my $dir = $CFG->{admin_root_path} . "/templates/" . $selected_dir; local *TPL; opendir TPL, "$dir/local" or die "Unable to open directory '$dir/local': $!"; my %files = map { _is_template("$dir/local", $_, $mask) ? ($_ => 2) : () } readdir TPL; opendir TPL, $dir or die "Unable to open directory '$dir': $!"; for (readdir TPL) { next unless _is_template($dir, $_, $mask); $files{$_}++; } closedir TPL; # %file now has keys of filenames, and values of: 1 => system, 2 => local, 3 => both return { file_select => [map +{ filename => $_, $files{$_} >= 2 ? (local => 1, new_local => $files{$_} == 3) : (local => 0) }, sort { lc $a cmp lc $b } keys %files] }; } sub template_file_stats { # Returns information about a file. Takes the following arguments: # - filename # - template set # The following tags are returned: # - file_path - the full path to the file, relative to the admin root directory # - file_size - the size of the file in bytes # - file_local - 1 or 0 - true if it is a local file # - file_restore - 1 or 0 - true if it is a local file and a non-local file of the same name exists (The non-local can be restored) # - file_mod_time - the date the file was last modified require GT::Date; my ($file, $tpl_dir) = @_; $tpl_dir ||= $CFG->{default_template_set} || 'default'; my $return = { file_local => 1, file_restore => 1 }; my $dir = "$CFG->{admin_root_path}/templates/$tpl_dir"; if (-f "$dir/local/$file" and -r _) { $return->{file_path} = "templates/$tpl_dir/local/$file"; $return->{file_size} = -s _; $return->{file_local} = 1; $return->{file_mod_time} = GForum::date((stat _)[9]); $return->{file_restore} = (-f "$dir/$file" and -r _) ? 1 : 0; } else { $return->{file_path} = "templates/$tpl_dir/$file"; $return->{file_size} = -s "$dir/$file"; $return->{file_local} = 0; $return->{file_restore} = 0; $return->{file_mod_time} = GForum::date((stat _)[9]); } return $return; } sub quick_links { # ------------------------------------------------------------------- # Add quick links to the admin menu. # my $name = $IN->param('name'); my $url = $IN->param('url'); my $manage = $IN->param('manage') || ''; my @to_delete = $IN->param('remove'); if ($IN->param('delete')) { foreach my $url (@to_delete) { delete $CFG->{quick_links}->{$url}; } $CFG->save; } if ($name and $url) { $CFG->{quick_links}->{$url} = $name; $CFG->save; } my $output; foreach my $url (sort { $CFG->{quick_links}->{$a} cmp $CFG->{quick_links}->{$b} } keys %{$CFG->{quick_links}}) { $output .= qq~ ~ if ($manage); $output .= qq~  $CFG->{quick_links}->{$url}
~; } return { quick_links => \$output }; } sub sql_monitor { # ------------------------------------------------------------------- # Runs queries. # my $query = $IN->param('query'); my $file = $IN->param('saveto'); my $table = $DB->table('Post'); $table->connect(); my $return = { db_prefix => scalar $DB->prefix }; if ($query) { my ($sth, $rv, $output); eval { $sth = $table->prepare ($query); }; ($@ or !defined $sth) and return { error => "Query Error: $GT::SQL::error" }; eval { $rv = $sth->execute(); }; ($@ or !defined $rv) and return { error => "Query Error: $GT::SQL::error" }; my $rows = $sth->rows || 0; $file and (open (FILE, ">$file") or return { error => "Unable to open file: '$file'. Reason: $!" }); if ($query =~ /^\s*(SELECT|DESCRIBE|SHOW|sp_)/i) { $output = "
Your query returned $rows rows. \n\n";
            while (my $arr = $sth->fetchrow_arrayref) {
                $file ? (print FILE join ("\t", @$arr), "\n") : ($output .= join ("\t", @$arr) . "\n");
            }
            $output .= "
"; } else { $output = "Rows affected: $rows"; } $return->{result} = $output; } return $return; } sub remote_user { # ------------------------------------------------------------------- # Returns a remote_user environment variable. # my $user = $ENV{REMOTE_USER} or return ''; $user eq '-' and return ''; # xitami sets it to '-', ugh. return $user; } sub auth_users { # ------------------------------------------------------------------- # Shows a list of users in the .htpasswd file. # my $htpasswd = $CFG->{admin_root_path} . "/.htpasswd"; open (HTPAS, "< $htpasswd") or die "Unable to open: $htpasswd ($!)"; my @users = ; close HTPAS; my $delete_list = '' if @users; return { delete_list => \$delete_list }; } 1;