WebChat part 3

Finally, $chat_buffer is ended with a footer stating that the end of the occupants list has been reached. $chat_buffer .= "<P><H2>End of Occupants List</H2><P>"; } # End of occupants processing PROCESS CHAT MESSAGES The next part of the chat script processes the chat messages for display to the user. Here, there is one thing to take into consideration: frames. If frames are activated, the chat program should display messages only if it has been called upon to read messages ($fmsgs is on). If the main frame HTML document is being output ($frames is on) or if the message submit frame is being output ($fsubmit), the script will not enter the part of the script that processes messages. if ($fmsgs eq "on" || ($frames ne "on" && $fsubmit ne "on")) {

pdf12 trang | Chia sẻ: tlsuongmuoi | Lượt xem: 1919 | Lượt tải: 0download
Bạn đang xem nội dung tài liệu WebChat part 3, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Finally, $chat_buffer is ended with a footer stating that the end of the occupants list has been reached. $chat_buffer .= "End of Occupants List"; } # End of occupants processing PROCESS CHAT MESSAGES The next part of the chat script processes the chat messages for display to the user. Here, there is one thing to take into consideration: frames. If frames are activated, the chat program should display messages only if it has been called upon to read messages ($fmsgs is on). If the main frame HTML document is being output ($frames is on) or if the message submit frame is being output ($fsubmit), the script will not enter the part of the script that processes messages. if ($fmsgs eq "on" || ($frames ne "on" && $fsubmit ne "on")) { PROCESS WHO FILES Before the messages are collected, a new who file is generated indicating that the user has read new messages. First, the old who file is deleted using unlink. Then the who file is re-created and the user information is printed to it: $user_name, $user_email, $user_http, and $current_date_time. $whofile = "$chat_room_dir/$session.who"; unlink($whofile); open(WHOFILE, ">$whofile"); print WHOFILE "$user_name|$user_email|$user_http"; print WHOFILE "|$current_date_time\n"; close (WHOFILE); Chapter 26: WebChat 709 The code deletes the file instead of writing over it, to ensure that the who file is assigned a different file creation time. A subroutine dis- cussed later removes old who files on the basis of creation time. Because this script is meant to run on multiple operating system platforms other than UNIX, the file is deleted and re-created to ensure consistency on as many platforms as possible. The RemoveOldWhoFiles subroutine is called to delete who files for users that have not read messages within the $chat_who_length period of time. $chat_who_length is a global variable that is specified in chat.setup. &RemoveOldWhoFiles; READ CHAT MESSAGES To read the chat messages, the script can be configured to restrict the num- ber of messages that are seen. Generally, users do not want to see all the old messages over and over again, so the chat script keeps track of the last read message of the user. When it is created, each message is assigned a unique sequence number in ascending order. Whenever a user reads all the mes- sages in the chat room directory, the current highest message number is set to the user’s last read message number. Then, the next time the script is called to view messages, the “last read” message number can be compared against the message numbers in the directory. If the message number is lower than the last read number, we know that the message is old. The $msg_to_read variable is set up to reflect the preceding algorithm except that 1 is added to it. Later, when the message numbers are com- pared, we will use the greater than or equal to (>=) 0 operator to com- pare the current message numbers to the last read message number stored in $msg_to_read. $msg_to_read = $user_last_read + 1; Next, $how_many_old is subtracted from $msg_to_read. As a result, some old messages are displayed with the new ones. Remember that in the chat room logon screen, the user chooses how many old messages to display with new ones. Chapter 26: WebChat 710 $msg_to_read -= $how_many_old; If there are fewer messages in the directory than $how_many_old messages, $msg_to_read could become a negative number or zero and the chat script would spend extra work trying to read files that do not exist. Thus, the next piece of code converts $msg_to_read into a positive value. if ($msg_to_read < 1) { $msg_to_read = 1; } The next if statement checks quickly to see whether $msg_to_read is greater than the current $high_message number. If $msg_to_read is greater than $high_message, we do not need to bother iterating through all the files in the directory, because nothing would be displayed. if ($high_message >= $msg_to_read) { Now we begin reading the messages within the for loop started here. for ($x = $high_message; $x >= $msg_to_read; $x—){ The sprintf command is used to format the current message number, $x, to an integer with a length of 6. Because $x is usually fewer than six char- acters long, sprintf pads it with leading spaces. Immediately afterward, the tr command is used to convert all the leading spaces to zeros. Thus, sprintf converts a number such as "5" to " 5", and the tr command converts " 5" to "000005." This is done because the messages are stored in the chat room directory as six-digit numbers with leading zeros. $x = sprintf("%6d",$x); $x =~ tr/ /0/; The message is checked for existence using the -e operator. If it exists, it is opened. If the opening of any message fails, the program exits with an error message printed to the user’s Web browser. if (-e "$chat_room_dir/$x.msg") { open(MSG,"$chat_room_dir/$x.msg") || &CgiDie("Could not open $x.msg"); Chapter 26: WebChat 711 If the file is opened successfully, the message is processed. Each line of the message corresponds to a field of information. The format of a message appears below: [USERNAME OF USER WHO POSTED MESSAGE] [EMAIL OF USER WHO POSTED MESSAGE] [URL LINK TO USER WHO POSTED MESSAGE] [USERNAME OF USER MESSAGE IS ADDRESS TO (USUALLY ALL)] [MESSAGE DATE AND TIME] [MESSAGE BODY] All the preceding fields (except the message body) are read to the follow- ing variables: $msg_from_user, $msg_email, $msg_http, $msg_to_user, and $msg_date_time. The command is a Perl convention that takes any file handle surrounded by brackets () and returns the next line in the file. In addition, any fields that the user has entered are processed using the HtmlFilter function to remove HTML codes if you have disallowed them in chat.setup. $msg_from_user = ; $msg_from_user = &HtmlFilter($msg_from_user); $msg_email = ; $msg_email = &HtmlFilter($msg_email); $msg_http = ; $msg_http = &HtmlFilter($msg_http); $msg_to_user = ; $msg_to_user = &HtmlFilter($msg_to_user); $msg_date_time = ; The last character of all the variables is chopped, because a superfluous newline character is always appended to the end of a line read from a file. chop($msg_from_user); chop($msg_email); chop($msg_http); chop($msg_to_user); chop($msg_date_time); Messages are displayed to a user only if the addressee is "ALL," if the addressee matches the current username, and if the poster username matches the current username. Chapter 26: WebChat 712 if ($msg_to_user eq "ALL" || $msg_to_user =~ /^$user_name$/i || $msg_from_user =~ /^$user_name$/i) { The information about the message is then converted to HTML code to be displayed to the user. This code is placed in the $chat_buffer variable, just as the occupants list HTML code was placed there previously. Each message header is formatted as an HTML table. The first field set up in the table is the "From:" field. $chat_buffer .= "\n"; $chat_buffer .= ""; $chat_buffer .= "From:"; If there is an E-mail address associated with the user who posted the mes- sage, a hypertext reference to the user’s address is placed in $chat_buffer. Otherwise, $msg_from_user is placed in $chat_buffer. if ($msg_email ne "") { $chat_buffer .= qq!<A HREF=MAILTO:! . qq!$msg_email>!; } $chat_buffer .= $msg_from_user; if ($msg_email ne "") { $chat_buffer .= ""; } If $msg_http is defined, the user’s URL link will be added as a hypertext reference in $chat_buffer. if ($msg_http ne "") { $chat_buffer .= qq! (! . qq!Home Page)!; } Periodically, the $chat_buffer fields are delimited with the standard , , , and HTML tags. $chat_buffer .= "\n"; $chat_buffer .= "\n"; Chapter 26: WebChat 713 If the current message number ($x) is greater than $user_last_read, then a New Msg tag is appended to the information header. if ($x > $user_last_read) { $chat_buffer .= " (New Msg) " } The date and time of the message are added to $chat_buffer. $chat_buffer .= " at $msg_date_time"; If the message was generated for a particular user, a tag is generated for the information header that lets the user know that this is a private mes- sage to him or her or that it is a private message that the user posted to someone else. $chat_buffer .= "\n"; if ($msg_to_user =~ /^$user_name$/i || ($msg_from_user =~ /^$user_name$/i && $msg_to_user ne "ALL")) { $chat_buffer .= ""; $chat_buffer .= "Private Msg To:" . "$msg_to_user" . "\n"; } The table is closed using the HTML tag, and then the body of the message is read from the file inside HTML tags. Each line is filtered using the HtmlFilter subroutine. In addition, each line is printed with a tag to show a line break. $chat_buffer .= "\n"; $chat_buffer .= "\n"; while() { $_ = &HtmlFilter($_); $chat_buffer .= "$_"; } When the message body is finished, the file is closed and the program loops back to process another file unless the current message number ($x) has reached $high_message_number. Chapter 26: WebChat 714 close(MSG); $chat_buffer .= "\n"; } $chat_buffer .= "\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 } PROCESS LOGOFF If the logoff button was pressed, the who file is deleted immediately using unlink. The user will no longer show up on the occupants list. if ($logoff ne "") { $whofile = "$chat_room_dir/$session.who"; unlink($whofile); } Because the Web is connectionless, it is possible to stay online after you “log off.” The ability to “log off” is presented as a means to allow a group of people who follow chat room etiquette to gain an accurate picture of who is in the chat room. It is not a security measure. PRINT THE CHAT SCREEN The final part of the main chat.cgi program is the printing of the chat page. The logic contained in the PrintChatScreen subroutine is complex, because it must account for both frames and nonframes printing of the chat messages and submit message form. An example of a new message in the chat message frame appears in Figure 26.11. &PrintChatScreen($chat_buffer, $refresh_rate, $session, $chat_room, $setup, $frames, $fmsgs, $fsubmit); Chapter 26: WebChat 715 Figure 26.11 Example of a new message appearing in the chat message frame. THE GETSESSIONINFO SUBROUTINE The GetSessionInfo subroutine in the chat script retrieves information about the user’s current session. This includes the username, E-mail address, URL link, refresh rate, use of frames, and last read message number. The routine starts by accepting the current session number and data about whether we are currently using frames ($frames) and, if so, whether we are refreshing the submit message frame ($fsubmit). sub GetSessionInfo { local($session, $fsubmit,$frames) = @_; $session_file, $temp, @fields, @f, $high_number, and $high_message are declared local to the subroutine. Chapter 26: WebChat 716 local($session_file); local($temp,@fields, @f); local($high_number, $high_message); $session_file appends a .dat extension to the session ID. This is the name of the session file. Then the session file is opened in the $chat_ses- sion_dir directory. $session_file = "$session.dat"; open (SESSIONFILE, "$chat_session_dir/$session_file"); The session file is read using a while loop. The session file should consist of one line of fields that are pipe-delimited. (The fields are separated by the pipe (|) symbol.) Here is an example session file: Gunther|gb@foobar.com||0|10|000067 The fields in the preceding session file are the username, E-mail address, URL, automatic refresh rate (in seconds), number of messages to display, and last read message number. while () { $temp = $_; } A chop is added so that the last field does not have a hanging newline at the end. (A file read typically reads the whole line including the newline character that separates lines in a file.) The fields are separated into the @fields array. Finally, the session file is closed. chop($temp); @fields = split(/\|/, $temp); close (SESSIONFILE); $high_message is set to the highest message number in the current chat room. This message number is used to overwrite the last read message for the user. In other words, now that the user’s last read message num- Chapter 26: WebChat 717 ber has been read to @fields from the session file, we update it with the highest message number so that the next time the script runs, only the latest messages will be displayed to the user. $high_message = &GetHighMessageNumber; @f stores the contents of @fields as a temporary holder for the old session values. Then the last field in the @fields array is set equal to $high_mes- sage. This last field corresponds to the user’s last read message number. @f = @fields; @fields[@fields - 1] = $high_message; @fields - 1 returns a number representing the number of the last element of the @fields array. @fields returns the total number of ele- ments in the array, but because arrays start counting at zero instead of 1, we subtract 1 from @fields to get a reference to the last element of the @fields array. This technique is used throughout the chapter. If frames are not on and if we are not printing the submit portion of a frame, the session file is updated with the new high message number. We open the session file and write the new @fields values to it. if ($fsubmit ne "on" && $frames ne "on") { open (SESSIONFILE, ">$chat_session_dir/$session_file"); print SESSIONFILE join ("\|", @fields); print SESSIONFILE "\n"; close (SESSIONFILE); } Finally, the original session values in @f are returned, along with the cur- rent high message number. This message number is returned because the script must know up to what sequence number to display new messages. (@f, $high_message); } # End of GetSessionInfo Chapter 26: WebChat 718 Because the user’s last read message number is set to $high_mes- sage, there is a chance that more messages might be posted to the chat room while this script is processing the messages to display. Although $high_message is actually out of date with regard to the true high message number, it is important to see that the user’s last read message is in sync with the $high_message number of mes- sages that have been displayed to the user. GETHIGHMESSAGENUMBER SUBROUTINE The GetHighMessageNumber routine reads the current chat room directory and returns the highest message number found. It uses $last_file and @files as locally declared variables to do this processing. sub GetHighMessageNumber { local($last_file, @files); First, $chat_room_dir is opened and all the files are read. The grep com- mand is used to filter in only files that have msg in the filename. In addi- tion, the messages are sorted. opendir(CHATDIR, "$chat_room_dir"); @files = sort(grep(/msg/, readdir(CHATDIR))); closedir(CHATDIR); If the number of files in the array is greater than zero, the highest mes- sage number in the array is placed in $last_file. If there are no files with msg in the chat room directory, $last_file is set to zero. Note that the filenames are all six digits long and use leading zeros to pad the number. if (@files > 0) { $last_file = $files[@files - 1]; } else { $last_file = "0000000"; } The substr command is used to return the first six characters of the file- name. Because the filenames contain six-digit numbers, this arrangement effectively returns just the numeric portion of the message filename. Chapter 26: WebChat 719 substr($last_file,0,6); } # End of GetHighMessageNumber THE MAKESESSIONFILE SUBROUTINE The MakeSessionFile routine creates the session file that stores the cur- rent user information. GetSessionInfo later uses this session file to retrieve information about the currently logged on user every time the current session ID is sent to the routine. This routine starts by accepting a list of fields that make up the user information and then returns the newly acquired session ID that is associated with the session file. sub MakeSessionFile { local(@fields) = @_; local($session, $session_file); The first thing MakeSessionFile does is to call a routine (RemoveOldSessions) to remove old session files that are no longer being used. Then a new ses- sion ID is generated by generating a random number. The random number is first seeded in the srand function by taking the value of the process ID and current time variable and combining them with the or operator (|). This random number, the time, and the process ID are converted to a long hexadecimal number that serves as the new session ID. A hexadecimal number is made up of digits that cover the numbers 0 through 9 and the letters A through F instead of the digits found in the base 10 system, 0 through 9. The session filename consists of the session ID plus a .dat extension. &RemoveOldSessions; srand($$|time); $session = int(rand(60000)); $session = unpack("H*", pack("Nnn", time, $$, $session)); $session_file = "$session.dat"; Next, the session file is opened for creation in the directory specified by the $chat_session_dir variable, which has been set in chat.setup. The Chapter 26: WebChat 720

Các file đính kèm theo tài liệu này:

  • pdfWebChat part 3.pdf
Tài liệu liên quan