作者 主題: phpBB還可以離線閱讀哦?!  (閱讀 3972 次)

0 會員 與 1 訪客 正在閱讀本文。

duncanlo

  • SA 苦力組
  • 俺是博士!
  • *****
  • 文章數: 7312
    • 檢視個人資料
phpBB還可以離線閱讀哦?!
« 於: 2002-11-23 18:07 »
以news的方式看phpbb的討論,
用perl script把phpbb模擬成news主機,
目前只提供"READ",還不行"POST",
感謝 Simon 熱情的分享!

下載修改設定後直接執行就可以,
然後最好用粉陽春的news reader去看文章,
我用Outook Express 5試也行,
中文部份只要變更Outlook Express的編碼,
主題及內文都可以正常顯示...

假如想把phpBB跟netnews作結合,
可以參考這個東東去修改:
http://stitt.org/usenetgrab/
不然就要改vbb那個news gateway的模組了!

代碼: [選擇]
#!/usr/bin/perl -w -T
#
# Usenet hack for phpbb and derivatives
#
# This script makes your phpbb forums available to people using a standard
# usenet news reader like rtin, or xnews.
#
# There are still problems with outlook express, and mozilla, although
# these _almost_ work as expected.
#
# This script is free. You are welcome to do whatever you want with it as
# long as you don't try and sell it or claim it as your own.
# The copyright is retained by the author.
#
# Author:
#  Singularo (simon@iseek.ws)
#
# CHANGELOG
# 16/01/02 - Initial Release
# 17/01/02 - Added phpbb2 support
# 18/01/02 - Fixed so it works with Outlook Express
#            Added "taint" flag to perl command line
#            Silently ignore blank commands
#

package MyNews;

use strict;
use vars qw(@ISA);
use NetServer::Generic;
use Net::Server::Fork;
use DBI;
use Mysql;

my $use_dbi = 1;
my $use_net_server = 1;

@ISA = qw(Net::Server::Fork);

my $posting_allowed = 1;       # Change to 0 to stop posting
my $debug = 1;                 # Turn on debuging
my $timeout = (20 * 60);       # Connection inactivity timeout - 20 mins

my $allow_user_kill = 0;       # Allow a user to kill the server

###########################################################################
# Performance options
# -------------------------------------------------------------------------
# Max Number of posts to select at once.
# Since this was developed on a P200, and running a mysql select for 27000
# records eats up all my memory, and the news reader hangs up, this reduces
# the number of posts fetched at once.
# On a big machine, you can probably make it bigger. Check the memory
# usage on news.pl with ps/top after you make a change.
#
# I think its caused by mysql sending the data back to the perl script, and
# of course, 27000+records is big.
#
my $granularity = 2000;        

#
# Put references (threading) into posts/xover
# Requires and extra query for each article
# Try with it on at first, set it to 0 if speed is slow
#
my $do_xref = 1;

#
# Fake the size of articles in xover (reduces the query result size hugely)
# Try with it off at first, set it to 1 if speed is slow
#
my $fake_size = 0;

my $db          = "";                 # database name
my $db_host     = "localhost";        # hostnmae
my $db_username = "root";             # username
my $db_password = "";                 # password

#
# News mode - 1 = phpbb, 2 = phpbb2
my $news_mode = 1;

my $sitename    = "";                 # your site
my $fullsitename = "";                # full site name
my $localip     = "";                 # your ip
my $timezone    = "-600";             # your timezone

my $server_port = 1190;

# You should not have to modify anything below here.
my $dbh;

my $curr_group;
my $curr_group_id;
my $curr_article;
my $curr_group_arts;

my $sep = "\.";

my %username_cache = ();

my $server_cb;

if ($use_net_server) {
$server_cb = sub {
my $self = $_[0];
my $cmd;

$dbh = db_connect();

greeting();

while (defined (my $tmp = <STDIN>)) {
$tmp =~ s/\r?\n$//;
$cmd = $tmp;

next if ($cmd =~ /^$/i);

console("$cmd") if ($debug > 0);

nntp_command($self, $cmd);
};

db_disconnect();
};

my (%config) = ("port"      => $server_port,
"callback"  => $server_cb,
"hostname"  => "",
"mode"      => "forking",
"timeout"   => $timeout,
);

my ($server) = new NetServer::Generic(%config);
print "Starting server using NetServer::Generic\n";
$server->run();
} else {
# See Net::Server manpage for explanation of the parameters
MyNews->run(
#log_level        => '4',
#log_file         => '/var/log/news',
port             => $server_port,
#host             => '*',
#user             => 'nobody',
#group            => 'nobody',
#background       => 0,
);
print "Starting server using NetServer::Generic\n";
}
exit 0;

sub process_request {
my $self = $_[0];
my $cmd;

$dbh = db_connect();

greeting();

eval {
local $SIG{ALRM} = sub { console("Timed Out!\n"); die; };

my $previous_alarm = alarm($timeout);
while (<STDIN>) {
s/\r?\n$//;
$cmd = $_;

next if ($cmd =~ /^$/i);

console("$cmd") if ($debug > 0);

nntp_command($self, $cmd);
alarm($timeout);
}
alarm($previous_alarm);
};

db_disconnect();
}

sub nntp_command {
my $self = $_[0];
my $cmd = $_[1];

# Process commands entered by the user
if ($cmd =~ /^(?:quit|exit|bye)/i) {
console("QUIT/EXIT/BYE Processing") if ($debug > 5);

reply_msg("205", "bye");
db_disconnect();
exit 0;
return;
}

if ($cmd =~ /^kill/i) {
console("KILL Processing") if ($debug > 5);

reply_msg("205", "bye");
db_disconnect();

if ($allow_user_kill) {
$self->server_close();
}

return;
}

if ($cmd =~ /^help/i) {
console("HELP Processing") if ($debug > 5);

reply_msg("100", "In your dreams");
return;
}

if ($cmd =~ /^mode reader/i) {
console("MODE READER Processing") if ($debug > 5);

greeting();
return;
}

# Select and list a particular group
if ($cmd =~ /^listgroup/i) {
$cmd =~ s/listgroup//i;
$cmd =~ s/\s+//g;

console("LISTGROUP Processing") if ($debug > 5);

my $group = $cmd;
$group =~ s/\_/ /g;

my $query = ("select forum_posts, forum_id " .
"from phpbb_forums " .
"where forum_name = '$group'");
my $query_results = db_fetch($query);
if (db_rows($query_results) > 0) {
($curr_group_arts, $curr_group_id) =
$query_results->fetchrow_array();
reply_msg("211", "list of article numbers follows");
} else {
reply_msg("411", "no such news group");
}
$curr_group = $group;
$curr_article = 1;

$query = ("select post_id " .
 "from phpbb_posts " .
 "where forum_id = $curr_group_id " .
 "order by post_id");
$query_results = db_fetch($query);
while (my ($post_id) = $query_results->fetchrow_array()) {
reply_msg("", "$post_id");
}
reply_msg("", ".");
return;
}

# List available newsgroups
if ($cmd =~ /^list/i) {
$cmd =~ s/list\s//i;
$cmd =~ s/list//i;

console("LIST Processing") if ($debug > 5);

my $output_descriptions;

if ($cmd =~ /^overview.fmt/i) {
$cmd =~ s/overview.fmt//i;
reply_msg("215", "information follows");
reply_msg("", "Subject:");
reply_msg("", "From:");
reply_msg("", "Date:");
reply_msg("", "Message-ID:");
reply_msg("", "References:");
reply_msg("", "Bytes:");
reply_msg("", "Lines:");
reply_msg("", "Xref:Full");
reply_msg("", ".");
return;
}

if ($cmd =~ /^newsgroups/i) {
$cmd =~ s/newsgroups\s//i;
$output_descriptions = 1;
}

if ($cmd =~ /^extensions/i) {
reply_msg("202", "Extension list follows");
reply_msg("", "XOVER");
reply_msg("", "LISTGROUP");
reply_msg("", ".");
return;
}

$cmd =~ s/active\s//i;

reply_msg("215", "list follows");

my $query = ("select forum_name, forum_desc, forum_posts " .
"from phpbb_forums");

my ($match) = $cmd;
if ($match) {
$query .= (" where forum_name like '$match%'");
}

my $query_results = db_fetch($query);
while (my ($group, $group_desc, $number_arts) =
  $query_results->fetchrow_array()) {
$group =~ s/ /\_/g;
if ($output_descriptions) {
reply_msg("", "$group, $group_desc");
} else {
reply_msg("", "$group $number_arts 1 y");
}
}
reply_msg("", ".");
return;
}

# List new newsgroups - cant do with phpbb
if ($cmd =~ /^newgroups/i) {
console("NEWGROUPS Processing") if ($debug > 5);

reply_msg("231", "list of new newsgroups follows");
reply_msg("", ".");
return;
}

# List of new messages
if ($cmd =~ /^newnews/i) {
$cmd =~ s/newnews\s//i;
$cmd =~ s/newnews//i;

console("NEWNEWS Processing") if ($debug > 5);

my ($groups, $tdate, $ttime, $extra1, $extra2) = split(/ /, $cmd);

my ($year) = substr($tdate, 0, 2);
my ($month) = substr($tdate, 2, 2);
my ($day) = substr($tdate, 4, 2);

my ($hour) = substr($ttime, 0, 2);
my ($min) = substr($ttime, 2, 2);
my ($sec) = substr($ttime, 4, 2);

my $search_date_time = sprintf("%s-%s-%s %s:%s:%s",
  $year, $month, $day,
  $hour, $min, $sec);

my $query = ("select post_id, topic_id, forum_id, poster_id " .
"from phpbb_posts ");
if ($news_mode == 1) {
$query .= "where post_time > '$search_date_time' ";
} elsif ($news_mode == 2) {
$query .= "where post_time > unix_timestamp($search_date_time) ";
}
$query .= ("order by post_id");

my $query_results = db_fetch($query);
if (db_rows($query_results) > 0) {
while (my ($post_id, $topic_id, $forum_id, $poster_id) =
  $query_results->fetchrow_array()) {

my $article_id =
art_id_encode($post_id, $topic_id, $forum_id, $poster_id);
reply_msg("", "<$article_id>");
}
}
reply_msg("", ".");
return;
}

# Select a particular newsgroup
if ($cmd =~ /^group/i) {
$cmd =~ s/group//i;
$cmd =~ s/^\s+//g;
$cmd =~ s/\_/ /g;

console("GROUP Processing") if ($debug > 5);

my $group = $cmd;

my $query = ("select forum_posts, forum_id " .
"from phpbb_forums " .
"where forum_name = '$group'");

my $query_results = db_fetch($query);
if (db_rows($query_results) > 0) {
($curr_group_arts, $curr_group_id) =
$query_results->fetchrow_array();

$query = ("select post_id " .
 "from phpbb_posts " .
 "where forum_id = $curr_group_id " .
 "order by post_id desc " .
 "limit 1");
$query_results = db_fetch($query);
my ($group_max_art_no) = $query_results->fetchrow_array();

reply_msg("211", "$curr_group_arts 1 $group_max_art_no $group");
} else {
reply_msg("411", "no such news group");
}
$curr_group = $group;
$curr_article = 1;
return;
}

if ($cmd =~ /^next/i or $cmd =~ /^last/i) {
console("NEXT/LAST Processing") if ($debug > 5);

if (!$curr_group) {
reply_msg("412", "no newsgroup selected");
}

if (!$curr_article) {
reply_msg("420", "no current article has been selected");
}

if ((($curr_article < $curr_group_arts) && $cmd =~ /^next/i)
or (($curr_article > 1) && $cmd =~ /^last/i)) {
my $query;
if ($cmd =~ /^next/i) {
$query = ("select post_id, topic_id, forum_id, poster_id " .
 "from phpbb_posts " .
 "where forum_id = $curr_group_id " .
 "and post_id > $curr_article " .
 "order by post_id " .
 "limit 1");
} else {
$query = ("select post_id, topic_id, forum_id, poster_id " .
 "from phpbb_posts " .
 "where forum_id = $curr_group_id " .
 "and post_id < $curr_article " .
 "order by post_id desc " .
 "limit 1");
}

my $query_results = db_fetch($query);
if (db_rows($query_results) > 0) {
my ($post_id, $topic_id, $forum_id, $poster_id) =
$query_results->fetchrow_array();

my $article_id =
art_id_encode($post_id, $topic_id, $forum_id, $poster_id);
my $article_number = $post_id;
$curr_article = $article_number;

reply_msg("233",
 "$article_number <$article_id> " .
 "request text seperately");
} else {
reply_msg("421", "no $cmd article in this group");
}
} else {
reply_msg("421", "no $cmd article in this group");
}
return;
}

if (($cmd =~ /^article/i) or
($cmd =~ /^body/i) or
($cmd =~ /^head/i) or
($cmd =~ /^stat/i)) {

console("ARTICLE Processing") if ($debug > 5);

my $mode = 0;

$cmd =~ s/article\s//i;

if ($cmd =~ /^body/i) {
console("BODY Only Processing") if ($debug > 5);

$cmd =~ s/body\s//i;
$mode = 1;
}

if ($cmd =~ /^head/i) {
console("HEAD Only Processing") if ($debug > 5);

$cmd =~ s/head\s//i;
$mode = 2;
}

if ($cmd =~ /^stat/i) {
console("STAT Only Processing") if ($debug > 5);

$cmd =~ s/stat\s//i;
$mode = 3;
}

my $article = $cmd;

my ($post_id, $topic_id, $forum_id, $poster_id);

if (!$forum_id) {
$forum_id = $curr_group_id;
}

if ($article =~ /\@/) {
# Remove square brackets
$article =~ s/\<//g;
$article =~ s/\>//g;

# We've been given an article id
# Convert it to an article, forum, etc number
($post_id, $topic_id, $forum_id, $poster_id) =
art_id_decode($article);

#$curr_group_id = $forum_id;
$article = $post_id;
}

# Build the query, taking into account differing requirements
my $query = ("select p.post_id, p.topic_id, p.forum_id, " .
"p.poster_id, t.post_text, s.topic_title, ");

if ($news_mode == 1) {
$query .= "date_format(p.post_time, '%a, %d %b %Y %T') ";
} elsif ($news_mode == 2) {
$query .= "from_unixtime(p.post_time, '%a, %d %b %Y %T') ";
}
$query .= ("from phpbb_posts as p, phpbb_posts_text as t, " .
  "phpbb_topics as s " .
  "where p.post_id = t.post_id " .
  "and p.topic_id = s.topic_id " .
  "and p.forum_id = $forum_id " .
  "and p.post_id >= $article " .
  "order by p.post_id " .
  "limit 1");

my $query_results = db_fetch($query);
if (db_rows($query_results) > 0) {
my ($post_id, $topic_id, $forum_id, $poster_id,
$post_text, $subject, $post_time) =
$query_results->fetchrow_array();

my ($user_email, $username) =
split(/:/, get_userdetails($poster_id));

my $article_id =
art_id_encode($post_id, $topic_id, $forum_id, $poster_id);
my $article_number = $post_id;
# $curr_article = $article_number;

if ($mode == 3) {
reply_msg("223",
 "$article_number <$article_id> " .
 "article exists");
return;
}

my $posted_text = remove_bb_code($post_text);
my $posted_text_len = length($posted_text);
my $posted_text_lines = ($posted_text =~ s/\n/\n/g);
if (!$posted_text_lines) {
$posted_text_lines = 1;
}

if ($mode != 1) {
reply_msg("220",
 "$article_number <$article_id> " .
 "article retrieved - head and body follow");
reply_msg("", "Path: $fullsitename!$sitename");
reply_msg("", "From: $user_email ($username)");
reply_msg("", "Newsgroups: $curr_group");
reply_msg("", "Followup-To: $curr_group");
reply_msg("", "Subject: $subject");
reply_msg("", "X-Newsreader: phpbb");
reply_msg("", "X-PhpBB-extra: ");

reply_msg("", "Date: $post_time $timezone");
reply_msg("", "Organization: $sitename");
reply_msg("", "Message-ID: <$article_id>");
reply_msg("", "NNTP-Posting-Host: $localip");
reply_msg("", "Content-Type: text/plain; charset=ISO-8859-1");
reply_msg("", "Content-Transfer-Encoding: 8bit");
reply_msg("", "NNTP-Posting-Date: $post_time GMT");

if ($do_xref) {
# Get other references and put them in
$query = ("select post_id, topic_id, " .
 "forum_id, poster_id " .
 "from phpbb_posts " .
 "where forum_id = $forum_id " .
 "and topic_id = $topic_id " .
 "and post_id < $post_id " .
 "order by post_id " .
 "limit 1");

my $query_results2 = db_fetch($query);
if (db_rows($query_results2) > 0) {
my ($post_id, $topic_id, $forum_id, $poster_id) =
$query_results2->fetchrow_array();
my $article_id2 =
art_id_encode($post_id, $topic_id, $forum_id,
 $poster_id);
reply_msg("", "References: <$article_id2>");
}
}

reply_msg("", "Bytes: " . $posted_text_len);
reply_msg("", "Lines: " . ($posted_text_lines + 1));
reply_msg("", "Xref: $fullsitename $curr_group:$article_number");
if ($mode == 2) {     # Head mode
reply_msg("", ".");
return;
}
reply_msg("", "");
} else {
reply_msg("222",
 "$article_number <$article_id> " .
 "article retrieved - body follows");
}
chomp $posted_text;
reply_msg("", $posted_text);
reply_msg("", ".");
} else {
reply_msg("430", "no such article found");
}
return;
}

if ($cmd =~ /^xover/i) {
$cmd =~ s/xover\s//i;
$cmd =~ s/xover//i;

console("XOVER Processing") if ($debug > 5);

my $stop = 0;
my $start = 0;

if (!$curr_group_id) {
reply_msg("412", "no newsgroup selected");
return;
}

reply_msg("224", "XOVER follows");

if ($cmd =~ /-/) {
($start, $stop) = split(/-/, $cmd);
my $i = $start;
my $j = $stop;
my $stopstr;

if (($j - $i) > $granularity) {
while ($i < $stop) {
$j = $i + $granularity - 1; # 1 less than the granularity
if ($j > $stop) {
$j = $stop;
}
$stopstr = "and p.post_id <= $j ";
send_xover_data($i, $stopstr);
$i += $granularity;
}
} else {
$stopstr = "and p.post_id <= $stop ";
send_xover_data($start, $stopstr);
}
} elsif ($cmd) {
$start = $cmd;
send_xover_data($start, "");
} else {
$start = 1;
send_xover_data($start, "");
}

reply_msg("", ".");
return;
}

console("Command: $cmd not recognised");
reply_msg("500", "unimplemented");
};

sub send_xover_data {
my $start = $_[0];
my $stop = $_[1];

my $query = ("select p.post_id, p.topic_id, p.forum_id, " .
"p.poster_id, ");

if (!$fake_size) {
$query .= "t.post_text, ";
} else {
$query .= "\"\", ";
}

$query .= "s.topic_title, ";

if ($news_mode == 1) {
$query .= "date_format(p.post_time, '%a, %d %b %Y %T') ";
} elsif ($news_mode == 2) {
$query .= "from_unixtime(p.post_time, '%a, %d %b %Y %T') ";
}

$query .= ("from phpbb_posts as p, phpbb_posts_text as t, " .
  "phpbb_topics as s " .
  "where p.post_id = t.post_id " .
  "and p.topic_id = s.topic_id " .
  "and p.forum_id = $curr_group_id " .
  "and p.post_id >= $start " .
  $stop .
  "order by p.post_id");

console("Query: $query") if ($debug > 1);

my $query_results = db_fetch($query);
while (my ($post_id, $topic_id, $forum_id, $poster_id,
  $post_text, $subject, $post_time) =
  $query_results->fetchrow_array()) {
my $posted_text;
my $posted_text_len;
my $posted_text_lines;

my ($user_email, $username) =
split(/:/, get_userdetails($poster_id));

my $article_id =
art_id_encode($post_id, $topic_id, $forum_id, $poster_id);
my $article_id2;
my $article_number = $post_id;

if (!$fake_size) {
$posted_text = remove_bb_code($post_text);
$posted_text_len = length($posted_text);
$posted_text_lines = ($posted_text =~ s/\n/\n/g);
if (!$posted_text_lines) {
$posted_text_lines = 1;
}
} else {
$posted_text = "";
$posted_text_len = int(rand(100) + 1);
$posted_text_lines = int(rand(10) + 1);
}
if ($do_xref) {
# Get other references and put them in
$query = ("select post_id, topic_id, forum_id, poster_id " .
 "from phpbb_posts " .
 "where forum_id = $forum_id " .
 "and topic_id = $topic_id " .
 "and post_id < $post_id " .
 "order by post_id " .
 "limit 1");

my $query_results2 = db_fetch($query);
if (db_rows($query_results2) > 0) {
my ($post_id, $topic_id, $forum_id, $poster_id) =
$query_results2->fetchrow_array();
$article_id2 =
art_id_encode($post_id, $topic_id, $forum_id, $poster_id);
$article_id2 = "<" . $article_id2 . ">";
} else {
$article_id2 = " ";
}
} else {
$article_id2 = " ";
}

reply_msg("",
 "$article_number\t" .
 "$subject\t" .
 "$username\t" .
 "$post_time $timezone\t" .
 "$article_id2\t" .
 "Xref:$sitename $curr_group:$article_number\t" .
 "$posted_text_len\t" .
 "$posted_text_lines");
}
return;
}

sub get_userdetails {
my $poster_id = $_[0];
my $user_email;
my $username;

if (!defined($username_cache{$poster_id})) {
my $query = ("select u.user_email, u.username " .
 "from phpbb_users as u " .
 "where u.user_id = $poster_id");
my $query_results = db_fetch($query);
if (db_rows($query_results) > 0) {
($user_email, $username) =
$query_results->fetchrow_array();
if (!$user_email) {
$user_email = "unknown\@$sitename";
}
$username_cache{$poster_id} = "$user_email:$username";
} else {
$user_email = "unknown\@$sitename";
$username = "unknown";
}
} else {
($user_email, $username) =
split(/:/, $username_cache{$poster_id});
}
return "$user_email:$username";
}

sub remove_bb_code {
    my $text = $_[0];

    $text =~ s/&/&/ig;
    $text =~ s/"/\"/ig;
    $text =~ s/</</ig;
    $text =~ s/>/>/ig;
    $text =~ s/\[size=[0-9]+\]|\[\/size\]//ig;
    $text =~ s/\[color=(\"\#)?[A-Za-z0-9]+(\")?\]|\[\/color\]//ig;
    $text =~ s/\[url(=)?(\")?//ig;
    $text =~ s/(\")?\](.+)\[\/url\]/$2/gi;
    $text =~ s/\[email(=)?(\")?//ig;
    $text =~ s/(\")?\](.+)\[\/email\]/$2/gi;
    $text =~ s/\[font=(\"\#)?[A-Za-z]+(\")?\]|\[\/font\]//ig;
    $text =~ s/\[list(=)?[1Aa]?\]|\[\/list(=)?[1Aa]?\]//ig;
    $text =~ s/\[\*\]/ - /ig;
    $text =~ s/\[(\/)?code\]//ig;

    $text =~ s/\r/\n/g;

    # strip out html linefeeds and replace them with real ones
    #$text =~ s/<BR>/\n/gi;
    $text =~ s/<BR>\n/\n/gi;
$text =~ s/<BR>/\n/gi;

    # strip out all other html
    $text =~ s/<.*?>//gi;

    return $text;
}

sub art_id_encode {
my $post_id = $_[0];
my $topic_id = $_[1];
my $forum_id = $_[2];
my $poster_id = $_[3];

return ("$post_id$sep$topic_id$sep$forum_id$sep$poster_id\@$sitename");
}

sub art_id_decode {
my $article_id = $_[0];

# Strip sitename
$article_id =~ s/\@.*//g;

return split(/$sep/, $article_id);
}

sub greeting {
if ($posting_allowed) {
print STDOUT "200 NNTP Server - Posting Allowed\n";
} else {
print STDOUT "201 NNTP Server - No Posting Allowed\n";
}
}

sub reply_msg {
my ($code) = $_[0];
my ($string) = $_[1];

if ($code) {
print STDOUT "$code $string\r\n";
# console("$code $string") if ($debug > 0);
} else {
print STDOUT "$string\r\n";
# console("$string") if ($debug > 0);
}
}

sub db_connect {
my $dbh;

if ($use_dbi) {
console("Connecting to database using DBI") if ($debug > 5);
my $dsn = "DBI:mysql:database=$db;host=$db_host";
$dbh = DBI->connect($dsn,
$db_username,
$db_password,
{
RaiseError => 1,
PrintError => 1,
}
) or die ("Cant connect to $db using " .
 "$db_username\@$db_host");
} else {
console("Connecting to database using Mysql module") if ($debug > 5);
$dbh = Mysql->connect($db_host,
 $db,
 $db_username,
 $db_password);
$dbh->selectdb($db);
}
    return $dbh;
}

sub db_disconnect {
if ($use_dbi) {
$dbh->disconnect;
} else {
undef $dbh;
}
}

sub db_fetch {
    my $sql = $_[0];
    my $qry;

console($sql) if ($debug > 1);

if (!defined($dbh)) {
$dbh = db_connect();
}

if ($use_dbi) {
console("Preparing Query") if ($debug > 1);
$qry = $dbh->prepare($sql)
|| console("$!");
console("Executing Query") if ($debug > 1);
$qry->execute()
|| console("Query failed ($sql) $!");
console("Returning Query") if ($debug > 1);
} else {
$qry = $dbh->query($sql);
}
    return $qry;
}

sub db_rows {
my $self = $_[0];

if ($use_dbi) {
return $self->rows;
} else {
return $self->numrows();
}
}

sub console {
my $message = $_[0];

print STDERR "$message\n";
}