#!/usr/bin/perl -- ######################################################################### ##### # ##### SFEChat v1.1 # ##### Copyright 1999-2005, Kristina L. Pfaff-Harris, # ##### http://tesol.net/scriptmail.html # ##### # ##### A real-time chat program for the web. # ##### # ######################################################################### ##### Licensing: # ##### # ##### This program may be used free of charge under the following # ##### conditions: # ##### # ##### 1. All instructions and Copyright lines must remain unchanged. # ##### 2. All pages generated by the program must contain one of the # ##### following pieces of HTML code: # ##### # ##### ##### # ##### Powered by SFEChat # ##### OR: # ##### # ##### # ##### # ##### 3. You may not sell or redistribute this program. This isn't # ##### really arbitrary: I just like to make sure that when people # ##### get the script, they get the latest version. You may charge # ##### a reasonable fee for installing it for a client as long as # ##### you make it clear that you are not the author, and you are # ##### not selling the program to them: only charging for installing # ##### it. # ##### 4. You agree that this program is offered without warranty of # ##### any kind, including warranty of fitness for a particular # ##### purpose. You further agree that the author and all sites # ##### associated in any way with this program are not liable for # ##### any damage or loss incurred as a result of using this program.# ######################################################################### ##### # ##### IMPORTANT INSTRUCTIONS: # ##### # ##### In this program, I have put **CHANGE** in all the places where # ##### you will need to modify the program to run on your server, so # ##### that you can easily find all the places where changes are # ##### necessary. This program must be chmod 755 or 775 in order to # ##### work, and any html files must be chmod 644. Note: on some, # ##### systems, you'll have to either make the files "chatters.txt" # ##### and sfechatwindow.html world writeable (chmod 766) or you'll # ##### have to make sfechat.cgi run as you (setuid - chmod 4755). # ##### This latter isn't always as easy as just chmodding the program. # ##### Ask your local technical support person if your web server # ##### supports setuid Perl scripts. # ##### # ##### Please read the README.sfechat file for more instructions # ##### on how to set this up. Please read all the instructions below # ##### carefully as well. # ######################################################################### ###### Begin Configuration Section ###### # First of all, let's set up to print out some debugging information. # This can help you figure out what might be going wrong with the # program if you're not getting it to work quite right. When you # have the program set up and functioning, **CHANGE** $debugging = 1; # to $debugging = 0; $debugging = 1; ######################################################################### # # # FILE PATH CONFIGURATION # # # # The next several settings are for "system paths" to various files # # that need to be written to and read by the script. It is important # # to note that these paths are NOT the same as URLs (web addresses) # # and must NOT begin with "http://". "System paths" are how your web # # server sees things, and this is often very different from how you and # # your browser see them. If these files are in the same folder as # # sfechat.cgi, then the default values ("./file.txt") may work. It's # # worth a try, anyway. If not, the paths should probably look something # # like "/home/users/yourlogin/cgi-bin/sfechatwindow.html", or, under # # Windows, "c:\\home\\users\\yourlogin\\sfechatwindow.html". Please note# # the use of the double backslashes. It's important that you enter # # Windows paths in this manner. # # # # **CHANGE** these if you need to do so. # # # ######################################################################### # $path_to_language file is where you have put the language file you'd # like to use. The script will not run without a language file, so make # sure you have uploaded it and set this variable correctly!!! This must # be the full system path to the file. For example, something like # g:/users/yourlogin/lang-de on Windows or /home/users/yourlogin/lang-de # on Unix-type systems. NOTE: If the lang-en.txt file is in the same # folder as this script, the below may work. This file must be chmod # 644. $path_to_language_file = "./lang-en.txt"; # $path_to_active_users is the system path to the chatters.txt file # which contains a list of people who are currently logged into the # chatroom. This file must be writeable by the web server, which # usually means chmod 766. If this file is in the same folder as this # script, the below may work. $path_to_active_users = "./chatters.txt"; # $path_to_registered_users is the full system path to your registered users # file. Chmod 766, or world-writeable. If this file is in the same folder # as this script, the below may work. $path_to_registered_users = "./registered_users.txt"; # $path_to_icons_file is the full system path of a text file that you # wish to keep your icons in. Only used if you set $use_icons = 1; later # on in the script. If this file is in the same folder as this script, # the below may work. # This file should be chmod 766 or otherwise set so the system can write # to it. **CHANGE** this to the full system path to your sfeicons.txt file. $path_to_icons_file = "./sfeicons.txt"; # $path_to_badwords_file is the full system path to your badwords.txt file # that contains your list of bad words you want to censor out of your # chatroom. This file should contain a list of bad words or phrases, # one per line, and should be a plain text file. This is only used if # you set $censor_chat = 1; later on in the script. If this file is # in the same folder as this script, the below may work. This file should # be chmod 766 or world-writeable. $path_to_badwords_file = "./badwords.txt"; # $path_to_banned_ip_file is the full system path to IP addresses or # hosts that you do not want to allow into your chatroom. This file # should contain hosts or addresses, one per line. If you wish to ban # an entire block of IP's (say 10.0.0.1 - 10.0.0.254) you can just put # the first part of the IP block in there (10.0.0) and the chatroom # will block everyone with an address in that range. You can also add # to this file with /ban . If this file is in the same folder as this # script, the below may work. This file should be chmod 766 or world # writeable. $path_to_banned_ip_file = "./banned-ip.txt"; # $path_to_chat_file is the full system path to the file where you # want the program to keep track of the conversation. This is generally # sfechatwindow.html. If you've followed the suggested installation # from README.sfechat, then what I have below may work. If not, then # put in the real path to sfechatwindow.html on your server. This file # should be chmod 766 or world-writeable. $path_to_chat_file = "../sfechat/sfechatwindow.html"; # $path_to_topic_file is the full system path to the file where you want # to store the chat topic of the moment (usually topic_file.txt). # If this file is in the same folder as this script, the below may work. # This file should be chmod 766 or world-writeable. $path_to_topic_file = "./topic_file.txt"; # $log_directory needs to be the full system path to a directory on # your server where you want the log/transcript files to be stored. # You should probaby make a separate directory for these logs, something like # "chatlogs" and chmod it 777 or otherwise so that the server can write to it. # DO NOT put a / or a \ on the end of this. **CHANGE** this to the # directory where you want your logs to be stored on your system. # This is only used if you set $log_all_chats = 1; later on in the script. $log_directory = "./logs"; ######################################################################### # # # WEB ADDRESS (URL) CONFIGURATION # # # # In this next section, we're going to put in the full web addresses # # of some things so that the program can link them up properly. Unlike # # the last section, these ARE URL's and MUST begin with "http://". # # # ######################################################################### # $url_of_sfechat_cgi is the full URL path to the sfechat.cgi # program on your server. $url_of_sfechat_cgi = "http://your_domain/cgi-bin/sfechat.cgi"; # $url_of_chat_file is the full URL of the file where you # want the program to keep track of the conversation. (What actually # gets shown in the chat room.) This should also probably # **CHANGE** this to the url of this file on your server. $url_of_chat_file = "http://your_domain/sfechat/sfechatwindow.html"; # $url_of_sound_file is the full web address to the sound file you want # to play when someone enters the chatroom. This MUST begin with # "http://". For example: http://www.your.site/ding.wav # If you wish to play sounds, you must upload a sound file to your # website. The sound file does not come with SFEChat for # copyright reasons: you'll have to make or upload your own, and then # put its address here. This is only used if $play_sound_on_entering = 1; # is set later on in the script. $url_of_sound_file = "http://your_domain/sfechat/ding.wav"; # $url_of_sfechatbanner is the address of sfechatbanner.html . This # is just a sort of plain text file that shows up at the top of the # chat window. $url_of_sfechatbanner = "http://your_domain/sfechat/sfechatbanner.html"; ######################################################################### # # # ADMIN PASSWORD CONFIGURATION # # # # In order to be able to use the admin functions such as /kick, /ban, # # and /topic (unless you've enabled $users_can_change_topic), you'll # # need to be logged in as the admin user. Below, select a username # # that you want to be known as the admin user. It doesn't have to be # # "admin." It can be "JoeSmith" or "B3R53RKR" or whatever you like. # # NOTE: if you have set $disable_special_characters_in_login = 1; # # then you may ONLY use letters or numbers in $admin_login. # # # ######################################################################### $admin_login = "admin"; # You'll also need to choose a password for your admin user. You can # use pretty much anything, but you MUST put a backslash in front of # any @, $, or " characters: $admin_password = "hungry"; ######################################################################### # # # GENERAL OPERATION OPTIONS # # # # The next several things have to do with general options for the # # program. You can probably skip these unless you want to change # # something from the default. However, you can **CHANGE** these # # settings as appropriate. # # # ######################################################################### # First of all, if you would like chatters to be able to enter HTML code # which will be rendered on the screen, **CHANGE** $disable_html = 1; # to $disable_html = 0; Note that if you set $disable_html to 0, users # will be able to put inline images, sounds, links, etc, right into the # chat window which sometimes makes things confusing and hard to read. # PLUS, it can be used by malicious people to trick others into clicking # on links to viruses, etc. It's generally best to leave this set to 1. $disable_html = 1; # $number_of_chats_to_display is just how many lines you want to display # of the ongoing chat before the program drops one off the end. For # example, if you make this "5", then 5 people will get to say something, # then when the 6th person says something, the 1st person's statement # will drop off the list. **CHANGE** this if you like to something # longer or shorter. 15 - 20 seems reasonable. $number_of_chats_to_display = "15"; # $new_chat_lines_on_top lets you decide whether you want new additions # to the chat to go on the bottom or the top of the existing chat window. # If you set $new_chat_lines_on_top to 0, then the chatroom will go from # top to bottom with new posts last. WARNING: If you do this, then please # note that people with smaller screens may have to scroll down every time # the chat room refreshes. The chatroom will try to scroll down automatically, # but depending on the web browser's capabilities, this may not work for # everyone. This could be *extremely* annoying to people, and since # you have no way of knowing what kind of screen everyone will have, I really # recommend that you not do this, and leave it at $new_chat_lines_on_top = 1; # which is the default. However, if you really want the chat to read from # top to bottom instead of bottom to top, **CHANGE** this so that it says # $new_chat_lines_on_top = 0; $new_chat_lines_on_top = 0; # $clear_chatroom_when_empty is whether or not you want to clear out # all the old chats when the last person leaves the chatroom. If you # do not want it to clear out the chatroom, **CHANGE** # $clear_chatroom_when_empty = 1; to # $clear_chatroom_when_empty = 0; # By default, it will not clear out the chatroom. $clear_chatroom_when_empty = 1; # $play_sound_when_entering is whether or not you want SFEChat to # play a sound when someone enters the chatroom. Note: With some versions # of Netscape, the sound will play every time the chatroom refreshes. If # this happens, having the user set their cache preferences to "Verify # documents every time" may help. In addition, the sound will continue # to play for everyone every time the chat window refreshes UNTIL someone # says something. Thus, when someone logs in, it's good to say "Hi" right # away to stop the sound. :-) If you set this to "yes", you MUST # tell SFEChat the web address of the sound file you want to play # in $url_of_sound_file up in the URL configuration options above. # If you would like to enable sound playing, # **CHANGE** # $play_sound_when_entering = 0; to # $play_sound_when_entering = 1; $play_sound_when_entering = 1; # $server_time_offset is how many hours later or earlier you want the # chatroom time to show up. Ordinarily, the chatroom gets its time # from the timezone of the web server where it is being run. If you are # in a different timezone, then you will need to figure out how many # hours difference there are between you and your web server, and enter # that number here. For example, if the chatroom shows 11:33 and your # time is 13:33, you would set $server_time_offset = 2; If the chatroom # shows 17:21 and your time is 12:21, you would set # $server_time_offset = -5; **CHANGE** this only if you want to change # the time displayed in the chatroom. $server_time_offset = 0; # $time_format allows you to determine how you want the date/time displayed # in the chatroom. It goes like this: # MM will change to the 2-digit month. # DD will change to the 2-digit day of the month. # YY will change to the 2-digit year. # YYYY will change to the 4-digit year. # HH will change to the hour # MN will change to the minute # SS will change to the second. # So, if you set $time_format to "MM/DD/YY HH:MN:SS" it will display something # like 10/03/01 04:12:01. # If you set $time_format to "YYYY.MM.DD HH:MM:SS" it will display something # like 2001.10.31 14:23:01. $time_format = "MM/DD/YY HH:MN:SS"; # $log_all_chats is whether or not you want to keep a log of the chats # over and above the "$number_of_chats_to_display" above. If you don't # care about keeping a record of all your chat sessions, set # $log_all_chats = 0; Otherwise, if you'd like to be able to go # back later for transcripts, set $log_all_chats = 1; and the program # will attempt to create log files for chat transcripts. IMPORTANT!!! # Be sure if you set this to "1," that you also choose a logging method # in "$type_of_log" below, the directory where you want your logs to be # kept in $log_directory, and the maximum amount of disk space you want to # allocate to your logs in $max_log_space. **CHANGE** this if you want to # keep transcripts. $log_all_chats = 1; # $type_of_log has four options, described below. You should **CHANGE** this # to the type of log you want: # daily: Creates a new log every day containing chat records from that day. # monthly: Creates a new log every month. # big: Creates one log that gets added to forever. $type_of_log = "big"; # $max_log_space is the amount of diskspace in bytes that you want to # devote to logs. Note that one chat page with "$number_of_chats_to_display" # set to "20" is about 3500 bytes, or 3.5 kilobytes. You will need to take # into account how much space your chat logs can take up by making sure that # you limit it to less than the amount of disk space available to you. NOTE # that this program will take your word for it, so if you enter something like # 20000000 (20 megabytes) and you only have 5 megabytes available, the # program will happily keep logging until it uses up all your disk space # at which point this program, and probably many others you have, may not # work at all, you may not be able to log into your account at all, and you # will be embarassed before your local technical support people. Currently # the default is 1000000 or one megabyte. **CHANGE** this to the amount # of diskspace you want logs to be limited to. $max_log_space = "1000000"; # $refresh_time is how often you would like the chat window to refresh # itself. This time is in seconds. Note: the lower this number is, # the faster the chat window will refresh. For some people, this gives # a very choppy look to the chat screen and can be hard on the eyes. # If you make this number too high, however, then the chatroom can seem # "dead". **CHANGE** this to the number of seconds you'd like the room # to wait before refreshing itself. $refresh_time = 5; # $idle_timeout is how long (in minutes) you would like to wait before # automatically logging out an idle user. Since the program can't catch # people logging out if, e.g. their computer crashes, this can keep your # "Who's On" log from filling up with people who left the chat room days # before. $idle_timeout = "5"; # $use_icons determines whether things like :-) or :( should be turned # into images. Admin may add icons to the system by using: # /addicon :-) http://www.your_domain/images/happy.gif # or remove icons by using: # /removeicon :-) # You MUST have images already uploaded, and you must know where they # are. If you set $use_icons = 1; the system will look for images to # replace things like :-) or :-( . If it can't find an image for them, it # will just leave them alone. **CHANGE** this to $use_icons = 0; if you # do not want to use icons. $use_icons = 1; # $censor_chat will try to censor some "bad words" out of the chat. # If you want to try to censor the chat, then add words or phrases # that you want to have censored, one per line, to badwords.txt, and # set: # $censor_chat = 1; # Otherwise, set $censor_chat = 0; # PLEASE NOTE: This program is not very intelligent as far as this # sort of "censorship" goes. With a bad word, say, "blah," a user # can easily get around the censorship by typing "b l a h" or similar. # This only cuts down on some foul language, and will not prevent # people who are really determined to cuss from cussing in your chat # room. $censor_chat = 1; # $censored_msg is what you want to show up instead of any bad words # you might be taking out. For example: "Blankety Blank" or "!@#%*.$". # NOTE: This must be in SINGLE quotes, not double quotes as below. $censored_msg = '!@#%*.$'; # $ban_preferences determines whether you want to ban by login or by # IP or both. # $ban_preferences = "ip"; will ban just the user's IP. # $ban_preferences = "login"; will ban just the user's login name but not his IP. # $ban_preferences = "both"; will ban both the user's login name and his IP. # "login" is probably safest, since it will block the user and not other # users who might be behind the same proxy server. $ban_preferences = "login"; # $banned_message is some text that you want to display to a user # whose IP has been banned. **CHANGE** Only between the # and lines. # Be sure to put a backslash (\) in front of any " or @ signs (like # this \" \@) or it will break the script. $banned_message = qq[ Sorry, but you may not participate in this chatroom. ]; # $disable_special_characters_in_login is an attempt to prevent people # from logging in with a username that contains punctuation or other # non-word characters. If you change this, the program will still # attempt to remove characters such as ", ', [, ], and |, but will # leave the rest of the login alone. NOTE: If you set this to 0, # then non-US-ASCII characters will be removed, so this probably wouldn't # be a good idea to do if you are using this in a non-U.S. website. $disable_special_characters_in_login = 1; # $show_settings_to_user is whether or not you want your users to # be able to see various chatroom settings, such as whether or not # the room is censored, how long the refresh and idle timeouts are, # etc. If you want them to be able to view settings, leave this as it # is. Otherwise, **CHANGE** this to: # $show_settings_to_user = 0; $show_settings_to_user = 1; # $show_user_address tells us whether or not to show where the user # is coming from when they log in. E.g. "Kristina logged in from # somehost.somedomain.com" or "Jojo logged in from 192.168.4.3". # If you want to show this information, set $show_user_address = 1; # If you want to show only "Kristina Entered the Chatroom" set # $show_user_address = 0; $show_user_address = 1; # $users_can_change_topic is whether or not you want ordinary users # (other than admin) to be able to change the topic that is shown # across the top of the chat room. To allow anyone to change the topic, # set $users_can_change_topic = 1; If you ONLY want admin to be able # to change the topic, set $users_can_change_topic = 0; $users_can_change_topic = 1; ######################################################################### # # # BASIC DISPLAY/LOOK OPTIONS # # # # The last set of options are some things that help set the colors and # # fonts and size of the chat window. You may wish to leave these alone # # and it's not necessary to change them, but if you're handy with CSS # # and HTML, then you can feel free to change these. # # # ######################################################################### # $side_color is the color of the frame on the right hand side and bottom # of the chat window. (Currently, a sort of light blueish lavendar.) # You can set this to another appropriate HTML color if you wish. $side_color="eeeeff"; # $chat_window_width and $chat_window_height are the size in pixels that # you want your chat window to be. You may **CHANGE** this to make it larger # or smaller, but NOTE that if you do, scrollbars may appear where you # don't expect them. The size below seems to work with a minimum of # scrolling, but feel free to play around. $chat_window_width = 580; $chat_window_height = 400; # $stylesheet_text is for the fonts and so forth you want to use for the # chat. You can change in between "Begin Style Section" and "End Style Section" # if you choose. $stylesheet_text = qq[ ]; ######################################################################### # # # That's it! You're all done! See, now, that wasn't that bad, was it? # # You should not need to change anything beyond this point, but # # you can look through it if you like that sort of thing. If you # # change anything after this point, though, then I can't be held # # responsible. If the script had a warranty, which it does not, you'd # # void the warranty by modifying anything below this point. :-) # # # ######################################################################### %data = &parse_data(); # Operating system - mostly for flock and binmode if($^O =~ /win/i || $^O =~ /mac/i){ $opsys = "win"; } else { $opsys = "unix"; } # Don't change this next line with the "(open(T, "<$path_to_topic_file");": open(T, "<$path_to_topic_file"); $chat_topic = ; close(T); # $chat_window_header is probably something you don't want to mess with. # If you do mess with it, and you break something, I may not help you, but # here are a few tips. First, if you do mess with this, don't insert the # initial tags , since this chat program puts them in later. # Also, don't mess with the JavaScript below if you have set # $new_chat_lines_on_top to 0!!!! # If you remove or change the "Topic:" line, it will break the topic function # of the script. # If you remove or change the "scrollChat();" line, then you will break the # part of the script that automatically scrolls down when refreshing and people # will have to manually scroll to see the chat. Annoying! # Basically, if you mess with this, the entire chat script could just # go completely wooglie on you, and nobody wants that. $chat_window_header = qq[ Chat window $stylesheet_text
Topic: $chat_topic

]; #<-- DO NOT REMOVE THIS! # $chat_window_footer is the HTML footer that you want for the page that # contains the chat window (the window where the "conversation is"). You # can use any HTML code you like. HOWEVER, you must abide by the # backslashing rules as with the chat_window_header above. I wouldn't # really advise changing this, but you can if you really want to. Just # don't blame me if it breaks stuff. :-) $chat_window_footer = " "; #<-- This quote and semicolon are necessary. Don't backslash them! # $form_window_header is the HTML header for the frame where the form # is that you type in to "talk". Again, you may **CHANGE** this but # be careful of special characters. $form_window_header = qq[ $stylesheet_text SFEChat v1.1 ]; #<-- DO NOT REMOVE OR CHANGE THIS # $form_window_footer is the HTML footer for the frame where the form # is that you type in to "talk". Again, you may change this but # be careful of special characters. $form_window_footer = "
"; #<-- This quote and semicolon are necessary. Don't backslash them! $idle_time_min = $idle_timeout; $idle_timeout = $idle_timeout * 60; $cgi_url = $url_of_sfechat_cgi; $header = $chat_window_header; $footer = $chat_window_footer; $chat_in_new_window = "yes"; if($chat_in_new_window eq "yes"){ $js_functions = " "; $login_cgi_url = "onSubmit=\"return SFEChat_newWin();\""; $target = "SFEChatWin"; } else{ $target = "_top"; } # Turn debugging off if we're printing the frameset for the chat. Otherwise # we have problems showing it. if($data{'FA'} eq "Login"){$debugging = 0;} ($i_am_admin,$i_am_really_admin) = &check_admin_status(); &process_lang; &check_config(); $msg_debug1 = &trans_subst($msg_debug1,"%OPERATINGSYSTEM%",$^O); &debug("$msg_debug1") if $^O ne ""; $msg_debug2 = &trans_subst($msg_debug2,"%SERVERSOFTWARE%",$ENV{'SERVER_SOFTWARE'}); &debug("$msg_debug2") if $ENV{'SERVER_SOFTWARE'} ne ""; unless(-f $path_to_chat_file){ $msg_debug3 = &trans_subst($msg_debug3,"%PATH_TO_CHAT_FILE%",$path_to_chat_file); &debug("$msg_debug3"); } unless(-f $path_to_active_users){ $msg_debug4 = &trans_subst($msg_debug4,"%PATH_TO_ACTIVE_USERS%",$path_to_active_users); &debug("$msg_debug4"); } if($log_all_chats == 1){ unless(-d $log_directory){ $msg_debug5 = &trans_subst($msg_debug5,"%LOG_DIRECTORY%",$log_directory); &debug("$msg_debug5"); $log_all_chats = 0; } } # If you remove this link, without replacing it with a similar # HTML comment (as above in the Licensing section) you are in violation # of the license for this program. There are no exceptions to this. # Honestly, since you didn't have to pay for this, is the link # really too much to ask? If so, please use another chat program. there # are a gazillion of them out there. Thanks! :) $form_window_footer = " Powered by SFEChat.$form_window_footer"; $msg_debug6 = &trans_subst($msg_debug6, "%PATH_TO_ACTIVE_USERS", $path_to_active_users); $msg_debug7 = &trans_subst($msg_debug7, "%PATH_TO_ACTIVE_USERS", $path_to_active_users); $msg_debug8 = &trans_subst($msg_debug8, "%PATH_TO_CHAT_FILE", $path_to_chat_file); $msg_debug9 = &trans_subst($msg_debug9, "%PATH_TO_CHAT_FILE", $path_to_chat_file); $login = $data{'Login'}; $password = $data{'Password'}; if($disable_special_characters_in_login == 1){ # Take out all non-word characters $ok_login_chars = 'A-Za-z0-9-_.'; $login =~ s/[^$ok_login_chars]//g; } else { # Take out just characters that will mess up the program. # Thanks to James Brown for the bug report and regexp. :-) $login =~ s/[()|\[\]']//g; $login =~ s/\"/"/g; $login =~ s/>/>/g; $login =~ s/"; } if($ENV{'REMOTE_HOST'} ne ""){ $remotehost = $ENV{'REMOTE_HOST'}; } else { $remotehost = $ENV{'REMOTE_ADDR'}; } # This just updates the number of users frame... if($data{'FA'} eq "ShowUsers"){ &show_users_online; exit(); } elsif($data{'FA'} eq "RefreshChat"){ &refresh_chat; exit(); } elsif($data{'FA'} eq "Logout"){ &logout; } elsif($data{'FA'} eq "Register"){ ®ister; } elsif($data{'FA'} eq "Login"){ # Check if they are banned. &check_banned_ip; &authenticate; &print_frameset; } elsif($data{'FA'} eq "ChatMenu"){ # Check if they are banned. &check_banned_ip; &authenticate; &print_chat_menu; } elsif($data{'FA'} eq "LoginScreen"){ # Check if they are banned. #&check_banned_ip; &loginscreen; } elsif($data{'FA'} eq "Talk"){ # Check if they are banned. &check_banned_ip; &authenticate; &talk; } else { # Print a default error message. &pct; print "$header Error: Invalid action $footer"; exit(); } sub print_chat_menu { $msg_text3 = &trans_subst($msg_text3,"%LOGIN%",$login); &pct; print "$form_window_header
$msg_text3
"; if($use_icons == 1){ open(F, "<$path_to_icons_file"); my $i = 0; while(){ if($_ =~ /^#/){ next; } my($smiley,$url) = split(/\|\|\|/, $_); $icons_tbl .= "\"$smiley\" "; } if($icons_tbl){ print "Click to use: $icons_tbl"; } } print "$form_window_footer"; exit(); } sub loginscreen { &pct; print "$form_window_header $msg $js_functions
$msg_text14
$msg_text56
$msg_text15                                                     [Register!]
                             
$form_window_footer"; exit(); } sub talk { &get_date('',$time_format); $data{'Sez'} =~ s/^\s+//g; $data{'Sez'} =~ s/\s+$//g; $data{'Sez2'} =~ s/^\s+//g; $data{'Sez2'} =~ s/\s+$//g; if($data{'Sez'} eq ""){$data{'Sez'} = $data{'Sez2'};} open(CHATTERS, "<$path_to_active_users") || &debug("$msg_debug6 $!"); $ison = (grep(/^$login\|/, ))[0]; close(CHATTERS); $ison =~ s/\s+$//g; if($ison ne ""){ $loggedin = 1; } if($loggedin != 1){ # If not, add to chatters. open(CHATTERS, ">>$path_to_active_users") || &debug("$msg_debug7 $!"); if($^O !~ /win/i){ flock(CHATTERS, 2); } else { binmode(CHATTERS); } seek(CHATTERS, 0, 2); print CHATTERS "$login|$remotehost|$time|$data{'color'}\n"; if($^O !~ /win/i){ flock(CHATTERS, 8); } close(CHATTERS); } # If so, update time. else { ($f_login,$f_remote,$f_time,$f_color) = split(/\|/, $ison); $time = time + ($server_time_offset * 60 * 60); open(CHATTERS, "+<$path_to_active_users") || &debug("$msg_debug7 $!"); if($^O !~ /win/i){ flock(CHATTERS, 2); } else{ binmode(CHATTERS); } @chatters = ; foreach $chatter (@chatters){ $chatter =~ s/\s+$//g; if($chatter =~ /^$f_login\|/){ $nchatter .= "$f_login|$f_remote|$time|$f_color\n"; } else { $nchatter .= "$chatter\n"; } } truncate(CHATTERS, length($nchatter)); # Rewind to the beginning of the file... seek(CHATTERS, 0, 0); print CHATTERS $nchatter; close(CHATTERS); &check_idle_timeouts; } if($data{'Sez'} eq ""){$text = "<$msg_text6>";} else { $text = $data{'Sez'}; } if($loggedin != 1){ if($show_user_address == 1){ $msg_text18 = &trans_subst($msg_text18,"%REMOTEHOST%",$remotehost); $text = "<$msg_text18.$embedsnd> $text"; } else{ $text = "<$msg_text19.$embedsnd> $text"; } } # Add to chat file. &write_to_chat_file($login,$remotehost,$text,""); # Now display it... # Get the contents of that file into a variable. Could also have used # $file = `cat list.html`; but it's better to avoid this, as it doesn't # work on all systems if the systems don't have "cat". open(T, "<$path_to_topic_file"); $chat_topic = ; close(T); open(FILE, "<$path_to_chat_file") || &debug("$msg_debug8 $!"); &pct; while(){ $_ =~ s/(.*)/$chat_topic/s; print; } close(FILE); $/="\n"; exit(); } sub get_date { my($testtime,$timefmt,$twodigityear); if($_[0] eq ""){$testtime = time + ($server_time_offset * 60 * 60);} else{$testtime = $_[0];} if($_[1] ne ""){$timefmt = $_[1];} else {$timefmt = "MM/DD/YY HH:MN:SS";} my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($testtime))[0,1,2,3,4,5]; $mon = $mon + 1; if ($hour < 10) { $hour = "0$hour"; } if ($min < 10) { $min = "0$min"; } if ($sec < 10) { $sec = "0$sec"; } $year += 1900; $twodigityear = $year; $twodigityear =~ s/(\d\d)(\d\d)/$2/; $timefmt =~ s/MM/$mon/g; $timefmt =~ s/DD/$mday/g; $timefmt =~ s/YYYY/$year/g; $timefmt =~ s/YY/$twodigityear/g; $timefmt =~ s/HH/$hour/g; $timefmt =~ s/MN/$min/g; $timefmt =~ s/SS/$sec/g; $date = "$timefmt"; $date; } sub show_users_online { &pct; &check_idle_timeouts; print " \n "; $users_online .= "
\n"; open(FILE, "<$path_to_active_users") || &debug("$msg_debug6 $!"); @clines = ; foreach $cline (@clines){ ($show_user,$show_remote_host,$time_on,$color)=split(/\|/, $cline); ($show_user,$blah) = &check_badwords($show_user,"blah"); $date = &get_date($time_on,$time_format); chomp($color); $color =~ s/\s+$//g; $users_online .= "\n"; $found_users = $found_users + 1; } close(FILE); $users_online_header = " $msg_text8

\n"; if($found_users == 0){ $users_online .= "\n"; if($clear_chatroom_when_empty == 1){ &clear_chatroom; } } else{ if($found_users == 1){ $user_s = "$msg_text10"; } else{ $user_s = "$msg_text11"; $user_s =~ s/%NUMUSERS%/$found_users/; } $kphdate = &get_date('',$time_format); print "$msg_text8\n"; } $msg_text13 =~ s/\s+/ /g; print "$users_online
$msg_text2$msg_text7
$show_user $date
$msg_text9
$user_s
$msg_text12:
$kphdate
"; print "
[ $msg_text13 ]
"; } sub parse_data { local($string); # get data if ($ENV{'REQUEST_METHOD'} eq 'GET') { $string = $ENV{'QUERY_STRING'}; } else { read(STDIN, $string, $ENV{'CONTENT_LENGTH'}); } # split data into name=value pairs @data = split(/&/, $string); # split into name=value pairs in associative array foreach (@data) { split(/=/, $_); $_[0] =~ s/\+/ /g; # plus to space $_[0] =~ s/%0D%0A%0D%0A/\n\n/g; #added by kristina make newlines? $_[0] =~ s/%0a/newline/g; $_[0] =~ s/\%00//g; $_[0] =~ s/%(..)/pack("c", hex($1))/ge; # hex to alphanumeric if(defined($data{$_[0]})){ $data{$_[0]} .= "\0"; $data{$_[0]} .= "$_[1]"; } else { $data{"$_[0]"} = $_[1]; } } # translate special characters foreach (keys %data) { $data{"$_"} =~ s/\+/ /g; # plus to space $data{"$_"} =~ s/%(..)/pack("c", hex($1))/ge; # hex to alphanumeric $data{"$_"} =~ s/\%00//g; } %data; # return associative array of name=value } sub debug { if($debugging == 1){ &pct; print "$msg_debug0: $_[0]
\n"; } } sub pct { # Just prints the mime header if we need to. print "Content-type: text/html\n\n" if $pct != 1; $pct = 1; } sub print_frameset { # Subroutine to just draw the frameset on login: # I need to have $login &pct; open(CHATTERS, "<$path_to_active_users") || &debug("$msg_debug6 $!"); $isloggedon = (grep(/^$login\|/, ))[0]; close(CHATTERS); if($login eq "" || $login =~ /^\s+$/){ $msg_text20 = &trans_subst($msg_text20,"%LOGIN%",$login); $msg_text20 = &trans_subst($msg_text20,"%REFERER%",$ENV{'HTTP_REFERER'}); print "$header $msg_text20 $footer"; exit(); } elsif($isloggedon ne ""){ $msg_text21 = &trans_subst($msg_text21,"%LOGIN%",$login); $msg_text21 = &trans_subst($msg_text21,"%REFERER%",$ENV{'HTTP_REFERER'}); print "$header $msg_text21 $footer"; exit(); } $encpw = encodepw($data{'Password'}); print < Chat! $footer EOF open(CHATTERS, ">>$path_to_active_users") || &debug("$msg_debug7 $!"); if($^O !~ /win/i){flock(CHATTERS, 2);} else{ binmode(CHATTERS);} seek(CHATTERS, 0, 2); print CHATTERS "$login|$remotehost|$time|$data{'color'}\n"; if($^O !~ /win/i){flock(CHATTERS, 8); } close(CHATTERS); $msg_text18 = &trans_subst($msg_text18,"%REMOTEHOST%",$remotehost); if($show_user_address == 1){ $text = "<$msg_text18$embedsnd>"; } else{ $text = "<$msg_text19$embedsnd>"; } &write_to_chat_file($login,$remotehost,"$text"); exit(); } sub logout { open(FILE, "+<$path_to_active_users") || &debug("$msg_debug6 $!"); binmode(FILE); @lines = ; if($^O !~ /win/i){flock(FILE, 2);} foreach $line (@lines){ $line =~ s/\s+$//g; if($line !~ /^$login\|/){ $nfile .= "$line\n"; } } truncate(FILE, length($nfile)); seek(FILE, 0, 0); print FILE "$nfile"; close(FILE); &write_to_chat_file($login,$remotehost,"<$msg_text22>") if $data{'color'} ne ""; if(length($nfile) == 0 && $clear_chatroom_when_empty == 1){ &clear_chatroom; } &pct; print qq[Good bye!
Close Window
]; exit(); } sub write_to_chat_file { my($login) = $_[0]; my($ip) = $_[1]; my($message) = $_[2]; my($js_stuff) = $_[3]; my($text) = $_[2]; my($date) = &get_date('',$time_format); if($play_sound_when_entering == 1 && $text =~ /\Q$embedsnd\E/){ $playsound = 1; } undef $/; open(FILE, "+<$path_to_chat_file") || &debug("$msg_debug9 $!"); # Try to open a file that holds the statements everyone has been making # and lock it... if($^O !~ /win/i){ flock(FILE, 2); } else{ binmode(FILE); } # We assume that there is between each "statement" # because we put it there. :) @entries = split("", ); # Now, we can get any entry in "@entries" by calling them by number. # this way, we can print only $number_of_chats_to_display to the file later. # Now, we've opened the file, but let's make sure it refreshes the next time. $newhtml = " $chat_window_header "; # Don't allow them to put in html code if we don't want them to... if($disable_html == 1 && $playsound != 1){ $login =~ s//>/g; $text =~ s//>/gs; } $clogin = $login; $ctext = $text; # Check for "bad words". :) ($clogin,$ctext) = &check_badwords($clogin,$ctext); # Don't parse for smileys if it's the command to remove an icon if($ctext !~ /\/removeicon/ && $ctext !~ /\/addicon/){ ($clogin,$ctext) = &do_icons($clogin,$ctext); } # must get rid of " in the message... # Make their message in a happy color with date and stuff... # See if they did "/me" or "/login" and treat that accordingly. if($ctext =~ /^\/me /i || $ctext =~ /^\/$login /i){ $ctext =~ s/^\/me //; $ctext =~ s/^\/$login //; $ctext = "[$date] $clogin $ctext
"; } # /yell elsif($ctext =~ /^\/$msg_text23/i){ $ctext =~ s/^\/$msg_text23//i; $ctext =~ s/^\s+//ig; $ctext =~ tr/[a-z]/[A-Z]/; $msg_text24 = &trans_subst($msg_text24,'%LOGIN%',$clogin); $ctext = "[$date] $msg_text24 \"$ctext\"
"; } # Trying settings # /settings elsif($ctext =~ /^\/$msg_text40/i){ $unique = $$; $fname = $login; $fname =~ s/\W+//g; if($show_settings_to_user == 1){ if($disable_special_characters_in_login == 1){$cdisspl = "$msg_text25";} else{$cdisspl = "$msg_text26";} if($disable_html == 1){ $cdisable_html = "$msg_text25"; } else { $cdisable_html = "$msg_text26"; } if($clear_chatroom_when_empty == 1){ $emptyout = "$msg_text26"; } else { $emptyout = "$msg_text25"; } if($log_all_chats == 1){ $clogging = "$msg_text26"; } else { $clogging = "$msg_text25"; } if($show_user_address == 1){ $showaddr = "$msg_text26"; } else { $showaddr = "$msg_text25"; } if($censor_chat == 1){$ccensor = "$msg_text26";} else{$ccensor = "$msg_text25";} $ctext = "\n\n"; } else { $msg_text39 = &trans_subst($msg_text39,"%SETTINGS%",$msg_text40); $ctext = "\n\n"; } } # /addicon elsif($ctext =~ /^\/$msg_text76 /i){ &addicon(); } # /removeicon elsif($ctext =~ /^\/$msg_text78 /i){ &removeicon; } # /kick elsif($ctext =~ /^\/$msg_text57 /i){ &kick; } # /quit elsif($ctext =~ /^\/$msg_text90/i){ &quitchat; } # /showusers elsif($ctext =~ /^\/$msg_text84\b/i){ &showusers; } # /deluser elsif($ctext =~ /^\/$msg_text86\b/i){ &deluser; } # /adduser elsif($ctext =~ /^\/$msg_text88\b/i){ &adduser; } # /op elsif($ctext =~ /^\/$msg_text80 /i){ &op; } # /unop elsif($ctext =~ /^\/$msg_text82 /i){ &unop; } # /badword elsif($ctext =~ /^\/$msg_text72 /i){ &badword; } # /unbadword elsif($ctext =~ /^\/$msg_text73 /i){ &unbadword; } # /ban elsif ($ctext =~ /^\/$msg_text58 /){ $ctext =~ s/^\/$msg_text58 /\/$msg_text57 /; &kick; if($i_am_admin == 1){ open(BIP, ">>$path_to_banned_ip_file") || &debug("$msg_debug13: $!"); if($^O !~ /win/){ flock(BIP, 2); } print BIP "$iptb\n" if $iptb ne "" && ($ban_preferences eq "ip" || $ban_preferences eq "both"); print BIP "$tologin\n" if $tologin ne "" && ($ban_preferences eq "login" || $ban_preferences eq "both"); close(BIP); $ctext .= "[$date] $tologin:$msg_text66 ($iptb)
"; } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /$msg_text58
",$login); } } # /unban elsif ($ctext =~ /^\/$msg_text59/){ $unique = $$; if($i_am_admin == 1){ if($ctext eq "/$msg_text59"){ # Show them what names, addys are banned. open(BIP, "<$path_to_banned_ip_file") || &debug("$msg_debug12: $!"); while(){ chomp; $banned .= "$_
"; } close(BIP); $ctext = "\n\n"; } else { ($unban,$pattern) = split(/\s+/, $ctext); open(BIP, "+<$path_to_banned_ip_file") || &debug("$msg_debug13 $!"); if($^O !~ /win/i){flock(BIP, 2);} else { binmode(BIP); } @bips = ; foreach $bip (@bips){ chomp($bip); if($bip ne $pattern){ $newbipfile .= "$bip\n"; } } truncate(BIP, length($newbipfile)); seek(BIP, 0, 0); print BIP $newbipfile; close(BIP); $ctext = "\n\n"; } } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /$msg_text59
",$login); } } # /whisper (msg_text41) or /msg elsif($ctext =~ /^\/msg/i || $ctext =~ /^\/$msg_text41/i){ $ctext =~ s/\"/\\\"/g; $unique = $$; $fname = $login; $fname =~ s/\W+//g; $ctext =~ s/^\/msg//i; $ctext =~ s/^\/$msg_text41//i; $tologin = $ctext; $tologin =~ s/^\s+//g;$tologin =~ s/\s+$//g; $tologin =~ s/(.*?)(\s+)(.*)/$1/; $tomsg = $ctext; $tomsg =~ s/^\/msg $tologin//; $tomsg =~ s/^\s+$tologin//; $tomsg =~ s/^$tologin//; $pvtmsgfrom = &trans_subst($msg_text42,"%LOGIN%",$clogin); $pvtmsgto = &trans_subst($msg_text43,"%LOGIN%",$tologin); $frommsg = "
[$date] [$pvtmsgto] $tomsg
"; $tomsg = "
[$date] [$pvtmsgfrom] $tomsg
"; $tomsg = uri_escape($tomsg,'\0-\377'); $frommsg = uri_escape($frommsg,'\0-\377'); $ctext = "\n"; } # /topic elsif($ctext =~ /^\/$msg_text71/i){ $ctext =~ s/^\/$msg_text71//; if($chat_topic ne $ctext){ $chat_topic = $ctext; } if($i_am_admin || $users_can_change_topic == 1){ open(F, ">$path_to_topic_file"); print F $ctext; close(F); open(F, "+<$path_to_chat_file") || print "NO!"; undef $newfile; while(){ $_ =~ s/(.*)/$ctext/s; $newfile .= $_; } truncate(F, length($newfile)); seek(F, 0, 0); print F $newfile; close(F); $ctext = "[$date] $clogin: Changed the topic to \"$ctext\"
"; } else { $ctext = "[$date] $clogin: Tried to change the topic. That's a no-no! :-)
"; } } # /adminhelp elsif($ctext =~ /^\/$msg_text92/i){ $unique = $$; $fname = $login; $fname =~ s/\W+//g; $ctext =~ s/^\/$msg_text44//i; $msg_text50 =~ s/\"/\\\"/g; $lcmessagetext = lc($msg_text47); $ucmessagetext = uc($msg_text47); if($i_am_admin == 1){ $adminhelp = 1; $helptext = show_helptext($adminhelp); } else { $helptext = "[Error]: You are not authorized to use this command.
"; } $helptext = uri_escape($helptext, '\0-\377'); $code = qq[ document.write(unescape('$helptext')); ]; $ctext = private_code($login,$code); } # /help elsif($ctext =~ /^\/$msg_text44/i){ $unique = $$; $fname = $login; $fname =~ s/\W+//g; $ctext =~ s/^\/$msg_text44//i; $lcmessagetext = lc($msg_text47); $ucmessagetext = uc($msg_text47); $helptext = show_helptext($adminhelp); $helptext = uri_escape($helptext, '\0-\377'); $code = qq[ document.write(unescape('$helptext')); ]; $ctext = private_code($login,$code); } else { $ctext = "[$date] $clogin: $ctext
"; } # Put the new info in. if($new_chat_lines_on_top == 1){ $ctext =~ s/\n+/\n/sg; $newhtml .= "$ctext"; $newhtml .= "\n\n"; } # Now, we're going to step through the previous entries, and print them # back to the file: if($new_chat_lines_on_top == 0){ while($#entries >= $number_of_chats_to_display){ shift(@entries); } } # Starting with 1, until $i is equal to 10, add 1 to $i and keep looping... for($i = 1; $i <= $number_of_chats_to_display; $i++){ if($entries[$i] !~ /$chat_window_footer/){ $entries[$i] =~ s/\Q$embedsnd\E//sg; $entries[$i] =~ s/\n+/\n/gs; $newhtml .= "$entries[$i]\n\n" if $entries[$i] ne ""; } } if($new_chat_lines_on_top == 0){ $ctext =~ s/\n+/\n/sg; $newhtml .= $ctext; $newhtml .= "\n\n"; } $newhtml .= "$js_stuff\n$chat_window_footer"; truncate(FILE, length($newhtml)); seek(FILE, 0, 0); print FILE $newhtml; # Close the document cleanly. close(FILE); $/ = "\n"; # Log it if they want a transcript... &log("$ctext") if $log_all_chats == 1; } sub clear_chatroom { undef $/; open(FILE, "$path_to_chat_file") || &debug("$msg_debug8 $!"); # We assume that there is between each "statement" # because we put it there. :) @entries = split("", ); close(FILE); $/ = "\n"; $i = 0; foreach $entry (@entries){ if($entry =~ /table border/ && $entries[$i + 1] =~ /\Q$msg_text53\E/){ $already_cleared = 1; last; } $i++; } if($already_cleared != 1){ # Now, we can get any entry in "@entries" by calling them by number. # this way, we can print only $number_of_chats_to_display to the file later. $date = &get_date(time,$time_format); # Try to open a file that holds the statements everyone has been making # and lock it... open(FILE, ">$path_to_chat_file") || &debug("$msg_debug9 $!"); if($^O !~ /win/i){ flock(FILE, 2); } else{ binmode(FILE); } # Now, we've opened the file, but let's make sure it refreshes the next time. print FILE "\n"; print FILE "\n"; print FILE " $chat_window_header
"; # Put the new info in. print FILE "$msg_text53"; print FILE "\n"; # Now, we're going to step through the previous entries, and print them # back to the file: # Starting with 1, until $i is equal to 10, add 1 to $i and keep looping... for($i = 1; $i <= $number_of_chats_to_display; $i++){ if($entries[$i] !~ /$chat_window_footer/){ $entries[$i] =~ s/\n//gs; print FILE "
\n"; } } # Close the document cleanly. print FILE "
$chat_window_footer"; close(FILE); $/ = "\n"; } } sub check_idle_timeouts { # What the hey: let's check for people we should auto-timeout here # too. my $time = time + ($server_time_offset * 60 * 60); my($line, @chatters,$one,$two,$stuff); open(CHATTERS, "+<$path_to_active_users") || &debug("$msg_debug7 $!"); if($^O !~ /win/i){ flock(CHATTERS, 2); } else{ binmode(CHATTERS); } @chatters = ; foreach $line (@chatters){ $line =~ s/\s+$//g; ($f_l,$f_rh,$f_t,$f_c) = split(/\|/, $line); # New time is the time since they last spoke ($f_t) plus # the idle_timeout. $ntime = $f_t + $idle_timeout; # If this is less than the real time, then they need to # be cleared, otherwise ad them back to the file. if(($f_t + $idle_timeout) >= $time){ $one = $f_t + $idle_timeout; $two = $time; $stuff .= "$line\n"; } else{ $data{'color'} = $f_c; chomp($f_c); $js_header = " \n"; &write_to_chat_file($f_l,$f_rh,"<$msg_text22 ($msg_text54).>\n",$js_header); } } truncate(CHATTERS, length($stuff)); seek(CHATTERS, 0, 0); print CHATTERS $stuff; close(CHATTERS); if(length($stuff) == 0 && $clear_chatroom_when_empty == 1){ &clear_chatroom; } } sub log { $text = $_[0]; ($mday,$mon,$year) = (localtime(time + ($server_time_offset * 60 * 60)))[3,4,5]; $mon += 1; $year += 1900; opendir(DIR, "$log_directory"); @files = readdir(DIR); closedir(DIR); foreach $file (@files){ if(-f $file && $file =~ /^sfechat-log/){ $logsize += (stat($file))[7]; } } undef @files; if($type_of_log eq "daily"){ $file = "sfechat-log-$mday-$mon-$year.html"; } elsif($type_of_log eq "monthly"){ $file = "sfechat-log-$mon-$year.html"; } else{ $file = "sfechat-log.html";} if($logsize <= $max_log_space){ open(FILE, ">>$log_directory/$file") || &debug("$msg_debug10 $!"); if($^O !~ /win/i){ flock(FILE, 2);} else { binmode(FILE);} seek(FILE, 0, 2); print FILE "$text
\n"; close(FILE); } } sub check_badwords { my($clogin,$ctext) = @_; if($ctext =~ /^\/unbadword/){ return($clogin,$ctext); } if($censor_chat == 1){ $/ = "\n"; $msg_debug11 = &trans_subst($msg_debug11,"%BADWORDS_FILE%",$path_to_badwords_file); open(BW, "<$path_to_badwords_file") || &debug("$msg_debug11 $!"); @badwords = grep(!/^#/,); close(BW); foreach $badword (@badwords){ chomp($badword); $badword =~ s/^\s+//sg; $badword =~ s/\s+$//sg; if($badword eq ""){ next; } $clogin =~ s/$badword/\[$censored_msg\]/ig; $ctext =~ s/$badword/\[$censored_msg\]/ig; } } my(@results) = ($clogin,$ctext); @results; } sub check_banned_ip { $msg_debug12 = &trans_subst($msg_debug12,"%BANNED_IP_FILE%",$path_to_banned_ip_file); if($data{'Login'} eq $admin_login && $data{'Password'} eq $admin_password){ return; } open(BIP, "<$path_to_banned_ip_file") || &debug("$msg_debug12 $!"); @bips = grep(!/^#/,); close(BIP); foreach $bip (@bips){ chomp($bip); if($ENV{'REMOTE_HOST'} =~ /^$bip$/i || $ENV{'REMOTE_ADDR'} eq $bip || $data{'Login'} eq $bip){ &pct; print "$chat_window_header
$msg_text55


$banned_message
$footer"; exit(); } } } sub trans_subst { my ($text, $old, $new) = @_; $text =~ s/$old/$new/g; $text; } sub process_lang { open(LANG, "<$path_to_language_file") || &die_usefully("Could not open language file $path_to_language_file. Server error: $!"); @langtext = grep(!/^#/, ); close(LANG); foreach $textbit (@langtext){ chomp($textbit); $msgnum = $textbit; $msgnum =~ s/\:.*$//; $msgtext = $textbit; $msgtext =~ s/^(.*?)(:)(.*)$/$3/; $msgtext =~ s/^\s+//g; $msgtext =~ s/\s+$//g; if($msgnum !~ /^msg_(text|debug)\d{1,2}/){next;} else { $$msgnum = $msgtext; } # print "\$$msgnum $msgtext\n\n"; } } sub die_usefully { &pct; print "

Fatal Error: $_[0]
"; exit(); } sub register { use CGI::Carp qw(fatalsToBrowser); &pct; $login = $data{'login'}; $pw1 = $data{'password1'}; $pw2 = $data{'password2'}; if($data{'FA2'} eq "Addme"){ # We will only accept letters, numbers, dash, dot, and underscore in # logins. $ok_login_chars = 'A-Za-z0-9-_.'; if($login =~ /[^$ok_login_chars]/){ $msg = "Error: Logins may only contain letters, numbers, and the -, ., and _ characters. Please choose a different login.
"; $data{'FA2'} = ""; ®ister; } # Anything there? if($login eq "" || $pw1 eq "" || $pw2 eq ""){ $msg = "Error: Please choose a username and password.
"; $data{'FA2'} = ""; ®ister; } if($pw1 eq "" || $pw2 eq "" || $pw1 ne $pw2){ $msg = "Error: Passwords don't match. Please re-type your password.
"; $data{'FA2'} = ""; ®ister; } # Add the user to the file open(RF, "+<$path_to_registered_users") || &debug("Could not open registered users file for writing: $!"); if($opsys eq "unix"){ flock(RF, 2); } else { binmode(RF); } $testuser = (grep(/^$login\|/i, ))[0]; if($testuser ne ""){ $msg = "Error: Username $login is taken. Please try again.
"; $data{'FA2'} = ""; ®ister; } seek(RF, 0, 2); print RF "$login|" . crypt($pw1, $$.time) . "\n"; close(RF); $msg = "$login successfully registered!
"; &loginscreen; exit(); } print "$header $msg
Please choose a login name:
Please choose a password:
Type the password again:
$footer"; exit(); } sub authenticate { &pct; $login = $data{'Login'}; $pw = $data{'Password'}; $ok_login_chars = 'A-Za-z0-9-_.'; if($login =~ /[^$ok_login_chars]/){ $msg = "Error: Logins may only contain letters, numbers, and the -, ., and _ characters. [Register]
"; &loginscreen; exit(); } $! = ""; if($login eq "$admin_login" && $pw eq "$admin_password"){ $i_am_admin = 1; return 1; } open(RF, "<$path_to_registered_users") || &debug("Could not open registered users file: $!"); $stuff = (grep(/^$login\|/, ))[0]; ($t_login,$t_pw) = split(/\|/, $stuff); chomp($t_pw); if($t_login ne $login || crypt($pw, $t_pw) ne $t_pw){ $msg = "Error: Username or password incorrect. [Register]
"; &loginscreen; exit(); } } sub encodepw { $_[0] =~ s/([^A-Za-z0-9-_])/uc sprintf("%%%02x",ord($1))/eg; $_[0]; } sub admin_menu { # Nope. None of this is implemented. Maybe someday, though. :-) #$admin_login = "admin"; #$admin_password = "hungry"; # Ban user (select from users online) /ban username # Ban user by ip /ban username # Ban user by username (not online) Can't ban if they're not online. # Un-ban # Delete user # Change user pw # Configure chat } sub badword { if($i_am_admin == 1){ $ctext =~ s/\"/\\\"/g; $ctext =~ s/^\/$msg_text72//i; $ctext =~ s/^\s+//sg; $ctext =~ s/\s+$//sg; open(BW, ">>$path_to_badwords_file") || &debug("Could not write to badwords file: $!"); print BW "$ctext\n"; close(BW); $ctext = "[$date] $admin_login: Added $ctext to the badwords file.
"; } else { $ctext = private_msg("[$date] $clogin: Sorry, you are not authorized to use /$msg_text72
",$clogin); } } sub unbadword { if($i_am_admin == 1){ $ctext =~ s/\"/\\\"/g; $ctext =~ s/^\/$msg_text73//i; $/ = "\n"; open(BW, "+<$path_to_badwords_file") || &debug("Could not write to badwords file: $!"); while(){ $file_bw = $_; chomp($file_bw); $file_bw =~ s/^\s+//sg; $file_bw =~ s/\s+$//sg; $ctext =~ s/^\s+//sg; $ctext =~ s/\s+$//sg; if($file_bw !~ /^$ctext$/i && $file_bw ne ""){ $newbwfile .= "$_"; } else { $found = $file_bw; } } truncate(BW, length($newbwfile)); seek(BW, 0, 0); print BW $newbwfile; close(BW); $ctext .= "[$date] $admin_login: Removed '$ctext' ($found) from the badwords file.
"; } else { $ctext = private_msg("[$date] $clogin: Sorry, you are not authorized to use /$msg_text73
",$clogin); } } sub kick { if($i_am_admin == 1){ $ctext =~ s/\"/\\\"/g; $unique = $$; $fname = $login; $fname =~ s/\W+//g; $ctext =~ s/^\/$msg_text57//i; $tologin = $ctext; $tologin =~ s/^\s+//g;$tologin =~ s/\s+$//g; $tologin =~ s/(.*?)(\s+)(.*)/$1/; # $tologin =~ s/\W+//; # Get their host from the chatters.txt file open(CT, "<$path_to_active_users"); ($user_to_ban) = (grep(/^$tologin\|/, ))[0]; ($utb,$iptb,$ctb) = split(/\|/, $user_to_ban); close(CT); if($tologin eq $admin_login){ $ctext = "[$date] $tologin: $msg_text6
"; return; } open(CT, "+<$path_to_active_users") || &debug("$msg_debug6 $!"); binmode(CT); @lines = ; if($^O !~ /win/i){flock(CT, 2);} foreach $line (@lines){ $line =~ s/\s+$//g; if($line !~ /^$tologin\|/){ $nfile .= "$line\n"; } else { $found_kickee_online = 1; } } truncate(CT, length($nfile)); seek(CT, 0, 0); print CT "$nfile"; close(CT); if($found_kickee_online == 1){ $ctext = "\n\n"; $ctext .= "[$date] $tologin: $msg_text69
"; } # is logged on and has been kicked. else { $ctext = "\n\n"; } } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /$msg_text57
",$login); } } sub refresh_chat { &pct; open(T, "<$path_to_topic_file"); $chat_topic = ; close(T); open(F, "<$path_to_chat_file"); while(){ $_ =~ s/(.*)/$chat_topic/s; print; } exit(); } sub check_config { $error = &check_default_password(); eval("use URI::Escape;"); if($@){ $error .= "This program requires the Perl module \"URI::Escape\". Your server is reporting that it's not available. ($@) Please ask your web hosting provider to install the URI::Escape Perl module.
"; } foreach $var ('path_to_registered_users','path_to_chat_file','path_to_banned_ip_file','path_to_badwords_file','path_to_active_users','path_to_topic_file'){ unless(-w ${$var}){ $error .= "Cannot write to the file ${$var}. Please check the setting of \$$var in the script and make sure it is correct.
\n"; } } if($error){ &pct; print $header; print qq[ Sorry, but there is a problem with the configuration:

$error
The error(s) noted above must be fixed for the script to function. The following information about your system may prove useful in determining the correct settings:

]; print "Server O/S: $^O
" if $^O; print "Server Name: $ENV{'SERVER_NAME'}
" if $ENV{'SERVER_NAME'}; print "Server Software: $ENV{'SERVER_SOFTWARE'}
" if $ENV{'SERVER_SOFTWARE'}; print "Server Signature: $ENV{'SERVER_SIGNATURE'}
" if $ENV{'SERVER_SIGNATURE'}; print "Host Name: $ENV{'HTTP_HOST'}
" if $ENV{'HTTP_HOST'}; print "Server address: $ENV{'SERVER_ADDR'}
" if $ENV{'SERVER_ADDR'}; print "Script Name: $ENV{'SCRIPT_NAME'}
" if $ENV{'SCRIPT_NAME'}; print "Script Filename: $ENV{'SCRIPT_FILENAME'}
" if $ENV{'SCRIPT_FILENAME'}; print "Document Root: $ENV{'DOCUMENT_ROOT'}
" if $ENV{'DOCUMENT_ROOT'}; print "Path Translated: $ENV{'PATH_TRANSLATED'}
" if $ENV{'PATH_TRANSLATED'}; print "If you're not sure what this means, please feel free to copy and paste this info into an email message, email the author with a description of what you were trying to do, and I'll try to help. :-) $footer"; exit(); } } sub addicon { if($i_am_admin == 1){ $ctext =~ s/^\/$msg_text76//i; $ctext =~ s/^\s+//sg; $ctext =~ s/\s+$//sg; ($smiley,$url) = split(/\s+/, $ctext); open(IF, ">>$path_to_icons_file") || &debug("Could not write to icons file: $!"); print IF "$smiley|||$url\n"; close(IF); $ctext = "[$date] $admin_login: Added $smiley (\"$smiley\") to the list of emoticons.
"; } else { $ctext = private_msg("[$date] $clogin: Sorry, you are not authorized to use /addicon
",$clogin); } } sub removeicon { my($file_smiley,$f_smiley,$smiley,$url,$newfile); if($i_am_admin == 1){ $ctext =~ s/^\/$msg_text78//i; $ctext =~ s/^\s+//sg; $ctext =~ s/\s+$//sg; $smiley = $ctext; open(IF, "+<$path_to_icons_file") || &debug("Could not write to icons file: $!"); while(){ $file_smiley = $_; chomp($file_smiley); $file_smiley =~ s/^\s+//sg; $file_smiley =~ s/\s+$//sg; ($f_smiley,$url) = split(/\|\|\|/, $file_smiley); $f_smiley =~ s/^\s+//sg; $f_smiley =~ s/\s+$//sg; $smiley =~ s/^\s+//sg; $smiley =~ s/\s+$//sg; if($f_smiley !~ /\Q$smiley\E/){ $newfile .= "$file_smiley\n"; } else { $removed = "$f_smiley"; } } truncate(IF, length($newfile)); seek(IF, 0, 0); print IF $newfile; close(IF); $ctext = "[$date] $admin_login: Removed $smiley ($removed) from the list of emoticons.
"; } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /removeicon
",$login); } } sub do_icons { my($clogin,$ctext) = @_; open(F, "<$path_to_icons_file"); while(){ my($line) = $_; chomp($line); if($line =~ /^#/){ next; } ($smiley,$url) = split(/\|\|\|/, $line); $ctext =~ s/\Q$smiley\E/\"$smiley\"/sg; } close(F); return ($clogin,$ctext); } sub check_default_password { if($admin_password =~ /password/i){ $error = "Your admin password is '$admin_password'. You must change this, or anyone will be able to get into your chat room!
"; } return $error; } sub op { if($i_am_really_admin == 1){ open(F, "+<$path_to_registered_users") || &debug("Could not open registered users file: $!"); $ctext =~ s/^\/$msg_text80//i; $ctext =~ s/^\s+//sg; $ctext =~ s/\s+$//sg; $/ = "\n"; while(){ $userline = $_; chomp($userline); ($username,$pw,$adminstatus) = split(/\|/, $userline); if($username eq $ctext){ $opped = 1; $newfile .= "$username|$pw|1\n"; } else { $newfile .= "$userline\n"; } } truncate(F, length($newfile)); seek(F, 0, 0); print F $newfile; close(F); if($opped){ $ctext = "[$date] $admin_login: Gave admin status to $ctext.
"; } else { $ctext = "[$date] $admin_login: Tried to give admin status to $ctext: no such user.
"; } } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /$msg_text80
",$login); } } sub unop { if($i_am_really_admin == 1){ open(F, "+<$path_to_registered_users") || &debug("Could not open registered users file: $!"); $ctext =~ s/^\/$msg_text82//i; $ctext =~ s/^\s+//sg; $ctext =~ s/\s+$//sg; $/ = "\n"; while(){ $userline = $_; chomp($userline); ($username,$pw,$adminstatus) = split(/\|/, $userline); if($username eq $ctext){ $unopped = 1; $newfile .= "$username|$pw|0\n"; } else { $newfile .= "$userline\n"; } } truncate(F, length($newfile)); seek(F, 0, 0); print F $newfile; close(F); if($unopped){ $ctext = "[$date] $admin_login: Removed admin status from $ctext.
"; } else { $ctext = "[$date] $admin_login: Tried to remove admin status from $ctext: no such user.
"; } } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /$msg_text82
",$login); } } sub check_admin_status { my($i_am_admin,$username,$pw,$admin_status); if($data{'Login'} eq "$admin_login" && $data{'Password'} eq "$admin_password"){ $i_am_admin = 1; $i_am_really_admin = 1; } else { $i_am_really_admin = 0; open(F, "<$path_to_registered_users") || &debug("Could not open registered users file: $!"); while(){ chomp(); ($username,$pw,$admin_status) = split(/\|/, $_); if($username eq $data{'Login'} && crypt($data{'Password'}, $pw) eq $pw && $admin_status == 1){ $i_am_admin = 1; last; } } close(F); } return ($i_am_admin,$i_am_really_admin); } sub private_msg { my($msg,$tologin) = @_; my($text); my($unique) = time.$$; my($tomsg) = uri_escape($msg,'\0-\377'); $text = qq[ ]; $text; } sub showusers { if($i_am_admin == 1){ open(F, "<$path_to_registered_users") || return return_ctext("Could not open registered_users file $path_to_registered_users: $!"); my $i = 0; while(){ my(@userline) = split(/\|/, $_); $users[$i] = $userline[0]; $i++; } $i = 0; foreach $user (sort(@users)){ if($i == 0){ $users .= "
";} $users .= "$user "; if($i == 2){ $users .= "
"; $i = 0; } else { $i++; } } $ctext = private_msg("[$date] $login: Current users:
$users
",$login); } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /$msg_text84
",$login); } } sub adduser { if($i_am_really_admin == 1){ ($foo,$username,$pw) = split(/\s+/, $ctext); open(F, "+<$path_to_registered_users"); while(){ ($f_username,$f_pw,$admin) = split(/\|/, $_); if($f_username eq $username || $username eq $admin_login){ $ctext = private_msg("[$date] $login: User $username already exists. Not added.
",$login); close(F); return; } } seek(F, 0, 2); print F "$username|" . crypt($pw, $$.time) . "|0\n"; close(F); $ctext = private_msg("[$date] $login: User $username successfully added.
",$login); } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /$msg_text88
",$login); } } sub deluser { if($i_am_really_admin == 1){ ($foo,$username) = split(/\s+/, $ctext); open(F, "+<$path_to_registered_users"); while(){ $userline = $_; chomp($userline); ($f_username,$f_pw,$admin) = split(/\|/, $userline); if($username eq $f_username && $username ne $admin_login){ $found = 1; } else { $newfile .= $_; } } truncate(F, length($newfile)); seek(F, 0, 0); print F $newfile; close(F); if($found == 1){ $ctext = private_msg("[$date] $login: User $username successfully deleted.
",$login); } else { $ctext = private_msg("[$date] $login: User $username not found.
",$login); } } else { $ctext = private_msg("[$date] $login: Sorry, you are not authorized to use /$msg_text86
",$login); } } sub return_ctext { $ctext = private_msg("[$date] $login: ERROR: $_[0]
",$login); return $ctext; } sub quitchat { my($text); my($unique) = time.$$; $ctext = private_code($login,"top.location.href = '$cgi_url?Login=$login&FA=Logout&color=$data{'color'}';") } sub private_code { my($login,$code) = @_; my($text); my($unique) = time.$$; $text = qq[ ]; return $text; } sub show_helptext { my($admin) = $_[0]; my($helptext); my($width) = $chat_window_width - 180; if($admin){ $helptext = qq[
$msg_text65
/$msg_text58 <login>$msg_text60
/$msg_text59$msg_text61
/$msg_text59 <$msg_text62>$msg_text63
/$msg_text72 <word>$msg_text74
/$msg_text57 <login>$msg_text64
/$msg_text76 <smiley> <URL of image file>$msg_text77
/$msg_text78 <smiley>$msg_text79
/$msg_text80 <login>$msg_text81
/$msg_text82 <login>$msg_text83
/$msg_text84$msg_text85
/$msg_text88 <login> <password>$msg_text89
/$msg_text86 <login>$msg_text87
/$msg_text92 <login>$msg_text93
]; } else { $helptext = qq[
$msg_text45
/$msg_text44$msg_text46
/msg <login> <$msg_text47>
/$msg_text41 <login> <$msg_text47>
$msg_text48
/me <$msg_text49>$msg_text50
/$login <$msg_text49>$msg_text50
/$msg_text23 <$msg_text47>$msg_text51 "$ucmessagetext"
/$msg_text40$msg_text52
/$msg_text90$msg_text91
\n
]; } return $helptext; }