home *** CD-ROM | disk | FTP | other *** search
- #!/usr/local/bin/perl
- #
- # gmail: mail-to-Gopherspace interface
- #
- # usage: gmail [-c]
- #
- # PASR 12/28/92 Rough draft.
- # PASR 12/31/92 Initial test installation.
- # PASR 01/03/93 Added DELETE function.
- # PASR 01/05/93 Reworded authorization rejection message.
- # PASR 01/05/93 Forced sender's address to lowercase for easy matching.
- # PASR 01/08/93 Declared this release 0.1 for beta testing.
- # PASR 01/15/93 Fixed bug caused by perl's inability to write to long
- # paths; removed $caldir_by_date; made year in output
- # format be yyyy instead of yy to facilitate sorting.
- # PASR 02/02/93 Added the title line to the body of each file saved
- # to facilitate WAIS indexing.
- # PASR 02/03/93 Changed "From" lines to ">From" in header in order
- # to avoid confusing mailers when we send out feedback.
- # Reversed the logic of the test in &check_target (it was
- # bogus).
- # Declared this release 0.2 for further beta testing.
- # PASR 02/04/93 Force addresses in $gmailers file to lower case since
- # the gmail administrator can't be counted on to remember
- # to do so. :-)
- # PASR 02/05/93 Added "$publiccal" mode: if it is turned on, submissions
- # in calendar mode require no authorization in the $gmailers
- # file (although deletions still do).
- # Added an optional "$disclaimer".
- # PASR 02/22/93 Declared this release 1.0 for general use.
- # PASR 03/07/93 Fixed security problem by quoting $sender in mail pipe.
- # Attempt to prevent mail loops when error messages bounce
- # back to gmail.
- # Fixed whitespace cleanup in &normalize.
- # Don't allow tabs in Name= fields in .cap files
- # (reportedly gopherd can be confused by them).
- # Unlink data file if corresponding .cap file can't be made.
- # PASR 03/09/93 Create .cap files only when necessary.
- # Moved misplaced unlink() calls to take place before &abends.
- # PASR 03/12/93 Removed unnecessary &initialize call; just use &parse_message.
- # PASR 03/29/93 Declared this version 1.01.
- #
- # TODO: Think about cleaning up &delete_it() (should move aside old
- # data rather than just gobbling it into memory).
- # TODO: Think about screening for binhex and other ASCIIfied binary formats.
- # TODO: Think about extending the "public calendar" mode to cover
- # non-calendar items as well (a "public" mode which puts data into
- # a "$publicdir" directory).
- # TODO: Think about including a command-line option which causes header
- # info to be read from a file, allowing a single installation to
- # be used in multiple configurations (in particular, to allow
- # multiple events calendars).
- # TODO: Think about a reasonable way to specify multiple target directories
- # per sender. (Hairball!)
- # TODO: Think about notifying the original submitter if someone else
- # deletes or overwrites her data.
- # TODO: Think about using $address instead of/in addition to $sender
- # for address matching.
- # TODO: Think about a way to handle directory names in the gmailers file
- # containing whitespace or # signs.
- # TODO: Add better date checking (eliminate "Feb 30", etc.).
-
- #--------------------------------------------------------------------------
- # CONFIGURATION: modify these to suit your site!
-
- # All targets must live under a directory in this list.
- # (EXAMPLE: @safedir = ("/foo/bar/dir1", "/foo/bar/dir2");
- @safedir = ("/foo/cwis/gopher/world", "/foo/cwis/gopher/rice",
- "/foo/cwis/gopher/test");
-
- # Calendar data live under here (only needed if calendar mode is turned on)
- $caldir = "/foo/cwis/gopher/world/Calendars/Events/Upcoming";
-
- # File which lists authorized users and their target directories:
- $gmailers = "/foo/cwis/gopher/etc/gmailers";
-
- # Public calendar switch: if this is set to 1, items submitted in calendar
- # mode (the "-c" flag) will not require authorization in the $gmailers file.
- # Deletions and non-calendar items will still require authorization.
- # This option is irrelevant if you are not running in calendar mode.
- $publiccal = 0;
-
- # Administrator to notify in case of errors or unauthorized submissions:
- $prob_admin = "jdoe@foobar.edu";
-
- # Administrator to notify of *every* submission (leave this undefined if
- # you only want to hear about problems):
- $debug_admin = "jdoe@foobar.edu";
-
- # Preferred mailer program. Must accept recipients' addresses on command
- # line and "Subject:" line on standard input.
- $MAIL = "/bin/mail";
-
- # A short descriptive name of your Gopher server for use in feedback and
- # error messages. It should be under 40 characters for best results.
- $server_name = "the FooInfo Gopher server";
-
- # Gopher administrator contact info and signature for use in feedback and
- # error messages.
- $sig =
- "To contact the FooInfo Gopher administrator with questions, problems
- or suggestions, send mail to fooinfo@foobar.edu or call the Consulting
- Center at 527-4983.
-
- -- FooInfo Gopher Administrator, Information Systems, fooinfo@foobar.edu
- -- This message was automatically generated.
- ";
-
- # Optional disclaimer to be appended to each item saved in Gopherspace.
- # Leave it blank if you don't need a ubiquitous disclaimer.
- #$disclaimer = "[Foobar University is not responsible for this stuff.]";
- $disclaimer = "";
-
- # Umask: the Unix file permissions mask. Use 002 if you wish to have
- # files created by gmail be group-writeable, 022 otherwise.
- $UMASK = 022;
-
- #--------------------------------------------------------------------------
- # Feedback and error messages. You can tinker with these if you like,
- # but it shouldn't be necessary.
-
- # Acceptance message.
- $accept_msg =
- "Your submission was posted to $server_name.
- Please use Gopher to check it and make sure it looks as you
- intended. If it does not, please submit it again.
-
- If you did *not* submit this request, it may mean that someone has been
- forging electronic mail in your name. Please contact the Gopher
- administrator immediately.
- ";
-
- # Authorization message.
- $auth_msg =
- "Your submission was not accepted for $server_name
- because you have not been authorized to submit data by mail from this
- e-mail address. If you would like to sign up to do so, please contact
- the Gopher administrator.
- ";
-
- # Date message.
- $date_msg =
- "Your announcement was not accepted for $server_name
- because the subject line did not contain an appropriately formatted
- date. The subject line must begin with a date in the format
- \"yy-mm-dd\" or \"yyyy-mm-dd\". For example:
-
- Subject: 92-10-31: Institutional Halloween Party
-
- Subject: 2001-01-10: Twenty-first Century Lecture
-
- Please reformat the date in your subject line and resubmit your
- announcement.
- ";
-
- # Deletion acknowledgement.
- $del_ack_msg =
- "Your request to delete data in $server_name
- was accepted. Please check the data below and make sure that it was
- what you intended to delete.
-
- If you did *not* request that this item be deleted, it may mean that
- someone has been forging electronic mail in your name. Please save
- this message and contact the Gopher administrator immediately.
- ";
-
- # Deletion error message.
- $del_err_msg =
- "Your deletion request for data in $server_name
- was not processed because of the following error:
- ";
-
- # Error message.
- $error_msg =
- "Your submission was not accepted for $server_name
- because of the following error:
- ";
-
- # Style message.
- $style_msg =
- "Your submission was not accepted for $server_name
- because either (1) it is not strictly printable ASCII text or (2) it
- contains lines which are greater than 80 columns in length. Please
- reformat your data appropriately and resubmit it.
- ";
-
- # Separators for displaying the submitted item.
- $subsep = "-------------------- Submitted request follows --------------------";
- $subend = "-------------------- End of submitted request ---------------------";
- $delsep = "---------------------- Deleted item follows -----------------------";
- $delend = "---------------------- End of deleted item ------------------------";
-
- #--------------------------------------------------------------------------
-
- # Further initialization. Don't mess with this.
- require("ctime.pl");
- require("timelocal.pl");
- $auth = 0; # Is the sender authorized?
- $calendar = 0; # Are we in calendar mode? ("-c" option)
- $delete = 0; # Are we in delete mode? ("DELETE" keyword)
- $usage = "usage: gmail [-c]";
- umask $UMASK;
- $loopsenders = '^(root|mailer-daemon|postmaster)\b';
- # senders who may mean we're in a mail loop
-
- # Now we're rolling...
-
- # Refuse to run as root.
- &abend("Data not accepted for Gopher due to gmail error",
- $error_msg . "gmail should not be run as root.\n")
- if ($> == 0);
-
- # Process command-line options.
- ARGS:
- while ($#ARGV >= 0) {
- $arg = $ARGV[0];
- shift;
- if ($arg eq "-c") {
- $calendar = 1;
- next ARGS;
- }
- &abend("Data not accepted for Gopher due to gmail error",
- $error_msg . "Unrecognized command-line option: $arg\n\n"
- . $usage);
- }
-
- # Parse the incoming message. Global variables returned which we will use:
- # $body $friendly @headers $header $sender $subject
- &parse_message(STDIN);
- $header =~ s/^From/>From/; # Don't want to confuse mailer in feedback
- $subject =~ tr/\t/ /; # Tabs could confuse gopherd.
- $sender =~ s/'//g; # We'll want to enclose $sender in 's later.
- &abend("Data not accepted for Gopher due to gmail error",
- $error_msg . "Sender not defined in mail header.\n")
- unless ($sender);
- if ($sender =~ /$loopsenders/io ||
- $subject =~ /(returned mail|user unknown)/i) {
- # We may be in a mail loop. We can't abend the normal way because
- # that could perpetuate the loop. We try to signal our distress
- # via other methods, then exit without acknowledging the message.
- system("/usr/ucb/logger -i -p mail.error gmail in possible mail loop with '$sender'")
- if (-x "/usr/ucb/logger");
- exit(0);
- }
-
- # Try to match the sender in the list of authorized users.
- $target = &check_auth();
-
- # See if this is a delete request.
- # If so, this will modify the $subject accordingly.
- $delete = &parse_delete();
-
- # If we're in calendar mode, parse the subject line for a date.
- # This will modify the $subject and $target accordingly.
- &parse_date() if ($calendar);
-
- # Check $target to make sure it safely falls within @safedir.
- &check_target($target);
-
- # Carry out the deletion and exit if we're in delete mode.
- $filename = &normalize($subject);
- &delete_it() if $delete;
-
- # Check style of title and data.
- &check_style($subject, $body);
-
- # Write the file and the associated .cap file.
- $byline = "\n[Submitted by: $friendly ($sender)\n $headers{'date'}]\n";
- &write_it();
-
- # Give the user some positive feedback.
- &feedback();
-
- # Normal end.
- exit 0;
-
- #--------------------------------------------------------------------------
- # abend -- mail an error message to the sender and administrator and exit
- #
- # This will alert the administrator even if $sender has not yet been
- # defined...
- #
- # usage: &abend($shortmsg, $longmsg);
- # Global variables used:
- # $body $header $sender $MAIL $subend $subsep $prob_admin
-
- sub abend {
- local($shortmsg, $longmsg) = @_;
- if ($sender && sender !~ /$loopsenders/io) {
- open (MAIL, "| $MAIL $prob_admin '$sender'");
- } else {
- open (MAIL, "| $MAIL $prob_admin");
- }
- print MAIL "Subject: $shortmsg\n\n";
- print MAIL "$longmsg\n$sig\n\n";
- print MAIL "$subsep\n";
- print MAIL "$header";
- print MAIL "$body";
- print MAIL "$subend\n";
- close(MAIL);
- # We'd like to exit here with an error but it confuses sendmail...
- exit 0;
- }
- #--------------------------------------------------------------------------
- # check_auth -- look up user in list of authorized gmailers
- #
- # usage: $target = &check_auth()
- # returns: target directory ($caldir if we are in calendar mode)
- #
- # side effect: forces $sender to lower case
- # global variables used:
- # $calendar $caldir $error_msg $gmailers $auth_msg $sender $target
- # $delete $publiccal
-
- sub check_auth {
- local($auth, $targ, $matchaddr);
-
- # If we are in calendar mode and *not* in delete mode and the
- # "$publiccal" switch is turned on, no further authorization is
- # necessary.
- return ($caldir) if ($calendar && !$delete && $publiccal);
-
- $sender =~ tr/A-Z/a-z/; # ignore case for easy matching
- open (GMAIL, $gmailers) ||
- &abend("Data not accepted for Gopher due to gmail error",
- $error_msg . "Can't open gmailers file $gmailers\n$@");
- while (<GMAIL>) {
- ($matchaddr) = /^(\S*)/;
- $matchaddr =~ tr/A-Z/a-z/; # ignore case
- if ($matchaddr eq $sender) {
- # carve what we want out of the current line
- s/\s*#.*//; # remove comments;
- s/\s+$//; # remove final whitespace;
- s/^\s*\S*\s+//; # remove initial whitespace
- # and sender's address
- if ($calendar) {
- # Look for the "calendar" keyword
- $auth = (/\bcalendar\b/);
- $targ = $caldir;
- } else {
- # Remove the "calendar" keyword
- s/\s*calendar\s*//;
- $auth = $targ = $_;
- }
- last;
- }
- }
- close(GMAIL);
- unless ($auth) {
- if ($calendar) {
- &abend("Not authorized to submit data to Gopher events calendar", $auth_msg);
- } else {
- &abend("Not authorized to submit data to Gopher", $auth_msg);
- }
- }
- return($targ);
- }
- #--------------------------------------------------------------------------
- # check_style -- check to make sure that the style is acceptable
- # (i.e., that the subject and body consist of printable ASCII
- # characters and the lines in the body are all <80 chars wide).
- # Exit with an error message if it is not.
- #
- # usage: &check_style($subject, $body)
-
- sub check_style {
- local($subject, $body) = @_;
- local($line, $okay, $unprintables);
- $unprintables = "[\000-\010\012-\037]";
-
- $okay = 1;
- $okay = 0 if ($subject =~ /$unprintables/o);
- foreach $line (split(/\n/, $body)) {
- if ((length($line) >= 80) || ($line =~ /$unprintables/o)) {
- $okay = 0;
- last;
- }
- }
- &abend("Data not accepted for Gopher: style problems", $style_msg)
- unless $okay;
- }
- #--------------------------------------------------------------------------
- # check_target -- check to make sure target directory is legitimate,
- # exit with an error message if it is not.
- #
- # usage: &check_target($target)
- # Global variables used: @safedir
-
- sub check_target {
- local($target) = @_;
- local($okay, $safe);
-
- $okay = 0;
- # Disallow ".." to keep from climbing up out of @safedir.
- $okay = 0 if ($target =~ m#(^|/)\.\.(/|$)#);
- # Require that $target falls within @safedir.
- $target .= "/";
- SAFELOOP:
- foreach $safe (@safedir) {
- if ($target =~ m#^$safe/#) {
- $okay = 1;
- last SAFELOOP;
- }
- }
- &abend("Data not accepted for Gopher: bad target directory",
- $error_msg . "Bad target directory: $target\n")
- unless $okay;
- }
- #--------------------------------------------------------------------------
- # delete_it -- perform requested deletion of an item in Gopherspace
- #
- # usage: &delete_it()
- # Global variables used:
- # $filename $subject $target
-
- sub delete_it {
- local(@deldata);
-
- # Does the file even exist?
- &abend("Data not deleted from Gopher due to error",
- $del_err_msg . "File does not exist: $target/$filename\n")
- unless ( -f "$target/$filename" );
-
- # Slurp up a copy of data to be deleted. Yes, this is potentially
- # a big waste of memory. We should probably copy it or move it
- # instead (maybe even keep a backup), but we're feeling simple-minded
- # today.
- open (DATA, "< $target/$filename");
- @deldata = <DATA>;
- close(DATA);
-
- # Nuke it, and its .cap file too.
- unlink("$target/.cap/$filename");
- &abend("Data not deleted from Gopher due to error",
- $del_err_msg . "Could not delete file $target/$filename\n$@")
- unless (unlink("$target/$filename"));
-
- # Success -- give positive feedback and exit.
- open (MAIL, "| $MAIL $debug_admin '$sender'");
- print MAIL "Subject: Data deleted from Gopher: \"$subject\"\n\n";
- print MAIL "$del_ack_msg\n$sig\n";
- print MAIL "$delsep\n";
- print MAIL "Title: $subject\n";
- print MAIL "File: $target/$filename\n\n";
- print MAIL "@deldata";
- print MAIL "$delend\n\n";
- print MAIL "$subsep\n";
- print MAIL "$header";
- print MAIL "$body";
- print MAIL "$subend\n";
- close(MAIL);
- exit(0);
- }
- #--------------------------------------------------------------------------
- # Subroutine expand
- # expand a line (To, Cc, etc.) into a list of addressees.
- #
- # [Borrowed with thanks from the "audit.pl" package by Martin Streicher
- # (strike@convex.com), revision 1.9, 92/05/01.]
- #
- sub expand {
- local($_) = @_;
- local(@fccs) = ( );
-
- return(@fccs) if /^$/;
-
- for (split(/\s*,\s*/)) {
- s/.*<([^>]+)>.*/$1/;
- s/@.*//;
- s/.*!//;
- s/\(.*\)//;
- s/\s//g;
- push(@fccs,$_) unless $seen{$_}++;
- }
-
- return(@fccs);
- }
- #--------------------------------------------------------------------------
- # feedback -- mail the accepted item back to the user
- # (and to the $debug_admin, if defined)
- #
- # usage: &feedback()
- # Global variables used:
- # $accept_msg $body $byline $diclaimer $debug_admin $filename
- # $header $MAIL $sender $subend $subsep $target
-
- sub feedback {
- open (MAIL, "| $MAIL $debug_admin '$sender'");
- print MAIL "Subject: Data submitted to Gopher: \"$subject\"\n\n";
- print MAIL "$accept_msg\n$sig\n";
- print MAIL "$subsep\n";
- print MAIL "Title: $subject\n";
- print MAIL "File: $target/$filename\n\n";
- print MAIL "$header";
- print MAIL "$body";
- print MAIL "$byline";
- print MAIL "$disclaimer\n" if ($disclaimer);
- print MAIL "$subend\n";
- close(MAIL);
- }
- #--------------------------------------------------------------------------
- # normalize -- convert a title to something good for a filename
-
- sub normalize {
- local($str) = @_;
- $str =~ s/\s/_/g; # change white space to _
- $str =~ tr/\/&\\/+/; # change ands and slashes to +
- $str =~ tr/#%+,\-.0-9:;=@A-Z[]_a-z~/#/c; # change trouble to #
- $str;
- }
- #--------------------------------------------------------------------------
- # parse_delete -- see if the subject line specifies a deletion request
- #
- # Check whether the subject line begins with "delete" or "DELETE".
- # If not, return 0; if so, remove the "delete" keyword from the $subject
- # variable and return 1.
- #
- # usage: $delete = &parse_delete()
- # Global variables used: $subject
-
- sub parse_delete {
- local($firstword, $rest);
- ($firstword, $rest) = split(/\s+/, $subject, 2);
- $firstword =~ tr/A-Z/a-z/;
- if ($firstword eq "delete") {
- $subject = $rest;
- return 1;
- }
- return 0;
- }
- #--------------------------------------------------------------------------
- # parse_date -- parse a date on the subject line
- #
- # This has a side effect: it inserts a weekday into $subject.
- # It also abends with a message in case of error.
- #
- # We try to be flexible in parsing dates. Here are some formats accepted:
- # 92-12-30: This is the preferred format
- # 92/12/30 : (Wed) : But we can handle other separators and a weekday
- # 1992-12-30: We accept the year with or without the century
- # 1-1-1 This is a minimalist January 1, 2001
- #
- # These will all result in a new subject like this:
- # 1992-12-30 (Wed): The way things will look in Gopher
- #
- # usage: &parse_date()
- # Global variables used: $caldir $caldir_by_date $date_msg $subject $target
-
- sub parse_date {
- local($date, $gooddate, $yy, $mm, $dd, $title);
- $gooddate = 0;
- if ($subject =~ /^\s*(\d?\d?\d?\d)\D(\d?\d)\D(\d?\d)\s*:?\s*(.*)/) {
- $year = $1;
- $mm = $2;
- $dd = $3;
- $title = $4;
- }
-
- # Force the portions of the date into (at least) two-digit form.
- $year = "0" . $year if (length($year) == 1);
- $mm = "0" . $mm if (length($mm) == 1);
- $dd = "0" . $dd if (length($dd) == 1);
-
- # Add a century if it is missing.
- if ($year < 100) {
- if ($year > 70) {
- # We're in the waning years of the 20th century
- $year += 1900;
- } else {
- # You mean somebody's still using this program?
- $year += 2000;
- }
- }
-
- # Don't accept ancient history or Martian calendars
- &abend("Data not accepted for Gopher: bad date", $date_msg)
- unless ($year >= 1970 && $mm >= 1 && $mm <= 12 &&
- $dd >= 1 && $dd <=31);
-
- # Discard a weekday if one followed the date on the subject line.
- # Note the final whitespace in the pattern: we don't want to mess up
- # a subject like "93-06-01 Wedding bells for Sarah and Jim"!
- $title =~ s/^\(?(Mon|mon|Tue|tue|Wed|wed|Thu|thu|Fri|fri|Sat|sat|Sun|sun)\)?\s*:?\s+//;
-
- # Set the global $subject and $target.
- $date = "$year-$mm-$dd";
- $weekday = &weekday($year, $mm, $dd);
- $subject = "$date ($weekday): $title";
- }
- #--------------------------------------------------------------------------
- # Subroutine parse_email_address
- # Parse an email address into address, from, organization
- # address is full Internet address, from is just the login
- # name and organization is Internet hostname (without final domain)
- #
- # [Borrowed with thanks from the "audit.pl" package by Martin Streicher
- # (strike@convex.com), revision 1.9, 92/05/01.]
- #
- sub parse_email_address {
- local($_) = @_;
- local($friendly, $address, $from, $organization);
-
- $organization = "local";
- $friendly = "unknown";
-
- # From: Disk Monitor Daemon (/usr/adm/bin/dfbitch) <daemon@hydra.convex.com>?
-
- s/^\s*//;
- s/\s*$//;
- if (/(.*)\s*<[^>]+>$|<[^>]+>\s*(.*)$/) {
- $friendly = $+;
- $friendly =~ s/\"//g;
- } elsif (/\(([^\)]+)\)/) {
- $friendly = $1;
- };
-
- s/.*<([^>]+)>.*/$1/;
- s/\(.*\)//;
- s/\s*$//;
- $address = $_;
-
- s/@.*//;
- s/%.*//;
- s/.*!//;
- s/\s//g;
- $from = $_;
-
- $_ = $address;
- tr/A-Z/a-z/;
- if (/!/ && /@/) {
- s/\s//g;
- s/!.*//;
- $organization = $_;
- } elsif (/!/) {
- s/\s//g;
- s/![A-Za-z0-9_@]*$//;
- s/.*!//;
- s/\..*//;
- $organization = $_;
- } elsif (/@/) {
- s/.*@//;
- s/\s//g;
- if (! /\./) {
- $organization = "unknown";
- } else {
- if (/\.(com|edu)$/) {
- s/\.[A-Za-z0-9_]*$//;
- s/.*\.//;
- } else {
- s/\.[A-Za-z0-9_]*$//;
- s/\.[A-Za-z0-9_]*$//;
- s/.*\.//;
- };
- $organization = $_;
- };
- };
-
- return ($friendly, $address, $from, $organization);
- };
- #--------------------------------------------------------------------------
- # Subroutine parse_message
- # Parse a message into headers, body and special variables
- #
- # [Borrowed with thanks from the "audit.pl" package by Martin Streicher
- # (strike@convex.com), revision 1.9, 92/05/01.]
- #
- sub parse_message {
- local(*INFILE) = @_;
-
- $/ = ''; # read input in paragraph mode
- %headers = ( );
- @received = ( );
-
- $header = <INFILE>;
-
- $* = 1;
- while (<INFILE>) {
- s/^From />From /g;
- $body = "" if !defined($body);
- $body .= $_;
- };
- $/ = "\n";
- $* = 0;
-
-
- ;# -----
- ;# $sender comes from the UNIX-style From line (From strike...)
- ;#
- ($sender) = ($header =~ /^From\s+(\S+)/);
-
-
- ;# -----
- ;# fill out the headers associative array with fields from the mail
- ;# header.
- ;#
- $_ = $header;
- s/\n\s+//g;
- @lines = split('\n');
- for ( @lines ) {
- /^(\w*):\s*(.*)/ && do {
- $mheader = $1;
- $mheader =~ tr/A-Z/a-z/;
- if (($mheader eq "cc" || $mheader eq "to") && $headers{$mheader}) {
- $headers{$mheader} .= ", $2";
- } elsif ($mheader eq "received") {
- push(@received, $2);
- } else {
- $headers{$mheader} = $2;
- };
- };
- }
- @received = reverse(@received);
-
-
- ;# -----
- ;# for convenience, $subject is $headers{'subject'} and $precedence is
- ;# $headers{'precedence'}
- ;#
- $subject = $headers{'subject'};
- $subject = "(No subject)" unless $subject;
- $subject =~ s/\s+$//;
- $precedence = $headers{'precedence'};
-
-
- ;# -----
- ;# $from comes from From: line. $address is their email address.
- ;# $organization is their site. for example, strike@pixel.convex.com
- ;# yields an organization of convex.
- ;#
- $_ = $headers{'from'} ||
- $headers{'resent-from'} ||
- $headers{'sender'} ||
- $headers{'resent-sender'} ||
- $headers{'return-path'} ||
- $headers{'reply-to'};
-
- if ($_ eq "") {
- $from = $address = $organization = "unknown";
- return;
- };
-
- ($friendly, $address, $from, $organization) = &parse_email_address($_);
-
- ;# -----
- ;# create arrays for who was on the To, Cc lines
- ;#
- @to = &expand($headers{'to'});
- push(@to, &expand($headers{'apparently-to'}));
- @cc = &expand($headers{'cc'});
- }
- #--------------------------------------------------------------------------
- # weekday -- given a date, return the three-letter name of a weekday
- #
- # usage: &weekday($year, $mm, $dd)
-
- sub weekday {
- local($year, $mm, $dd) = @_;
- local($datestr);
- $year -= 1900; # tz structure expects years - 1900
- $mm -= 1; # tz struct expects months to be 0-11;
- $datestr = &ctime(&timelocal(1, 1, 1, $dd, $mm, $year, "", "", 0));
- return(substr($datestr, 0, 3));
- }
- #--------------------------------------------------------------------------
- # write_it -- write the data to Gopherspace (along with a .cap file)
- #
- # usage: &write_it()
- # Global variables used:
- # $body $byline $disclaimer $error_msg $filename $subject $target
- #
- # SIDE EFFECT: We chdir() to the $target directory.
- # Thanks to Fred Barrie (barrie@futique.scs.unr.edu) for supplying the fix
- # for a peculiar perl bug: it can't open a file with a fully-defined path
- # longer than 64 characters.
-
- sub write_it {
-
- chdir($target) ||
- &abend("Data not accepted for Gopher due to gmail error",
- $error_msg . "Can't chdir to directory $target\n$@");
- open (FILE, "> $filename") ||
- &abend("Data not accepted for Gopher due to gmail error",
- $error_msg . "Can't open file $target/$filename\n$@");
- print FILE "$subject\n\n";
- print FILE $body;
- print FILE "$byline";
- print FILE "$disclaimer\n" if ($disclaimer);
- close(FILE);
-
- # Make a .cap file only if one is needed.
- if ($subject ne $filename) {
- unless (-d ".cap") {
- mkdir(".cap", 0755);
- }
- unless (open (FILE, "> .cap/$filename")) {
- # Can't create .cap file -- complain and clean up
- unlink("$filename");
- &abend("Data not accepted for Gopher due to gmail error",
- $error_msg . "Can't open file $target/.cap/$filename\n$@");
- }
- print FILE "Name=$subject\n";
- close(FILE);
- }
- }
- #--------------------------------------------------------------------------
-
- # end of gmail script
-