#!/usr/local/bin/perl # # Copyright (c) 1999 by Per Cederberg # # The code in this file is made freely available for any purpose # whatsoever. The authors do not take any responsability for the # correctness or suitability for some particular purpose. # ###################################################################### # # Contains common subroutines and constants for CGI scripts. # # Authors: Per Cederberg, per at percederberg dot net # Version: 1.2.2 # Date: 17th of January 2000 # # # Description: # ------------ # Contains common subroutines and global constants for CGI scripts. # # # Revision history: # ----------------- # # Version 1.2.2 (2000-01-17, Per Cederberg) # - Corrected bug with BASEURL ending with an '/'. # # Version 1.2.1 (1999-09-26, Per Cederberg) # - Changed TEMPLATEDIR and removed TEMPLATEURL. # # Version 1.2 (1998-11-17, Per Cederberg) # - Changed all directory constants. # - Added TEMPLATEDIR and TEMPLATEURL. # - Removed ICONDIR and ICONURL. # - Removed BACKGROUNDDIR and BACKGROUNDURL. # - Added CollectFields routine. # # Version 1.1.2 (98-06-24, Per Cederberg) # - Added optional HTML codes to CreateHTMLImage. # - Added optional HTML codes to CreateHTMLLink. # # Version 1.1.1 (98-06-23, Per Cederberg) # - Added ICONURL and BAKGROUNDURL constants. # # Version 1.1 (98-06-22, Per Cederberg) # - Changed implentation of FileExists to use -e operator. # - Added Directory Exists routine. # - Added FindMatchingFiles routine. # - Changed to use COMMONFILE as the file variable everywhere. # - Added ReadDataFile and WriteDataFile routines. # - Added ReadAccessCount and IncreaseAccessCount routines. # # Version 1.0.1 (98-06-18, Per Cederberg) # - Corrected spelling bug in PrintErrorMessage. # - Added the FileExists routine. # - Added the LockFile and UnlockFile routines. # # Version 1.0 (98-06-16, Per Cederberg) # - First version of this script. # ###################################################################### ###################################################################### # # GLOBAL CONSTANTS AND VARIABLES # ###### Constants for directories ###### $BASEDIR = "/home/d93/d93-pol/public_html"; $CGIDIR = "/public/www.student/cgi-bin/d93-pol"; $TEMPLATEDIR = "$CGIDIR/templates"; ###### Constants for URLs ###### $BASEURL = "http://www.student.nada.kth.se/~d93-pol"; $CGIURL = "http://cgi.student.nada.kth.se/cgi-bin/d93-pol"; ###### Other global constants ###### $MAILPROG = '/usr/lib/sendmail'; # The sendmail program $CURDATE = 'No value yet'; # Current date, '1998-06-10' for example $CURTIME = 'No value yet'; # Current time, '13:39' for example $CURCENTURY = 'No value yet'; # Current century, '19' or '20' ###### Global variables ###### $method = 'No value yet'; # The form method, 'GET' or 'POST' %form = {}; # The form data exchange variable $errors = 0; # The number of errors found in the form %formerror = {}; # The errors for each field in the form ###################################################################### # # INITIALIZING # # # Initialize # # Initializing CURDATE, CURTIME and CURCENTURY. This routine is # executed once upon loading this script. # sub Initialize { local ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); if ($year gt '95') { $CURCENTURY = "19" } else { $year = $year - 100; $CURCENTURY = "20"; } $CURDATE = sprintf("%.2d%.2d-%.2d-%.2d", $CURCENTURY, $year, $mon+1, $mday); $CURTIME = sprintf("%.2d:%.2d", $hour, $min); } &Initialize(); ###################################################################### # # INPUT ROUTINES # # # ParseInput # # Parses the input sent via the CGI standard. The global variables # $method and %form will be set to new values when executing this # function. Each form field in the input will be found in the form # variable as a key with value. On multiple value for a single field # the values are concatenated with '\0' characters in the same string. # # The special input format in the CGI standard is handled and # converted to normal Perl strings. Also some substitutions of # characters with a special meaning in HTML is done. # sub ParseInput { local ($buffer, @pairs); # Read input if ($ENV{'REQUEST_METHOD'} eq 'POST') { $method = 'POST'; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @pairs = split(/&/, $buffer); } else { $method = 'GET'; @pairs = split(/&/, $ENV{'QUERY_STRING'}); } # Parse input %form = {}; foreach (@pairs) { local ($name, $value) = split(/=/, $_); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $value =~ s/&/&/g; $value =~ s//>/g; $value =~ s/\"/"/g; # $value =~ s/å/å/g; # $value =~ s/Å/Å/g; # $value =~ s/ä/ä/g; # $value =~ s/Ä/Ä/g; # $value =~ s/ö/ö/g; # $value =~ s/Ö/Ö/g; $form{$name} .= "\0" if (defined $form{$name} && $value ne ''); $form{$name} .= $value; } return %form; } # # RevertSubstitutions # # Reverts some of the imput substitutions made in the ParseInput # function, ie. converts some HTML sequences to single characters. # # Arguments: # string - the string containing the HTML special sequences # # Returns: # A string without the HTML sequences created in the input parsing. # sub RevertSubstitutions { local ($string) = @_; $string =~ s/"/\"/g; $string =~ s/<//g; $string =~ s/&/&/g; return $string; } ###################################################################### # # LIST HANDLING ROUTINES # # # PosInList # # Returns the position of a string in a given list. # # Arguments: # string - the string to search for # list - the list to search in # # Returns: # An index in the list (from zero), or -1 if the string wasn't found. # sub PosInList { local ($string, @list) = @_; local ($index); for ($index = 0; $index <= $#list; $index++) { if ($list[$index] eq $string) { return $index; } } return -1; } # # MergeLists # # Merges several lists into one, removing copies and empty strings. # # Arguments: # list1, list2, ... - the lists to merge # # Returns: # A list with all the distinct elements from the given lists. # sub MergeLists { local (@list) = @_; local ($i, @new); for ($i = 0; $i <= $#list; $i++) { if (&PosInList($list[$i],@new) == -1 && $list[$i] ne '') { $new[$#new+1] = $list[$i]; } } return @new; } # # RemoveElement # # Removes all occurrencies of an element from a list. # # Arguments: # elem - a list element # list - a list # # Returns: # A list where there are no occurrencies of the given element. # sub RemoveElement { local ($elem, @list) = @_; local ($pos); while (($pos = &PosInList($elem, @list)) > -1) { splice(@list, $pos, 1); } return @list; } # # SumList # # Sums all elements in a list. The elements has to be valid numbers. # # Arguments: # list - a list with numbers # # Returns: # The sum of all the numbers in the list. # sub SumList { local (@list) = @_; local ($i, $sum); $sum = 0; for ($i = 0; $i <= $#list; $i++) { $sum += $list[$i]; } return $sum; } # # WrapList # # Returns a new list where each element is "wrapped up" into some # template element. # # Arguments: # tag - a tag in the template string (where to put each list elem) # string - a template string # list - a list # # Returns: # A list where each element is of the template form but with the # original list element inserted on each occurrence of the tag. # sub WrapList { local ($tag, $string, @list) = @_; local ($temp, @new); foreach (@list) { $temp = $string; $temp =~ s/$tag/$_/g; $new[$#new+1] = $temp; } return @new; } ###################################################################### # # LIST TO AND FROM FORM ROUTINES # # # CollectFields # # Collects all form fields with a given name base into an # ordered list based on the field numbers. # # Arguments: # fieldname - a base field name # # Returns: # A list with all the field values in order from the lowest # numbered field to the highest. # sub CollectFields { local ($fieldname) = @_; local ($i, @res); $i = 1; @res = (); while ($form{"$fieldname$i"} ne '') { $res[$#res+1] = $form{"$fieldname$i"}; $i++; } return @res; } ###################################################################### # # STRING MANIPULATION ROUTINES # # # ChopWhitespace # # Removes trailing whitespaces on each line in a string, but keeps # the number of newlines. # # Arguments: # string - a string, possibly consisting of several lines # # Returns: # A string where all the trailing whitespace characters have # been removed for each line. # sub ChopWhitespace { local ($string) = @_; local ($result, $lastchar, $newlinecount, @lines); # Count the number of newlines $newlinecount = 0; while ($string =~m/\n/g) { $newlinecount++; } # Chop off all whitespace @lines = split(/\n/, $string); foreach (@lines) { if (length($_) > 0) { $lastchar = chop($_); while (length($_) > 0 && $lastchar =~ m/[ \n\r\t\v]/) { $lastchar = chop($_); } if ($lastchar =~ m/[ \n\r\t\v]/) { $lastchar = ''; } $result .= "$_$lastchar\n"; } else { $result .= "\n"; } } chop ($result); # To remove last newline added # Add missing newlines while ($result =~ m/\n/g) { $newlinecount--; } while ($newlinecount > 0) { $result .= "\n"; $newlinecount--; } return $result; } # # SplitLine # # Splits a string on a single line into a string containing # several lines. The trailing whitespace characters on each # line will be removed with ChopWhitespace. # # Arguments: # line - a string, possibly with newline characters # maxlen - a value for the maximum line lenght # # Returns: # A string where no line exceeds the maximum line length. # sub SplitLine { local ($string, $maxlen) = @_; local (@lines, $result, $index, $lastchar); $string = &ChopWhitespace($string); if (length($string) <= $maxlen) { return $string } @lines = split(/\n/, $string); foreach (@lines) { while (length($_) > $maxlen) { $index = rindex($_, " ", $maxlen-1); if ($index < 1) { $result .= substr($_, 0, $maxlen-1); $result .= "-\n"; $_ = substr($_, $maxlen-1); } else { $result .= substr($_, 0, $index+1); $result .= "\n"; $_ = substr($_, $index+1); } } $result .= "$_\n"; } return $result; } # # Linkify # # Detects URIs in a string and replaced them with HTML hyperlinks. # # Arguments: # string - a string # # Returns: # A string where all URI are linked to their respective address. # sub Linkify { local ($string) = @_; local (@links); @links = ($string =~ m/http:[^ \n\r\t\v]+/g); @links = &MergeLists(@links); # To remove unneccesary copies foreach (@links) { $string =~ s|$_|$_|g; } return $string; } ###################################################################### # # HTML CREATION ROUTINES # # # CreateHTMLLink # # Creates a HTML link. # # Arguments: # url - the URL to link to # text - the link text # extra - optional extra arguments to the A tag # # Returns: # A string containing the HTML hyperlink code. # sub CreateHTMLLink { local ($url, $text, $extra) = @_; local ($result); $extra = " $extra" if ($extra ne ''); $result = "$text\n"; return $result; } # # CreateHTMLImage # # Creates a HTML image insertion. # # Arguments: # src - the source of the image # text - the alternate text, can be left empty # extra - optional extra arguments to the IMG tag # # Returns: # A string containing the HTML image code. # sub CreateHTMLImage { local ($src, $text, $extra) = @_; local ($result); $result = " or # missing. # sub CreateHTMLList { local ($emptymsg, @list) = @_; local ($htmllist); if ($list[0] eq 0) { return 0; } if (@list) { foreach (@list) { $htmllist .= "
  • $_
  • \n"; } } else { $htmllist = "

    $emptymsg

    \n"; } return $htmllist; } # # CreateHTMLOptions # # Returns a html option list from a given list. # # Arguments: # default - the default option # list - a list of options # # Returns: # A string containing HTML code for the options. # sub CreateHTMLOptions { local ($default, @list) = @_; local ($options); if ($list[0] eq 0) { return 0; } $options = "\n"; foreach (@list) { if ($default eq $_) { $options .= "