Приглашаем посетить
Гаршин (garshin.lit-info.ru)

CHAT

#!/usr/local/bin/perl
############################################################
#                         CHAT.CGI
#
# This script was written by Gunther Birznieks. 
# Date Created: 5-15-96
#
#   You may copy this under the terms of the GNU General Public
#   License or the Artistic License which is distributed with
#   copies of Perl v5.x for UNIX.
#
# Purpose: Provides a script for real-time chatting on
#          A Web Page
#
# Special Notes: This script uses similar routines to the
#   authentication library.  The session file is used to
#   store last_read counter for the chat.
# 
#
############################################################

# Always set a path to the external libraries
$lib = ".";
require "$lib/cgi-lib.pl";
require "chat-html.pl";

# Read the form variables in
&ReadParse;

# 
# We print the magic header.  HOWEVER, since 
# we are constantly forcing the user to reload
# the web page for new chat information, if there
# is currently a session going on, we need to
# send a no-cache message to the browser to tell
# it not to waste memory/disk space caching the
# multiple Chat Pages.
#
print "Content-type: text/html\n";

if ($in{'session'} ne "") {
    print "Pragma: no-cache\n\n";
} else {
    print "\n";
}

#
# The chat_ variables are initial form
# variables read in from the first screen
# where the user signs up for the chat mode
#
# $refresh_rate is > 0 if the user
# has a browser that supports auto 
# refreshing using the META Tag such as
# netscape.
#
# How many old, is the amount of 
# old messages to display with the new
# messages.
#
# The above to variables are written to
# the session files.
#
$chat_username = $in{'chat_username'};
$chat_email = $in{'chat_email'};
$chat_http = $in{'chat_http'};
$refresh_rate = $in{'refresh_rate'};
$how_many_old = $in{'how_many_old'};

#
# Are we using frames? 
# $frames = "on" if we are using them
# 
# $fmsgs means the script was called
# from the frame with the messages in them
# 
# $fsubmit means the script was called
# from the frame with the submit chat 
# message form in it.
#
$frames = $in{'frames'};
$fmsgs = $in{'fmsgs'};
$fsubmit = $in{'fsubmit'};

# 
# $user_last_read is the last read
# chat message for the user in the chat
# room
#
$user_last_read = 0;

#
# $chat_room is the chat_room a person
# is in.
#
# $setup is the setup file to read.  If
# no setup is specified, then $setup will
# be set equal to "chat".
#
$chat_room = $in{'chat_room'};
$setup = $in{'setup'};

if ($setup eq "") {
    $setup = "chat";
}

require "$setup.setup";

#
# Set up a default chat_script
# if we did not define one
#
if ($chat_script eq "") {
    $chat_script = "chat.cgi";
}

#
# The following are variables
# related to the various chat operations
#

$enter_chat = $in{'enter_chat'};
$refresh_chat = $in{'refresh_chat'};
$submit_message = $in{'submit_message'};
$logoff = $in{'logoff'};
$occupants = $in{'occupants'};

# 
# The following are needed for submitting
# a message
#

$chat_to_user = $in{'chat_to_user'};
$chat_message = $in{'chat_message'};

$session = $in{'session'};

#
# If there is no session id, we need to create one
#

$new_session = "no";
if ($session eq "") {
    if ($chat_username eq "") {
        if ($enter_chat eq "") {
            &PrintChatEntrance($setup,"");
        } else {
            &PrintChatEntrance($setup,
             "Hey! You did not " .
             "enter a username.");
        }
    exit;
    }
    $new_session = "yes";
    $session = &MakeSessionFile($chat_username, $chat_email,
        $chat_http, $refresh_rate, 
        $how_many_old, "0");
}

#
# If the user logs in correctly, we
# should be able to get the chat room info
# we need
# 

($chat_room_name, $chat_room_dir) =
  &GetChatRoomInfo($chat_room);

#
# We need to get the current session
# information including the current
# high message number.
# 

($user_name, $user_email, $user_http,
 $refresh_rate, $how_many_old, 
 $user_last_read, $high_message) = 
          &GetSessionInfo($session, $fsubmit, $frames);

#
# If we are announcing the entry of
# users in the chat room, we need to submit
# a message to that effect
#

if ($chat_announce_entry eq "on" &&
    $new_session eq "yes") {
    $submit_message = "on";
    $chat_to_user = "ALL";
    $chat_message = "Automatic Message: $user_name Joined Chat Room";
}

#
# If the logoff button was pressed, we generate
# an automatic message
#

if ($logoff ne "") {
    $submit_message = "on";
    $chat_to_user = "ALL";
    $chat_message = "Automatic Message: $user_name Logged Off";
}

#
# We use the current date and time
# in the program
#
($min, $hour, $day, $mon, $year) = 
    (localtime(time))[1,2,3,4,5];
$mon++;
if (length($min) < 2) {
    $min = "0" . $min;
}
$ampm = "AM";
$ampm = "PM" if ($hour > 11);
$hour = $hour - 12 if ($hour > 12);
$current_date_time = 
    "$mon/$day/$year $hour:$min $ampm";

# If we are entering a new message,
# we need to write it to a file
#
if ($submit_message ne "") {
    if ($chat_to_user eq "" ||
        $chat_to_user =~ /^all$/i ||
        $chat_to_user =~ /everyone/i) {
        $chat_to_user  = "ALL";
    }
  
    $high_number = &GetHighMessageNumber;
    $high_number++; 
    $high_number = sprintf("%6d",$high_number);
    $high_number =~ tr/ /0/;           
    open(MSGFILE, ">$chat_room_dir/$high_number.msg");
    print MSGFILE "$user_name\n";
    print MSGFILE "$user_email\n";
    print MSGFILE "$user_http\n";
    print MSGFILE "$chat_to_user\n";
    print MSGFILE "$current_date_time\n";
    print MSGFILE "$chat_message\n";
    close(MSGFILE);

# we need to get rid of old messages
    &PruneOldMessages($chat_room_dir);

#
# We need to be able to GetSessionInfo
# again since the state of the messages that
# are available have changed since the 
# user last read the information.
#
# How, last_read has not changed, so we
# keep track of it with a temporary 
# variable (old_last_read) and reset it
# afterwards.
#
    $old_last_read = $user_last_read;
    ($user_name, $user_email, $user_http,
     $refresh_rate, $how_many_old, 
     $user_last_read, $high_message) = 
	 &GetSessionInfo($session, $fsubmit, $frames);
    $user_last_read = $old_last_read;

}

# Clear the chat buffer
$chat_buffer = "";
#
# $chat_buffer will have the occupants list
# in it if the button selected was the
# view occupants button
#
if ($occupants ne "") {
    opendir(CHATDIR, "$chat_room_dir");
    @files = grep(/who$/,readdir(CHATDIR));
    closedir(CHATDIR);
    $chat_buffer .= "<H2>Occupants List</H2><P>";
    if (@files > 0) {
	foreach $whofile (@files) {
	    open (WHOFILE,"<$chat_room_dir/$whofile");
	    $wholine = <WHOFILE>;
	    @whofields = split(/\|/,$wholine);
	    close(WHOFILE);
	    if ($whofields[1] ne "") {
		$chat_buffer .= qq!<A HREF=MAILTO:! .  
		    qq!$whofields[1]>!;
	    }
	    $chat_buffer .= $whofields[0];
	    if ($whofields[1] ne "") {
		$chat_buffer .= "</A>";
	    }
	    $chat_buffer .= " last viewed msgs at ";
	    $chat_buffer .= $whofields[3];
	    if ($whofields[2] ne "") {
		$chat_buffer .= 
		    qq! (<A HREF="$whofields[2]">! . 
			     qq!Home Page</A>)!;
	    }
		$chat_buffer .= "<P>";
	}
    } else {
	$chat_buffer .= "No Occupants Found";
    } # End of no occupants
    $chat_buffer .= 
	"<P><H2>End of Occupants List</H2><P>";

} # End of occupants processing

#
# We do not want to read in a chat_buffer
# if we are only printing the submit
# chat message frame
# 

if ($fmsgs eq "on" || 
    ($frames ne  "on" && 
     $fsubmit ne "on")) {

#
# Now that we have session information
# we need to gather the message info
# from the chat_room_directory.
#


# We want to make sure the "WHO" file 
# for a user is written in order
# to keep track of who is in the room.
#
$whofile = "$chat_room_dir/$session.who";
unlink($whofile);
open(WHOFILE, ">$whofile");
print WHOFILE 
    "$user_name|$user_email|$user_http|$current_date_time\n";
close (WHOFILE);
&RemoveOldWhoFiles;

#
# We add one to the user last read
# because we do not want to read the
# last read message.
# We substract how many old messages
# we are allowed to read.

$msg_to_read = $user_last_read + 1;
$msg_to_read -= $how_many_old;
if ($msg_to_read < 1) {
    $msg_to_read = 1;
}
if ($high_message >= $msg_to_read) {
    for ($x = $high_message; $x >= $msg_to_read; $x--) {
        $x = sprintf("%6d",$x);
        $x =~ tr/ /0/;   
        if (-e "$chat_room_dir/$x.msg") {
            open(MSG,"$chat_room_dir/$x.msg") ||
              &CgiDie("Could not open $x.msg");
        $msg_from_user = <MSG>;
	$msg_from_user = &HtmlFilter($msg_from_user);
        $msg_email = <MSG>;
	$msg_email = &HtmlFilter($msg_email);
        $msg_http = <MSG>;
        $msg_http = &HtmlFilter($msg_http);
        $msg_to_user = <MSG>;
        $msg_to_user = &HtmlFilter($msg_to_user);
        $msg_date_time = <MSG>;
        chop($msg_from_user);    
        chop($msg_email);
        chop($msg_http);
        chop($msg_to_user);    
        chop($msg_date_time);
        if ($msg_to_user eq "ALL" ||
            $msg_to_user =~ /^$user_name$/i ||
            $msg_from_user =~ /^$user_name$/i) {
        $chat_buffer .= "<TABLE>\n";
        $chat_buffer .= "<TR><TD>";
        $chat_buffer .= "From:</TD><TD>";
        if ($msg_email ne "") {
          $chat_buffer .= qq!<A HREF=MAILTO:! .  
                          qq!$msg_email>!;
        }
        $chat_buffer .= $msg_from_user;
        if ($msg_email ne "") {
          $chat_buffer .= "</A>";
        }

        if ($msg_http ne "") {
          $chat_buffer .= qq! (<A HREF="$msg_http">! . 
                          qq!Home Page</A>)!;
        }
        $chat_buffer .= "</TD>\n";
        $chat_buffer .= "\n<TD>";
        if ($x > $user_last_read) {
            $chat_buffer .= " (New Msg) "
        }
        $chat_buffer .= " at $msg_date_time</TD>";
        $chat_buffer .= "</TR>\n";
        if ($msg_to_user =~ /^$user_name$/i ||
            ($msg_from_user =~ /^$user_name$/i &&
             $msg_to_user ne "ALL")) {
        $chat_buffer .= "<TR><TD>";
        $chat_buffer .= "Private Msg To:" .
                        "</TD><TD>$msg_to_user</TD>" . 
                        "</TR>\n";
        }
        $chat_buffer .= "</TABLE>\n";
        $chat_buffer .= "<BLOCKQUOTE>\n";
        while(<MSG>) {
            $_ = &HtmlFilter($_);
            $chat_buffer .= "$_<BR>";
            }
            close(MSG);
            $chat_buffer .= "\n";
        }
        $chat_buffer .= "</BLOCKQUOTE>\n";
        } # End of IF msg is to all or just us
    }
}

} 
# End of IF we are not in the submit msg frame
#    or simply printing the main frameset
#    document

#
# If the user has logged off, we remove their
# who file so they do not show up in the 
# occupants list
#

if ($logoff ne "") {
    $whofile = "$chat_room_dir/$session.who";
    unlink($whofile);
}

# Print the chat screen.
&PrintChatScreen($chat_buffer, $refresh_rate, 
                 $session, $chat_room, $setup,
                 $frames, $fmsgs, $fsubmit);

#######################
#                     #
# END OF MAIN ROUTINE #
#                     #
#######################

############################################################
#
# subroutine: GetSessionInfo 
#   Usage:
#   ($session, $username, @extra_fields,
#    = &GetSessionInfo($session, "script name",
#    *in);
#
#   Parameters:
#     $session = session id.  Null if it is not defined yet
#     $fsubmit = we are printing the submit portion of
#        a chat frame so do not do new message processing
#     $frames = we are printing the main frameset HTML 
#        document so do not do new message processing
#
#   Output:
#     $session = session id
#     An array of fields consisting of:
#       $username, $email, $home page,
#       $refresh_rate, $old_message_count
#     $high_message = high message number
#
############################################################

sub GetSessionInfo {
local($session, $fsubmit,$frames) = @_;
local($session_file);
local($temp,@fields, @f);
local($high_number, $high_message);
$session_file = "$session.dat";

#
# Open the session file
#
open (SESSIONFILE, "$chat_session_dir/$session_file");
while (<SESSIONFILE>) {
$temp = $_;
} 
chop($temp);


@fields = split(/\|/, $temp);

close (SESSIONFILE);                  

#
# Get the highest message number 
#
$high_message = &GetHighMessageNumber;

# Keep track of old fields
@f = @fields;
# Update last read field
@fields[@fields - 1] = $high_message;
#
# We need to write the new last read variable out
# to the session file
#

if ($fsubmit ne "on" &&
    $frames ne "on") {
    open (SESSIONFILE, ">$chat_session_dir/$session_file");
    print SESSIONFILE join ("\|", @fields);
    print SESSIONFILE "\n";
    close (SESSIONFILE);
}
(@f, $high_message);

} # End of GetSessionInfo


############################################################
#
# subroutine: GetHighMessageNumber
#   Usage:
#     $high_message = &GetHighMessageNumber;
#
#  This routine returns the highest message number
#  for the chat room.
#
#   Output:
#     $high_message_number
#
############################################################

sub GetHighMessageNumber {
local($last_file, @files);

# Read in all the files and sort them
opendir(CHATDIR, "$chat_room_dir");
@files = sort(grep(/msg/, readdir(CHATDIR)));
closedir(CHATDIR);

# Return highest message or 0 if no files
if (@files > 0) {
    $last_file = $files[@files - 1];
} else {
    $last_file = "0000000";
}

# Return the first 6 characters of the filename
substr($last_file,0,6);

} # End of GetHighMessageNumber

############################################################
#
# subroutine: MakeSessionFile
#   Usage:
#   $session = &MakeSessionFile(@fields);
#
#  This routine makes a session file on the basis of the
#  fields that make up a user such as first name and last
#  name.
#
#  Parameters:
#   @fields = a list of fields that make up the user
#
#   Output:
#     $session = session id
#
############################################################
                                       
sub MakeSessionFile {
local(@fields) = @_;
local($session, $session_file);

#
# RemoveOldSessions
#
&RemoveOldSessions;

# Seed the random generator
srand($$|time);
$session = int(rand(60000));
# pack the time, process id, and random $session into a
# hex number which will make up the session id.
$session = unpack("H*", pack("Nnn", time, $$, $session));

$session_file = "$session.dat";

#
# Create the actual session file
# 
open (SESSIONFILE, ">$chat_session_dir/$session_file");      
print SESSIONFILE join ("\|", @fields);
print SESSIONFILE "\n";

close (SESSIONFILE);

$session;                                

} # End of MakeSessionFile


############################################################
#
# subroutine: RemoveOldSessions
#   Usage:
#     &RemoveOldSessions;
#
# This routine removes old session files based on the
# age determined by the defined variables 
# ($chat_session_length).                     
#
#  Parameters:
#    None.
#
#  Output:
#     None.
############################################################

sub RemoveOldSessions
{
local(@files, $file);
# Open up the session directory.
opendir(SESSIONDIR, "$chat_session_dir");
# read all entries except "." and ".."
@files = grep(!/^\.\.?$/,readdir(SESSIONDIR));
closedir(SESSIONDIR);                 
                         
# Go through each file
foreach $file (@files)
        {
# If it is older than session_length, delete it
        if (-M "$chat_session_dir/$file" > $chat_session_length)
                {
                unlink("$chat_session_dir/$file");
                }

        }
} # End of RemoveOldSessions
                                      
############################################################
#
# subroutine: RemoveOldWhoFiles
#   Usage:
#     &RemoveOldWhoFiles;
#
# This routine removes old who files based on the age
# determined by the defined variables
# ($chat_who_length)
#
#  Parameters:
#    None.
#
#  Output:
#     None.
############################################################

sub RemoveOldWhoFiles
{
local(@files, $file);
# Open up the chat_dir directory.
opendir(CHATDIR, "$chat_room_dir");
# read only "who" files
@files = grep(/who$/,readdir(CHATDIR));
closedir(CHATDIR);                 
                         
# Go through each file
foreach $file (@files)
        {
# If it is older than chat_who_length, delete it
        if (-M "$chat_room_dir/$file" > $chat_who_length)
                {
                unlink("$chat_room_dir/$file");
                }

        }
} # End of RemoveOldWhoFiles

############################################################
#
# subroutine: GetChatRoomInfo
#  Usage:
#    &GetChatRoomInfo($chat_room);
#
#   Parameters:
#     $chat_room = abbreviated chat room identifier
#
#   Output:
#     Returns an array of the chat room name and
#     chat room directory.
#
############################################################

sub GetChatRoomInfo {
   local($chat_room) = @_;           
   local($chat_room_name, $chat_room_dir, $x);
   local($chat_room_number, $error);

$chat_room_number = -1;

for ($x = 1; $x <= @chat_room_variable; $x++)
        {
        if ($chat_room_variable[$x - 1] eq $chat_room)
                {
                $chat_room_number = $x - 1;
                last;
                }
        } # End of FOR chat_room_variables

if ($chat_room_number > -1) {
    $chat_room_name = $chat_rooms[$chat_room_number];
    $chat_room_dir = $chat_room_directories[$chat_room_number];    
} else {
    $chat_room_name="";
    $chat_room_dir = "";
    $chat_room = "None Given" if ($chat_room eq "");
    $error =
        "<strong>Chat Room: '$chat_room' Not Found</strong>";
    &PrintChatError($error);
    die;
}
($chat_room_name, $chat_room_dir);

} # end of GetChatRoomInfo
                                   
############################################################
#
# subroutine: PruneOldMessages
#  Usage:
#    &PruneOldMessages($chat_room_dir);
#
#   Parameters:
#     $chat_room_dir = directory of chat room
#
#   Output:
#     Unlinks (deletes) messages
#     in the chat room directory based on age or sequence
#     number as defined in the setup file.
#
############################################################
                                                                        
sub PruneOldMessages {
    local($chat_room_dir) = @_;
    local($x, @files);
    local($prunefile);
#
# We prune on the basis of
#
# AGE IN DAYS:
# $prune_how_many_days
#
# AGE BY SEQUENCE NUMBER
# $prune_how_many_sequences
#
    opendir(CHATDIR, "$chat_room_dir");
    @files = sort(grep(/msg/, readdir(CHATDIR)));
    closedir(CHATDIR);

    for ($x = @files; $x >= 1; $x--) {
        $prunefile = "$chat_room_dir/$files[$x - 1]";
        # First we check the age in days
        if ((-M "$prunefile" > $prune_how_many_days) &&
            ($prune_how_many_days > 0)) {
            unlink("$prunefile");
            &RemoveElement(*files, $x - 1);
            next;
        }


        #
        # Check the sequence and delete if it is too old
        #

        if (($x <= (@files - $prune_how_many_sequences))
            && ($prune_how_many_sequences != 0)) {
            unlink("$prunefile");
            &RemoveElement(*files, $x - 1);
            next;
        }
    } # End of for all files

} # End of PruneOldMessages

############################################################
#
# subroutine: RemoveElement
#  Usage:
#    &RemoveElement;
#
#   Parameters:
#     *file_list = array of message numbers
#     $number = pointer into the array of the
#               element to remove
#
#   Output:
#     *file_list without the $number element.
#
############################################################

sub RemoveElement
{
local(*file_list, $number) = @_;

if ($number > @file_list)
        {
        die "Number was higher than " .
            "number of elements in file list";
        }
splice(@file_list,$number,1);

@file_list;

} # End of RemoveElement

############################################################
#
# subroutine: HtmlFilter
#  Usage:
#    $filtertext = &HtmlFilter($filterthis);
#
#   Parameters:
#    $filter = text to filter HTML in
#
#   Output:
#     Filtered string
#
############################################################

sub HtmlFilter
{
local($filter) = @_;
# 
# The following filters the HTML images
# out, if they are disallowed.  The code
# after this, filters out all HTML if it
# is disallowed.
#
if ($no_html_images eq "on")
{
    $filter =~ s/<(IMG\s*SRC.*)>/<$1>/ig;
} # End of parsing out no images

if ($no_html eq "on")
{
    $filter =~ s/<([^>]+)>/\<$1>/ig;
} # End of No html                                         

$filter;

} # End of HTML Filter