# Copyright (C) 2005 FishGrove Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

package bb;

use strict;
use DBI;
use Jcode;
use HTML::Template;
use Config::Tiny;
use bb::L10N;
use Affelio::NetLib::Email qw(send_email);

##############################################
# Constructor 
##############################################
sub new {
    my ($class, $afap) = @_;
    unless ($afap) { die("bb::new: Error: missing username\n"); }
    
    my $self = {};
    $self->{afap}  = $afap;
    $self->{tmpfile}= $afap->get_userdata_dir()."/.sqltmp";
    $self->{category_tb}= "$afap->{install_name}_category";
    $self->{forum_tb}= "$afap->{install_name}_forum";
    $self->{topic_tb}= "$afap->{install_name}_topic";
    $self->{pref_tb}= "$afap->{install_name}_pref";
    $self->{spam_tb}= "$afap->{install_name}_spam";

    $self->{dbh} = undef;
    #initialize
    
    ###########################
    #Locale init
    ###########################
    $self->{lh} = bb::L10N->get_handle(($afap->get_site_info("locale"),
					$afap->get_site_info("locale")));
    ###########################
    my $sth;
    my $query;
    $self->{dbh} = $afap->get_userdata_dbh();
    unless(-f $self->{tmpfile}) {
	open(TMP,"> $self->{tmpfile}");
	close(TMP); 	    

	#Category table
	$query="category_id INTEGER".get_query_primarykey($self)."
			title		TEXT,
			timestamp	INTEGER,
			update_time	INTEGER,
			user		TEXT,
			afid		TEXT,
			last_user	TEXT,
			last_afid	TEXT,
			lock INTEGER,
			ord		INTEGER";
	    
	$self->{dbh}->do("CREATE TABLE $self->{category_tb} ($query)");
	
	#Forum table
	$query="forum_id INTEGER".get_query_primarykey($self)."
			category_id		INTEGER,
			title		TEXT,
			description TEXT,
			timestamp	INTEGER,
			update_time	INTEGER,
			user		TEXT,
			afid		TEXT,
			pwd TEXT,
			last_user	TEXT,
			last_afid	TEXT,
			topics		INTEGER,
			posts INTEGER,
			status INTEGER,
			lock INTEGER,
			ord		INTEGER";
	
	$self->{dbh}->do("CREATE TABLE $self->{forum_tb} ($query)");
	
	
	#Topic table
	$query="topic_id INTEGER".get_query_primarykey($self)."
			forum_id		INTEGER,
			title	TEXT,
			description	TEXT,
			icon	TEXT,
			user		TEXT,
			afid		TEXT,
			pwd TEXT,
			last_user	TEXT,
			last_afid	TEXT,
			view		INTEGER,
			posts INTEGER,
			status INTEGER,
			lock INTEGER,
			timestamp	INTEGER,
			update_time INTEGER";
		
	$self->{dbh}->do("CREATE TABLE $self->{topic_tb} ($query)");
	

	    #general setting table
	$query="key	TEXT,value TEXT";
	$self->{dbh}->do("CREATE TABLE $self->{pref_tb} ($query)");
	$self->{dbh}->do("INSERT INTO $self->{pref_tb} (key, value) VALUES ('title', 'Affelio BB')");
	$self->{dbh}->do("INSERT INTO $self->{pref_tb} (key, value) VALUES ('email', '$self->{afap}->{af}->{user__email1}')");
	$self->{dbh}->do("INSERT INTO $self->{pref_tb} (key, value) VALUES ('max_topics', '300')");
	$self->{dbh}->do("INSERT INTO $self->{pref_tb} (key, value) VALUES ('max_comments', '1000')");
	$self->{dbh}->do("INSERT INTO $self->{pref_tb} (key, value) VALUES ('num_topics', '50')");
	$self->{dbh}->do("INSERT INTO $self->{pref_tb} (key, value) VALUES ('num_comments', '50')");
	$self->{dbh}->do("INSERT INTO $self->{pref_tb} (key, value) VALUES ('max_sbjlen', '256')");
	$self->{dbh}->do("INSERT INTO $self->{pref_tb} (key, value) VALUES ('max_textlen', '2000')");
	
	
	#SPAM keywords table
	$query="spam_id INTEGER".get_query_primarykey($self)."
			keyword	TEXT";
	$self->{dbh}->do("CREATE TABLE $self->{spam_tb} ($query)");
    }
    
    bless $self, $class;
    return $self;
}

##############################################
# destructor
##############################################

sub DESTROY {
    my $self = shift;
    $self->{dbh}->disconnect;
}


##############################################
# createReplyTable
##############################################

sub createReplyTable {
    my ($self, $topic_id) = @_;
    my $reply_tb = "reply_".$self->escape($topic_id, 'int');
    
    my $query="reply_id INTEGER".get_query_primarykey($self)."
			title TEXT,
			user		TEXT,
			afid		TEXT,
			pwd  TEXT,
			comment		TEXT,
			icon		TEXT,
			timestamp	INTEGER,
			update_time INTEGER";
		
    $self->{dbh}->do("CREATE TABLE $reply_tb ($query)");
}

##############################################
# addCategory
##############################################

sub addCategory {
    my ($self, $title, $user, $afid) = @_;
    my $time = time;
    
#  	my $id = $self->getColumn("SELECT MAX(category_id) FROM $self->{category_tb}");
    $title = $self->escape_all($title);
    $user = $self->escape_all($user);
    $afid = $self->escape_all($afid);
    $self->checkContent($title, $user, $afid, "","","");
    
    my @same = $self->getall("SELECT category_id FROM $self->{category_tb} WHERE title='$title'");
    $self->errorExit('<AF_M text="A category of the proposed name already exists.">') if($#same >= 0);

    $self->{dbh}->do("INSERT INTO $self->{category_tb} (title, timestamp, update_time, user, afid, last_user, last_afid, lock, ord) VALUES ('$title', $time, $time, '$user', '$afid', '$user', '$afid', 0, 0)");
#  	$id = $self->getColumn("SELECT MAX(category_id) FROM $self->{category_tb}");
}


##############################################
# addForum
##############################################

sub addForum {
    my ($self, $category_id,$title, $description, $user, $afid, $pwd) = @_;
    my $time = time;
    my $crypt="";
    $category_id = $self->escape($category_id, 'int');
    $title = $self->escape_all($title);
    $user = $self->escape_all($user);
    $afid = $self->escape_all($afid);
    $description = $self->escape($description);
    $pwd = $self->escape_all($pwd);
    $crypt = $self->cryptPwd($pwd)	if ($pwd ne "");
    $self->checkContent($title, $user, $afid, $description, "", $pwd);
    
    my @same = $self->getall("SELECT forum_id FROM $self->{forum_tb} WHERE title='$title'");
    $self->errorExit('<AF_M text="A forum of the proposed name already exists.">') if($#same >= 0);
    
    $self->{dbh}->do("INSERT INTO $self->{forum_tb} (category_id, title, description, timestamp, update_time, user, afid, pwd, last_user, last_afid, topics, posts, status, lock, ord) VALUES ($category_id, '$title', '$description', $time, $time, '$user', '$afid', '$crypt', '$user', '$afid', 0, 0,0,0,0)");
    my $forum_id=$self->getColumn("SELECT MAX(forum_id) FROM $self->{forum_tb} WHERE category_id = $category_id");

    $self->{afap}->post_news($title, "", $user,
		     $self->{afap}->get_site_info("web_root") . "/apps/". 
		     $self->{afap}->{install_name} . "/view_forum.cgi?f_id=".$forum_id);

    $description =~ s/<br[^>]*>/\n/g;
    $self->sendBbMail("New Forum $title was created by $user.\n\n-----\n$description\n\n$self->{afap}->{app__web_root}/view_forum.cgi?f_id=$forum_id");

    return $forum_id;
}

##############################################
# addTopic
##############################################

sub addTopic {
    my ($self, $forum_id,$title, $description, $icon,$user, $afid, $pwd,$status) = @_;
    my $time = time;
    my $crypt="";
    my $num_topics = 0;
    my $num_posts = 0;
    $forum_id = $self->escape($forum_id, 'int');
    $title = $self->escape_all($title);
    $description = $self->escape($description);
    $icon = $self->escape_all($icon);
    $user = $self->escape_all($user);
    $afid = $self->escape_all($afid);
    $pwd = $self->escape_all($pwd);
    $status = $self->escape($status, 'int');
    $crypt = $self->cryptPwd($pwd)	if ($pwd ne "");
    $self->checkContent($title, $user, $afid, $description, $icon, $pwd);
    
    my @same = $self->getall("SELECT topic_id FROM $self->{topic_tb} WHERE title='$title'");
    $self->errorExit('<AF_M text="A topic of the proposed name already exists.">') if($#same >= 0);
    
    $self->{dbh}->do("INSERT INTO $self->{topic_tb} (forum_id, title, description, icon, user, afid, pwd, last_user, last_afid, view, posts, status, lock,timestamp, update_time) VALUES ($forum_id, '$title', '$description', '$icon', '$user', '$afid', '$crypt', '$user', '$afid', 0, 0, $status, 0, $time, $time)");
    
    my $topic_id=$self->getColumn("SELECT MAX(topic_id) FROM $self->{topic_tb} WHERE forum_id = $forum_id");

    $num_topics = $self->getColumn("SELECT count(forum_id) FROM $self->{topic_tb} WHERE forum_id=$forum_id");
    $num_posts = $self->getColumn("SELECT sum(posts) FROM $self->{topic_tb} WHERE forum_id=$forum_id");
    $num_posts = $num_posts+$num_topics;
    $self->{dbh}->do("UPDATE $self->{forum_tb} SET topics = $num_topics, posts = $num_posts, last_user = '$user', last_afid = '$afid', update_time = $time WHERE forum_id = $forum_id");

    $self->{afap}->post_news($title, "", $user,
		     $self->{afap}->get_site_info("web_root") . "/apps/". 
		     $self->{afap}->{install_name} . "/view_topic.cgi?t_id=".$topic_id);
    $description =~ s/<br[^>]*>/\n/g;
    $self->sendBbMail("New Topic $title was created by $user.\n\n-----\n$description\n\n$self->{afap}->{app__web_root}/view_topic.cgi?t_id=$topic_id");
    
    return $topic_id;
}


##############################################
# updateTopic
##############################################

sub updateTopic {
    my ($self, $topic_id,$title, $description, $icon,$user, $afid, $status,$lock) = @_;
    my $time = time;
    $topic_id = $self->escape($topic_id, 'int');
    $title = $self->escape_all($title);
    $description = $self->escape($description);
    $icon = $self->escape_all($icon);
    $user = $self->escape_all($user);
    $afid = $self->escape_all($afid);
    $status = $self->escape($status, 'int');
    $lock = $self->escape($lock, 'int');
    $self->checkContent($title, $user, $afid, $description, $icon, "");
    
    my @same = $self->getall("SELECT topic_id FROM $self->{topic_tb} WHERE title='$title'");
    $self->errorExit('<AF_M text="A topic of the proposed name already exists.">') if($#same >= 1);
    
    $self->{dbh}->do("UPDATE $self->{topic_tb} SET title='$title', description='$description', icon='$icon', status=$status, lock=$lock, user = '$user', afid = '$afid', timestamp = $time WHERE topic_id = $topic_id");
    $description =~ s/<br[^>]*>/\n/g;
    $self->sendBbMail("Topic $title was updated by $user.\n\n-----\n$description\n\n$self->{afap}->{app__web_root}/view_topic.cgi?t_id=$topic_id");

    return $topic_id;
}


##############################################
# updateForum
##############################################

sub updateForum {
    my ($self, $forum_id,$title, $description, $user, $afid) = @_;
    my $time = time;
    $forum_id = $self->escape($forum_id, 'int');
    $title = $self->escape_all($title);
    $description = $self->escape($description);
    $user = $self->escape_all($user);
    $afid = $self->escape_all($afid);
    $self->checkContent($title, $user, $afid, $description, "", "");
    
    my @same = $self->getall("SELECT forum_id FROM $self->{forum_tb} WHERE title='$title'");
    $self->errorExit('<AF_M text="A forum of the proposed name already exists.">') if($#same >= 1);
    
    $self->{dbh}->do("UPDATE $self->{forum_tb} SET title='$title', description='$description', user = '$user', afid = '$afid', timestamp = $time WHERE forum_id = $forum_id");
    $description =~ s/<br[^>]*>/\n/g;
    $self->sendBbMail("Forum $title was updated by $user.\n\n-----\n$description\n\n$self->{afap}->{app__web_root}/view_forum.cgi?f_id=$forum_id");

    return $forum_id;
}


##############################################
# addSpamkey
##############################################

sub addSpamkey {
    my ($self, $keyword) = @_;
    $keyword = $self->escape_all($keyword);
    my @same = $self->getall("SELECT keyword FROM $self->{spam_tb} WHERE keyword = '$keyword'");
    if($#same >= 0) { return; }
    $self->{dbh}->do("INSERT INTO $self->{spam_tb} (keyword) VALUES ('$keyword')");
}

##############################################
# removeSpamkey
##############################################

sub removeSpamkey {
    my ($self, $spam_id) = @_;
    $spam_id = $self->escape($spam_id, 'int');
    $self->{dbh}->do("DELETE FROM $self->{spam_tb} WHERE spam_id = $spam_id");
}

##############################################
# deleteReply
##############################################

sub deleteReply {
    my ($self, $topic_id, $reply_id) = @_;
    $reply_id = $self->escape($reply_id, 'int');
    my $reply_tb = "reply_".$self->escape($topic_id, 'int');
    $self->{dbh}->do("UPDATE $reply_tb SET user = NULL, afid = NULL, title = NULL, icon = NULL, comment = '\<AF_M text=\"Deleted\"\>' WHERE reply_id = $reply_id");
}

##############################################
# updateCategoryInfo
##############################################

sub updateCategoryInfo {
    my ($self, $category_id, $user, $afid) = @_;
    my $time = time;
    $category_id = $self->escape($category_id, 'int');
    $user = $self->escape_all($user);
    $afid = $self->escape_all($afid);
    
    $self->{dbh}->do("UPDATE $self->{category_tb} SET last_user = '$user', last_afid = '$afid', update_time = $time WHERE category_id = $category_id");
}


##############################################
# updateForumInfo
##############################################
#sub updateForumInfo {
#    my ($self, $forum_id, $user, $afid) = @_;
#    my $time = time;
#    $forum_id = $self->escape($forum_id, 'int');
#    $user = $self->escape_all($user);
#    $afid = $self->escape_all($afid);
#    $self->{dbh}->do("UPDATE $self->{forum_tb} SET last_user = '$user', last_afid = '$afid', update_time = $time WHERE forum_id = $forum_id");
#}


##############################################
# addViewCountTopic
##############################################

sub addViewCountTopic {
    my ($self, $topic_id) = @_;
    $topic_id = $self->escape($topic_id, 'int');
    $self->{dbh}->do("UPDATE $self->{topic_tb} SET view = view+1 WHERE topic_id = $topic_id");
}

##############################################
# getCategory
##############################################

sub getCategory {
    my ($self, $category_id) = @_;
    $category_id = $self->escape($category_id, 'int');
    my @ret = $self->getall("SELECT * FROM $self->{category_tb} WHERE category_id = $category_id");
    return $ret[0];
}

##############################################
# getForum
##############################################

sub getForum {
    my ($self, $forum_id) = @_;
    $forum_id = $self->escape($forum_id, 'int');
    my @ret = $self->getall("SELECT * FROM $self->{forum_tb} WHERE forum_id = $forum_id");
    return $ret[0];
}

##############################################
# getTopic
##############################################

sub getTopic {
    my ($self, $topic_id) = @_;
    $topic_id = $self->escape($topic_id, 'int');
    my @ret = $self->getall("SELECT * FROM $self->{topic_tb} WHERE topic_id = $topic_id");
    return $ret[0];
}

##############################################
# deleteTopic
##############################################

sub deleteTopic {
    my ($self, $topic_id, $forum_id) = @_;
    my $reply_tb = "reply_".$self->escape($topic_id, 'int');
    $forum_id = $self->escape($forum_id, 'int');
    $self->{dbh}->do("DELETE FROM $self->{topic_tb} WHERE topic_id = $topic_id");
    $self->{dbh}->do("DROP TABLE $reply_tb");
    my $num_topics = $self->getColumn("SELECT count(topic_id) FROM $self->{topic_tb} WHERE forum_id=$forum_id");

    my $num_posts = $self->getColumn("SELECT sum(posts) FROM $self->{topic_tb} WHERE forum_id=$forum_id");

    $num_posts += $num_topics;
    $self->{dbh}->do("UPDATE $self->{forum_tb} SET topics = $num_topics, posts = $num_posts WHERE forum_id = $forum_id");
}

##############################################
# getAllReplies
##############################################

sub getAllReplies {
    my ($self, $topic_id) = @_;
    my $reply_tb = "reply_".$self->escape($topic_id, 'int');
    return $self->getall("SELECT * FROM $reply_tb ORDER BY timestamp");
}

##############################################
# getReplies
##############################################

sub getReplies {
    my ($self, $topic_id, $end, $start) = @_;
    my $reply_tb = "reply_".$self->escape($topic_id, 'int');
#    print "$start:$end";

    return $self->getall("SELECT * FROM $reply_tb WHERE reply_id BETWEEN $start AND $end");
}

##############################################
# getReply
##############################################

sub getReply {
    my ($self, $topic_id, $reply_id) = @_;
    $reply_id = $self->escape($reply_id, 'int');
    my $reply_tb = "reply_".$self->escape($topic_id, 'int');
    my @ret = $self->getall("SELECT * FROM $reply_tb WHERE reply_id = $reply_id");
    return $ret[0];
}

##############################################
# getPreference
##############################################
sub getPreference {
    my $self = shift;
    my $sth = $self->{dbh}->prepare("SELECT * FROM $self->{pref_tb}");
    $sth->execute;
    
    my @pref;
    while(my @row = $sth->fetchrow_array) {
	push (@pref, @row);
    }
    $sth->finish;

    return @pref;
}

##############################################
# updatePreference
##############################################

sub updatePreference {
    my ($self,$title,$email,$max_topics,$max_comments,$num_topics,$num_comments,$max_sbjlen,$max_textlen) = @_;
    $self->errorExit('<AF_M text="Please input data correctly.">') if ($max_topics =~ /\D/ || $max_comments =~ /\D/ || $num_topics =~ /\D/ || $num_comments =~ /\D/ || $max_sbjlen =~ /\D/ || $max_textlen =~ /\D/);
    $title = $self->escape_all($title);
    
    $self->{dbh}->do("UPDATE $self->{pref_tb} SET value = '$title' WHERE key = 'title'");
    $self->{dbh}->do("UPDATE $self->{pref_tb} SET value = '$email' WHERE key = 'email'");
    $self->{dbh}->do("UPDATE $self->{pref_tb} SET value = '$max_topics' WHERE key = 'max_topics'");
    $self->{dbh}->do("UPDATE $self->{pref_tb} SET value = '$max_comments' WHERE key = 'max_comments'");
    $self->{dbh}->do("UPDATE $self->{pref_tb} SET value = '$num_topics' WHERE key = 'num_topics'");
    $self->{dbh}->do("UPDATE $self->{pref_tb} SET value = '$num_comments' WHERE key = 'num_comments'");
    $self->{dbh}->do("UPDATE $self->{pref_tb} SET value = '$max_sbjlen' WHERE key = 'max_sbjlen'");
    $self->{dbh}->do("UPDATE $self->{pref_tb} SET value = '$max_textlen' WHERE key = 'max_textlen'");
}


##############################################
# getAllComments
##############################################

sub getAllComments {
    my ($self, $topic_id) = @_;
    $topic_id = $self->escape($topic_id, 'int');
    return $self->getall("SELECT * FROM $self->{reply_tb} WHERE topic_id = $topic_id ORDER BY timestamp");
}



##############################################
# getNewestEntries
##############################################

#sub getNewestEntries {
#	my ($self, $num) = @_;
#	unless ($num) { $num = 5; }
#	return $self->getall("SELECT * FROM $self->{category_tb} ORDER BY update_time DESC LIMIT $num");
#}

##############################################
# getNewestCategoryId
##############################################

sub getNewestCategoryId {
  	my ($self) = @_;
  	my @ret = $self->getall("SELECT MAX(category_id) as category_id FROM $self->{category_tb}");
  	return $ret[0];
}

##############################################
# getNewestProjectId
##############################################

sub getNewestProjectId {
  	my ($self) = @_;
  	my @ret = $self->getall("SELECT MAX(forum_id) as forum_id FROM $self->{forum_tb}");
  	return $ret[0];
}

##############################################
# getAllCategories
##############################################

sub getAllCategories {
	my ($self) = @_;
	return $self->getall("SELECT * FROM $self->{category_tb} ORDER BY timestamp");
}

##############################################
# getAllForums
##############################################

sub getAllForums {
    my ($self,$category_id) = @_;
    $category_id = $self->escape($category_id, 'int');
    return $self->getall("SELECT * FROM $self->{forum_tb} WHERE category_id = $category_id ORDER BY update_time DESC");
}

##############################################
# getAllTopics
##############################################

sub getAllTopics {
    my ($self,$forum_id) = @_;
    $forum_id = $self->escape($forum_id, 'int');
    return $self->getall("SELECT * FROM $self->{topic_tb} WHERE forum_id = $forum_id ORDER BY status DESC, update_time DESC");
}

##############################################
# getAllSpamkeys
##############################################

sub getAllSpamkeys {
    my ($self) = @_;
    return $self->getall("SELECT * FROM $self->{spam_tb}");
}


##############################################
# getSumOfFiles
##############################################
sub getSumOfFiles {
    my ($self, $category_id) = @_;
    $category_id = $self->escape($category_id, 'int');
    return $self->getColumn("SELECT COUNT(*) FROM $self->{topic_tb} WHERE category_id = $category_id");
}

##############################################
# getNumOfComments
##############################################
#sub getNumOfComments {
#	my ($self, $topic_id) = @_;
##	my $reply_tb = "reply_".$topic_id;
##	return $self->getColumn("SELECT COUNT(*) FROM $reply_tb");
#	return $self->getColumn("SELECT posts FROM $topic_tb WHERE topic_id=$topic_id");
#}

##############################################
# addComment
##############################################

sub addComment {
    my ($self, $topic_id, $title, $user, $afid, $comment, $pwd, $icon) = @_;
    my $time = time;
    my $crypt = "";
    $topic_id = $self->escape($topic_id, 'int');
    $title = $self->escape_all($title);
    $user = $self->escape_all($user);
    $afid = $self->escape_all($afid);
    $comment = $self->escape($comment);
    $pwd = $self->escape_all($pwd);
    $icon = $self->escape_all($icon);
    $crypt = $self->cryptPwd($pwd)	if ($pwd ne "");
    $self->checkContent($title, $user, $afid, $comment, $icon, $pwd);
    
    my @same = $self->getall("SELECT reply_id FROM reply_$topic_id WHERE title = '$title' AND user = '$user' AND comment = '$comment'");
    $self->errorExit('<AF_M text="A same comment already exists.">') if($#same >= 0);
    
    $self->{dbh}->do("INSERT INTO reply_$topic_id (title, user, afid, comment, icon, pwd, timestamp) VALUES ('$title', '$user', '$afid', '$comment', '$icon', '$crypt', $time)");
    
    $self->{dbh}->do("UPDATE $self->{topic_tb} SET posts = posts+1 WHERE topic_id = $topic_id");
    my $forum_id = $self->getColumn("SELECT forum_id FROM $self->{topic_tb} WHERE topic_id = $topic_id");
    $self->{dbh}->do("UPDATE $self->{forum_tb} SET posts = posts+1, last_user = '$user', last_afid = '$afid', update_time = $time WHERE forum_id = $forum_id");

    $self->{dbh}->do("UPDATE $self->{topic_tb} SET last_user = '$user', last_afid = '$afid', update_time = $time WHERE topic_id = $topic_id");
    
    $self->{afap}->post_news($title, "", $user,
		     $self->{afap}->get_site_info("web_root") . "/apps/". 
		     $self->{afap}->{install_name} . "/view_topic.cgi?t_id=".$topic_id);
    $comment =~ s/<br[^>]*>/\n/g;
    $self->sendBbMail("New Comment $title was written by $user.\n\n-----\n$comment\n\n$self->{afap}->{app__web_root}/view_topic.cgi?t_id=$topic_id");
}

##############################################
# sendBbMail
##############################################
sub sendBbMail {
    my ($self,$msg) = @_;
    my $mailto = $self->getColumn("SELECT value FROM $self->{pref_tb} WHERE key = 'email'");
    my $bb_title = $self->getColumn("SELECT value FROM $self->{pref_tb} WHERE key = 'title'");
    Affelio::NetLib::Email::send_email($self->{afap}->{af}->{cmd__sendmail}, "$self->{afap}->{af}->{user__email1}", "Affelio BB", $mailto, "Message from $bb_title", "$msg");
}

##############################################
# getComments
##############################################
sub getComments {
    my ($self, $id) = @_;
    $id = $self->escape($id, 'int');
    return $self->getall("SELECT * FROM $self->{reply_tb} WHERE id = $id ORDER BY timestamp");
}

##############################################
# getCommentsNo
##############################################
sub getCommentsNo {
    my ($self, $id) = @_;
    $id = $self->escape($id, 'int');
    return $self->getColumn("SELECT COUNT(*) FROM $self->{reply_tb} WHERE id = $id");
}

##############################################
# getColumn
##############################################
sub getColumn {
    my ($self, $query) = @_;
    my $sth = $self->{dbh}->prepare($query);
    $sth->execute;
    my $num;
    $sth->bind_columns(undef, \$num);
    $sth->fetch;
    $sth->finish;
    if($num) {
	return $num;
    }
    else {
	return 0;
    }
}

##############################################
# get all columns
##############################################
sub getall {
    my ($self, $query) = @_;
    my $sth = $self->{dbh}->prepare($query);
    $sth->execute;
    
    my @ret;
    while(my $row = $sth->fetchrow_hashref) {
	push @ret, $row;
    }
    $sth->finish;
    
    return @ret;
}

##############################################
# escape
##############################################
sub escape {
    my ($self, $str, $type) = @_;
    
    if ($type eq 'int') {
	return int($str);
    }
    else {
	$str =~ s/[\t\a]//g;
	$str =~ s/&/&amp;/g;
	$str =~ s/["']/&quot;/g;
	$str =~ s/</&lt;/g;
	$str =~ s/>/&gt;/g;
	$str =~ s/&lt;(\/?)(a|p|i|b|big|strong|small|em|u|blockquote)&gt;/<$1$2>/ig;
	$str =~ s/&lt;a +href=(&quot;)?(s?https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#]+) *(&quo\
t;)? *&gt;/<a href="$2">/ig;
	$str =~ s/&quot;"/"/g;
	$str =~ s/(\r\n|\r|\n)/<br \/>/g;
	
	while ($str =~ /(<(a|p|i|b|big|strong|small|em|u|blockquote)\b(?:(?!<\/\2>).)*(?:<\2>|$))\
/sigx) {
	    $self->errorExit("Error: You may mistype a tag or forget to close it.");
	}
    }
    
    return $str;
}

sub escape_all {
    my ($self, $str) = @_;
    
    $str =~ s/[\t\a]//g;
    $str =~ s/&/&amp;/g;
    $str =~ s/['"]/&quot;/g;
    $str =~ s/</&lt;/g;
    $str =~ s/>/&gt;/g;
    $str =~ s/(\r\n|\r|\n)/<br \/>/g;
    
    return $str;
}

sub autolink {
	my ($self, $str) = @_;
	
	$str =~ s/(https?|ftp)\:([\w|\:\!\#\$\%\=\&\-\^\`\\\|\@\~\[\{\]\}\;\+\*\,\.\?\/]+)/<a href=\"$1\:$2\" target=\"_blank\">$1\:$2<\/a>/ig;

	return $str;
}
############################################################################
# get user URI
############################################################################
sub getUserURI {
    my ($self, $uri) = @_;
    $uri=$self->{afap}->get_site_info("web_root").'/outgoing.cgi?dest_url='.$uri;
    return $uri;
}

############################################################################
# get primary key for DBs
############################################################################
sub get_query_primarykey {
    my ($self) = @_;
    my $DBConfig = Config::Tiny->new();
    $DBConfig = Config::Tiny->read("$self->{afap}->{af}->{site__user_dir}/db.cfg");
    my $db_type = $DBConfig->{db}->{type};
    my $query;

    if ($db_type eq "sqlite"){
	$query = " PRIMARY KEY,";
    }elsif ($db_type eq "mysql"){
	$query = " AUTO_INCREMENT PRIMARY KEY,";
    }
    return $query;
}

##############################################
# cryptPwd
##############################################
sub cryptPwd {
    my ($self, $pwd) = @_;
    if ( $pwd !~ /[a-zA-Z0-9]/){
	$self->errorExit('<AF_M text="Please use alphameric characters.">');
    }
    if (length($pwd)<4){
	$self->errorExit('<AF_M text="Please input more than 4 characters.">');
    }
    my @salts = ( "A".."Z", "a".."z", "0".."9", ".", "/" );
    my $salt = $salts[int(rand(64))] . $salts[int(rand(64))];
    my $crypt = crypt($pwd, $salt);
    return $crypt;
}

##############################################
# checkPwd
##############################################
sub checkPwd {
    my ($self, $pwd) = @_;
    $self->errorExit('<AF_M text="Please input a password.">') if($pwd eq "");
    if ( $pwd !~ /[a-zA-Z0-9]/){
	$self->errorExit('<AF_M text="Please use alphameric characters as your password.">');
    }
    if (length($pwd)<4){
	$self->errorExit('<AF_M text="Please input more than 4 characters as your password.">');
    }
}

##############################################
# cryptID
##############################################
sub cryptID {
    my ($self, $pwd) = @_;
    if ( $pwd !~ /[a-zA-Z0-9]/){
	$self->errorExit('<AF_M text="Please use alphameric characters.">');
    }
    if (length($pwd)<4){
	$self->errorExit('<AF_M text="Please input more than 4 characters.">');
    }
    my $salt = substr($pwd ,0,2);
    
    my $crypt = crypt($pwd, $salt);
    return $crypt;
}


############################################################################
#L10N added by slash
############################################################################
sub translate_templateL10N{
    my $af=shift;
    my $mesg = shift;
    
    my $tag_body ="";
    my $text_value="";
    my $param_value="";
    
    while( $mesg =~ /<AF_M ([^>]+)>/ ){
	$tag_body = $1;
	
	$tag_body =~ /text(\s*)=(\s*)["']([^"']*)["'](\s*)param(\s*)=(\s*)["']([^"']*)["']/;
	$text_value=$3;
	$param_value=$7;
	if($text_value eq ""){
	    $tag_body =~ /text(\s*)=(\s*)["']([^"']*)["']/;
	    $text_value=$3;
	}
	
	my $sbst = $af->{lh}->maketext($text_value, $param_value);
	$mesg =~ s/\Q<AF_M $tag_body>\E/$sbst/g;
    }
    return($mesg);
}

############################################################################
#check Content
############################################################################
sub checkContent {
    my ($self, $title, $user, $afid, $description, $icon, $pwd) = @_;
    my $max_sbjlen = $self->getColumn("SELECT value FROM $self->{pref_tb} WHERE key = 'max_sbjlen'");
    my $max_textlen = $self->getColumn("SELECT value FROM $self->{pref_tb} WHERE key = 'max_textlen'");
    $self->errorExit('<AF_M text="Too long title.">') if (length($title)>int($max_sbjlen));
    $self->errorExit('<AF_M text="Too long content.">') if (length($description)>int($max_textlen));
    $self->errorExit('<AF_M text="Too long nickname.">') if (length($user)>256);
    $self->errorExit('<AF_M text="Too long URI.">') if (length($afid)>256);
    $self->errorExit('<AF_M text="Too long filename of icon.">') if (length($icon)>64);
    $self->errorExit('<AF_M text="Too long password.">') if (length($pwd)>32);

    my @spam_key = $self->getall("SELECT keyword FROM $self->{spam_tb}");
    foreach(@spam_key){
	if ($description =~ /$_->{keyword}/ ||
	    $title =~ /$_->{keyword}/){
	    $self->errorExit('<AF_M text="Your message was quarantined as suspected spam.">');
	}
    }
}


############################################################################
#Show Error
############################################################################
sub errorExit {
    my ($self,$msg) = @_;
    my $affelio_id = $self->{afap}->get_visitor_info("afid");
    my $visitor_type=$self->{afap}->get_visitor_info("type");
    
    if($visitor_type eq ""){
	$visitor_type="pb";
    }
    my $tmpl = HTML::Template->new(filename => "./templates/error.tmpl");
    $tmpl->param(V_TYPE => $visitor_type);
    $tmpl->param(AF_ID => $affelio_id);
    $tmpl->param(MSG => $msg);

    print $self->translate_templateL10N( $tmpl->output );
    print $self->{afap}->get_HTML_footer();
    exit;
}

1;



