#!/usr/bin/perl
#
# konffannut ja ruotsintanut 9.4.2001 hingo@cc.hut.fi:
# - Ohjelman virheilmoitukset ja muut tulostukset ruotsinnettu.
# - Linkit yms muutettu niin että sopivat sivun rakenteeseen.
# - Alun "### Konfigurointi" -osio muutettu sopivaksi
# 13.5.2001:
# - Lisätty osio joka tarkistaa että osoite löytyy articles.txt tiedostosta
#   (eli ei lähetetä postia minne tahansa!)
#
#
# Tik-111.361 Hypermediadokumentin laatiminen
# CGI-mail: Erittäin yksinkertainen CGI/sähköposti-yhdyskäytävä
#
# (c) 1998-2000 Martti Rahkila
# Martti.Rahkila@tcm.hut.fi
#
# Tämä CGI-skripti on erittäin yksinkertainen CGI/sähköposti-yhdyskäytävä,
# joka on tehty Teknillisen Korkeakoulun opintojaksoa Tik-111.361 Hyper-
# mediadokumentin laatiminen varten. Ohjelmaa saa vapaasti käyttää ja
# muokata kurssin puitteissa. Ohjelmaa EI saa (eikä kannata) käyttää muihin tarkoituksiin.
# Martti Rahkila ei vastaa minkäänlaisista vahingoista, mitä tämän ohjelman
# käyttö voi aiheuttaa.
#
# http://www.tcm.hut.fi/hype/
#
# v0.0 19.01.1998
# v1.0 21.01.1998
# v1.1 23.03.1999
# v1.2 24.05.1999
# v1.21 21.02.2000
#
# Seuraavia asioita kannattaa pohtia:
# - miten tätä ohjelmaa voisi parantaa?
# - löydätkö bugeja tai turvallisuusriskejä?

### Konfigurointi:

# sendmail-ohjelman sijainti ja kutsu (kts. man sendmail):
$sendmail = "/usr/lib/sendmail -t -oi";
### mieti seuraavia määrittelyjä
# hingo: oletusarvoisesti maili lähetetään ylläpidolle
# jos lomakkeen mukana tulee "vastaanottaja" niminen kenttä
# vaihdetaan tämä siihen, paitsi jos kentän arvo on "admin" jolloin
# tämä on se mitä tarkoitetaan.
# (Lomakkeen mukana pitäis aina tulla "vastaanottaja".)
$toaddress = "hingo\@cc.hut.fi, ajalkane\@cc.hut.di, kkyykkan\@cc.hut.fi";
#$toaddress = "hingo\@cc.hut.fi";
#defaults
$subject = "Notnätet email";
$server = "hype.tml.hut.fi:2007";
$nexturl = "http://$server/demo/kiitos.php4";

### Pääohjelma

if (&LueData) {
    &LahetaMeili;
} else {
    &Virhe('Det uppstod ett fel vid behandlandet av ditt meddelande. Var vänlig och kontrollera att du fyllt i rutorna korrekt.');
}

exit(0);

### Aliohjelmat:

## &LueData: lukee lomakkeelta saadun syötteen ja palauttaa sen
## assosiatiivisena taulukkona tai arvon false, jos syötettä ei
## ole

sub LueData {
  local (*input) = @_ if @_;
  local ($method, $i, $key, $val);

# millä metodilla ohjelmaa on kutsuttu
  $method = $ENV{'REQUEST_METHOD'};
# luetaan syöte
  if ($method eq "GET") {
      $input = $ENV{'QUERY_STRING'};
  } 
  elsif ($method eq "POST") {
    read(STDIN,$input,$ENV{'CONTENT_LENGTH'});
  }

# separoidaan muuttujat
  @input = split(/[&;]/,$input); 

# url-dekoodataan syöte
  foreach $i (0 .. $#input) {

# +-merkki vastaa välilyöntiä
    $input[$i] =~ s/\+/ /g;

# erotellaan muuttujan nimi ja arvo
    ($key, $val) = split(/=/,$input[$i],2);

# muunnetaan erikoismerkit heksamuodosta
    $key =~ s/%(..)/pack("c",hex($1))/ge;
    $val =~ s/%(..)/pack("c",hex($1))/ge;

# assosioidaan muuttujan nimi ja arvo
# \0 erottaa useammat arvot
    $input{$key} .= "\0" if (defined($input{$key})); 
    $input{$key} .= $val;

  } #foreach

  return scalar(@input); 
}

## &Virhe(): Antaa virheilmoituksen ja keskeyttää ohjelman suorituksen

sub Virhe {
    local($message) = @_;

    print "Content-type: text/html\n\n";
    print <<EOF
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">
<html>
<head>
<title>Ett fel uppstod</title>
</head>
<body bgcolor=\"\#ffffff\">\n
<h1>CGI-mail: Fel!</h1>
<pre>
Det gick inte att skicka meddelandet:
Namn: $fromname
Från: $fromaddress
Till: $toaddress

$message
</pre>
</body>
</html>
EOF
    ;
    exit(1);
}

## &LahetaMeili: Lähettää viestin syötteessä annettuun osoitteeseen
## sendmail-ohjelmalla

sub LahetaMeili {
    local(*input) = @_ if @_;
    local($key,$val);

# hingo: Seuraavaan lisätty $formtoaddress
# luetaan syötteestä tarvittavat arvot
    foreach $key (keys %input) {
	$formtoaddress = $input{'vastaanottaja'},next if ($key eq "vastaanottaja");
	$fromname = $input{'nimi'},next if ($key eq "nimi");
	$fromaddress = $input{'sposti'},next if ($key eq "sposti");
	$subject  = $input{'otsikko'},next if ($key eq "otsikko");
	$data = $data . "$key:\t$input{$key}\n";
	next;
    }

# hingo: Tarkistetaan että $formtoadress kelpaa, eli se on "admin" tai
# diskussionforumista löytyvä osoite.
# Jos se on "admin" tai puuttuu, ei tehdä mitään. Jos se sisältää jotain muuta,
# Katsotaan löytyykö vastaava osoite diskussionsforumista.
# Jos ei löydy, tulostetaan virhe.
    if( $formtoaddress ne "admin" && $formtoaddress ne ""){

      #Tässä vaiheessa on jo selvää että ainakin tarkoitus olisi lähettää postia
      #muuhun kuin default osoitteeseen
      $toaddress = $formtoaddress;

      #Notkartoteketista ei lähetetä postia kuin yhteen osoitteeseen kerrallaan,
      #joten jos $toaddress sisältää pilkkuja se voidaan heti hylätä
      if($toaddress =~ m/.*\,.*/){
        &Virhe('Det är inte tillåtet att skicka till mer än en mottagare.');
      }

      #Haetaan kaikki merkkijonot jotka ovat "<" ja ">" merkkien välissä ja tulkitaan ne 
      #osoitteiksi. Jos <>-merkkejä ei ole yhtään, tulkitaan koko merkkijono pelkäksi osoitteeksi.

      @arrTo = split(/>/, $formtoaddress);
      for($i = $#arrTo; $i >= 0; $i--){
        @foo = split(/</, $arrTo[$i]);
        $arrTo[$i] = $foo[$#foo];
      } 

      #Seuraavaksi yksinkertaisesti tarkistetaan että 
      #osoite löytyy articles.txt tiedostosta. Siitä tiedetään, että osoitteet ovat rivin lopussa.
      #Luetaan koko articles.txt muuttujaan $artFile
      open(ARTICLES, '../articles.txt');
      $artFile = "";
      while($artLine = <ARTICLES>){
        $artFile = $artFile.$artLine;
      }
      #Sitten tarkistetaan, että osoite löytyy sieltä
      for($i = $#arrTo; $i >= 0; $i--){
        if($artFile !~ m/$arrTo[$i]$/m){
          &Virhe('Det är inte tillåtet att skicka till denna mottagaradress.');
        }
      }
    }
#hingo: Tästä jatkuu normaalisti

# varmistetaan, että riittävästi tietoja on annettu
    unless ($toaddress =~ /^.+\@.+/) { &Virhe('Mottagaradressen är felaktig. (Ser inte ut som en email-adress.)');}
    unless ($fromaddress =~ /^.+\@.+/) { &Virhe('Din email-adress är felaktig, du måste fylla i en korrekt e-mail adress.');}
    unless ($fromname) { &Virhe('Ditt namn fattas. Var vänlig gå tillbaka och fyll i ditt namn.')}

# filtteröidäänpäs vähän inputtia, mieti miksi!
    $toaddress =~ tr/[\n\r\;\0]//d;
    $fromname =~ tr/[\n\r\;\0]//d;
    $fromaddress =~ tr/[\n\r\;\0]//d;
    $fromname = substr($fromname,0,100);
    $fromaddress = substr($fromaddress,0,100);
    $subject =~ tr/[\n\r\0]//d;
    $subject = substr($subject,0,100);

# kutsutaan sendmail-ohjelmaa
    open(MAIL,"| $sendmail") || 
	&Virhe('Jag misslyckades med att få igång sendmail-programmet.');

# Lähetetään data
    print MAIL <<EOF;
From: $fromname <$fromaddress>
To: $toaddress
Subject: $subject
X-Mail-Gateway: Hype CGI-mail

$data
EOF
    ;
    close(MAIL);

# palautetaan url
    print "Location: $nexturl\n\n";
}
