<%
use CGI::Carp qw(fatalsToBrowser);
# use strict;
# use warnings;
# no warnings qw(uninitialized);
$PAGE{dynamic}++;
use SE::Travel::Constants;
require SE::Travel::Betriebe;
require SE::Travel::Vorlage;
require SE::Travel::Lib;
use vars '%VERMIETER';
my $out;
my $google_data;
my $template_format = $in{format} eq "xml" ? "xml" : "html";
$in{showall} = 1 if $in{format} eq "xml";
use SE::Lib::Lang;
SE::Lib::Lang->new("_travel");
SE::Lib::Lang->new("_travel-search");
$value[40] = _fix_liste($value[40]);
$value[40] =~ s/^0,//g;
$value[40] =~ s/,0$//g;
$USER{mandanten} = $value[40];
$SE{mandanten_vorlage} = $value[46];
$SE{mandanten_vorlage} = $SE{mandant} unless $SE{mandanten_vorlage};
$in{filter_mandanten} = $value[40] unless $in{filter_mandanten};
$in{filter_mandant} = $value[46];
my $mandant_platform = $in{filter_mandant};
$mandant_platform = &_mandanten_bilder($mandant_platform);
require SE::Travel::Merkmale;
langMerkmale( sprache => $vorhanden->{sprache} );
my %old_in = %in;
# Alternative Daten
if ($in{von_tag} > 0) {
$SE::in{feld_von_epoche} = timelocal(0,0,12,$in{von_tag},$in{von_monat}-1,$in{von_jahr});
}
if ($in{bis_tag} > 0) {
$SE::in{feld_bis_epoche} = timelocal(0,0,12,$in{bis_tag},$in{bis_monat}-1,$in{bis_jahr});
}
$TEMP{sonde} = $in{feld_von_epoche};
# Vereingestellter Betrieb
$in{gid} = $value[27] if $value[27] && $in{gid} eq "";
if ( $in{gid} eq "" && $in{lid} ) {
require SE::Travel::Betriebe;
my $betrieb = getBetriebe(
nr => $in{lid},
mandanten => $in{filter_mandant},
DB_readonly => 1,
);
$in{gid} = $betrieb->{id};
}
# Bei der Stichwortsuche stehen manchmal -Defaul-Werte drin, die natürlich kein
# Sucherlebnis erzeugen dürfen...
$in{stichwortsuche} = $in{stichwortsuche} || $in{query}; # sitesearch
$in{stichwortsuche} = "" if $in{stichwortsuche} =~ /Stichwortsuche|Suchbegriff|Hotelname|Keyword|Search|Vermietername|Suche/
|| ($LANG{stichwortsuche} ne "" && $in{stichwortsuche} eq $LANG{stichwortsuche})
|| ($LANG{Stichwortsuche} ne "" && $in{stichwortsuche} eq $LANG{Stichwortsuche})
|| ($in{"stichwortsucheIgnore"} ne "" && $in{"stichwortsuche"} eq $in{"stichwortsucheIgnore"});
# Ausgewählte Merkmale so für Checkboxen generieren, dass deren Zustände leicht erkannt werden können
$TEMP{merkmale} = "";
foreach (split /\0|\|/, $in{merkmale}) {
$TEMP{merkmale}->{$_} = "checked";
}
$TEMP{zimmermerkmale} = "";
foreach (split /\0|\|/, $in{zimmermerkmale}) {
$TEMP{zimmermerkmale}->{$_} = "checked";
}
my $template_searchform = $value[3] ? $value[3] : "default";
# Seite
$in{do} = $value[34] unless $in{do};
my $seite = $in{do};
#$seite =~ s/^(info|belegung|zimmer|lage|pauschalen|buchung|buchung2)$/$1/g;
$seite = "info" unless $seite;
# Vorlagen je nach dem welche da sind sonnst default
my %templates = ();
my $template_match = $value[37] || $template_searchform;
$templates{error_none} = &html_template_exists("_travel/_error_none_${template_match}.$template_format") ? $template_match : '';
for my $key ( "detail_$seite", 'detail_header', 'detail_footer', 'header', 'match', 'matchzimmer', 'footer' ) {
$templates{ $key } = &html_template_exists("_travel/_${key}_${template_match}.$template_format") ? $template_match : 'default';
}
# Alle Attribute der _travel Vorlage (wg. Speichern von Sessions)
my @session_saveme = (
filter_zimmertyp, feld_von_epoche, feld_bis_epoche, off_zeitraum,
intage, filter_pauschalen, nodate,
merkmale,
filter_merkmale,
zimmermerkmale,
filter_zimmermerkmale,
sortmode,
typ_zimmer,
filter_etage,
filter_online, filter_gruppen, filter_gruppen_oder, filter_kategorie, filter_ortsteil,
filter_personen, anzahl_zimmer, filter_schlafraeume, filter_betriebsart,
anzahl_zimmer_2,
typ_zimmer_2,
filter_zimmertyp_2,
filter_personen_2 ,
filter_raeume_2 ,
filter_schlafraeume_2 ,
filter_etage_2 ,
filter_zimmersterne2,
filter_raeume_schlafraeume_2,
filter_schlafraeume_min_2,
filter_schlafraeume_min,
filter_verpflegung, filter_zimmertyp_raeume,
filter_orte, filter_ort, filter_ort2, filter_sterne, stichwortsuche, p, filter_zimmerfewo,
ort_mandant, filter_betriebsart,
);
# Ausführen um die Voreinstellungen zu kennen
my %backup_in = %in;
my $nothing_null = &html_insert("::_travel/_searchform_${template_searchform}.$template_format"); # eval...
%in = %backup_in;
# Ergebnisse laden
# // Session laden . . . . . . . . . . . . . . . . . . . . . . . . . . . .
$out .= qq( BREAKPOINT #1
TRAVEL{nosticky} = $TRAVEL{nosticky}
) if $in{debug_saveme};
$out .= qq(
) if $in{google} == 1;
my $session_pageid;
if ( (! $value[1]) && $in{stichwortsuche} eq "" && ! $TRAVEL{nosticky} && $in{format} ne "xml" ) {
require "se_cookie.pl";
unless ($in{startsearch}) {
if ($SE{cookies}->{travel_sessionid} ne "") {
my $travel_sessionid = $SE{cookies}->{travel_sessionid};
if (-s "${appdir}/_temp/_session_${travel_sessionid}.txt") {
if ($in{travel_reset}) {
unlink "${appdir}/_temp/_session_${travel_sessionid}.txt";
} else {
my @session_data = &file_load("${appdir}/_temp/_session_${travel_sessionid}.txt", "SILENT");
my ($created,$usepage) = split(/\t/,shift @session_data);
$session_pageid = $usepage;
my %backup = %in;
my @saveme;
foreach my $key (@session_data) {
my @keypair = split /\t/,$key;
# nur die die im remember sind, refereshen
# bei rücksprung aus detailansicht, alle refreshen
if ($TRAVEL{remember} =~ /\b$keypair[0]\b/
|| $TRAVEL{remember} eq ""
|| $keypair[0] eq "p"
|| ( $ENV{QUERY_STRING} !~ /\b$keypair[0]=/ && $TRAVEL{remember} =~ /\b$keypair[0]\b/ || $TRAVEL{remember} eq "" )
|| $ENV{HTTP_REFERER} =~ /gid=\d/) {
unless ($in{$keypair[0]}) {
push @saveme, qq( $keypair[0] <= $keypair[1]);
$in{$keypair[0]} = $keypair[1];
} else {
push @saveme, qq( NOT: unless.... ($in{$keypair[0]}) ... $keypair[0] <= $keypair[1]);
}
$TRAVEL{session} = $travel_sessionid;
}
}
# wenn zu einer neuen suche gewechselt wird, sollte die Stichwortsuche wieder leer sein
$in{stichwortsuche} = "" if $ENV{QUERY_STRING} !~ /sortmode=/ && $ENV{HTTP_REFERER} !~ /gid=/;
# wenn jemand die sucher erneut startet mit leerer suche, sollte die suche auch verschwinden
$in{stichwortsuche} = "" if $backup{stichwortsuche} eq "";
# Die Seitenzahl muss erhalten bleiben
$in{p} = $backup{p} if $backup{p} > 0;
# %in debuggen...
if ($in{debug_saveme}) {
my $savemedebug; foreach (@saveme) { $savemedebug .= qq($_ ) }; $savemedebug =~ s/\t/=/g;
$out .= qq(
);
}
if ( $in{package_termin} ) {
my ( $package, $v, $b ) = split /:/, $in{package_termin};
$in{filter_packages} = $package;
$in{feld_von_epoche} = SE::Unixtime($v);
$in{feld_bis_epoche} = SE::Unixtime($b);
}
# Voreinstellungen fixieren falls vorhanden
$in{feld_von_epoche} = $value[10] if $value[10] > 100 ;
$in{feld_bis_epoche} = $value[11] if $value[11] > 100 ;
$in{inzeit} = $value[12] if $value[12];
$in{off_zeitraum} = $value[13] unless defined $in{off_zeitraum};
$in{filter_pauschalen} = $value[14] if $value[14];
$in{filter_online} = $value[15] if $value[15];
$in{filter_kategorie} = $value[16] if $value[16];
$in{filter_kategorie} =~ s/\0/,/g;
$in{filter_orte} = $value[17] if $value[17] && ( $in{filter_orte} eq "" || $value[17] !~ /$in{filter_orte}/ );
$in{filter_ortsteil} = $value[18] if $value[18] && ( $in{filter_ortsteil} eq "" || $value[18] !~ /$in{filter_ortsteil}/ );
$in{filter_strasse} = $value[44] if $value[44];
$in{filter_gruppen} = $value[19] if $value[19] && !defined $in{filter_gruppen};
$in{filter_gruppen_oder} = $value[52] if $value[52] && !defined $in{filter_gruppen_oder};
$in{filter_sterne} = $value[35] if $value[35];
$in{filter_buchbar} = $value[39] unless defined $in{filter_buchbar};
$in{filter_passiv} = $value[41]; # nur intern zu setzen
$in{nogroup} = 1 if $value[26] =~ /G/; # Grupperung der Ergebnisse Unterdrücken
$in{no_match_header_footer} = 1 if $value[26] =~ /H/; # Header /Footer der Trefferliste Unterdrücken
$in{filter_packages} = $value[47] unless $in{filter_packages};
$in{freimelde_tage} = $value[48] if $value[48];
$in{merkmale} .= "\0" . $value[30] if $value[30];
# Oder
$value[36] =~ s/\0/:/g if $value[36];
$in{merkmale} .= "\0" . $value[36] if $value[36];
# Doppelte Merkmale eliminieren
{
my %unique_merkmale;
foreach (split /\0/, $in{merkmale}) {
$unique_merkmale{"$_"}++ if $_;
}
$in{merkmale} = join "\0", keys %unique_merkmale;
}
$in{stichwortsuche_allow_merkmale} = 1 if $value[30]; # Vorläufig, das erlaubt das Filtern nach Merkmalen während einer Suche
$in{stichwortsuche_kombiniert} = 1 if $value[53]; # Erlaubt das Filtern nach dem Zeitraum während einer Stichwortsuche
$in{zimmermerkmale} .= "\0" . $value[31] if $value[31];
# Bei Pauschalenanzeige ohne Formular, groupmode erzwingen
$in{groupmode} = "pauschalen" if $value[14] eq "1" || $value[20] eq "1";
# Zimmer zeigen
$in{groupmode} = "zimmer" if $value[33] eq "1";
$in{groupmode} = "zimmertyp" if $value[33] eq "2";
# Sortiermodus vorgeben
$in{sortmode} = $value[22] if $in{sortmode} eq "" && $value[22];
# Anreisetage
$in{off_anreisetage} = $value[38] unless $in{off_anreisetage} ne "";
#
# Suchformular einblenden und nichts tun, wenn kein QUERY_STRING
if (! $value[1]
&& ! ($ENV{HTTP_REFERER} =~ /gid=/ && $session_pageid eq $PAGE{id} && $session_pageid ne "")
&& ( $ENV{QUERY_STRING} !~ /sortmode/ && $in{format} ne "xml")
&& $in{gid} !~ /^\d+$/
&& ! $value[25]) {
$out .= &html_insert("::_travel/_searchform_${template_searchform}.$template_format");
} else {
if ( $ENV{QUERY_STRING} =~ /sortmode|gid=|lid=|psession=/ || $in{p} > 0 ) {
# Vorhergehende Blöcke löschen oder Anzeigen je nach dem
$PAGE{flush} = 1 if $value[26] =~ /A/;
$PAGE{stop} = 1 if $value[26] =~ /B/;
}
# ------------------------------------------------------------------------
#
# Ein Betrieb im Detail
#
#
if ($in{gid} =~ /^\d+$/) {
require "se_mysql.pl";
my $dbh = connectDatenbank( server => connectMandanten(), datentyp => "Travel::Vorlage" );
if ( $SE{modules} =~ /travel/ ) {
if (($ENV{HTTP_REFERER} !~ /lid=|gid=/ && !$in{format}) || $in{_travel_redirect}) { # nur wenn von ausserhalb aufgerufen
my ($monat,$jahr) = (localtime(time))[4,5]; $jahr+=1900; $monat++;
# Zugriffe zählen bzw. Gerechtigkeits-Koeffizient
# ggf. travel_stats anlegen
$in{gn} = 20 if $in{gn} > 20;
$in{gn} = 1 if $in{gn} < 0;
# ALT
$in{gn} = $in{gn} >= 1 && $in{gn} < 20 ? (1-$in{gn}/20) : 0.5;
#$in{gn} = ( 1 / ( $in{gn} ) ) * ( 1 / ( $in{gn} ) );
my $sql_set;
if ( $in{_travel_redirect} ) {
# Vorläufig ohne Prüfung, wurde nicht mehr gezählt....
$sql_set = qq( links = links + 1 );
# $sql_set = qq( links = links + IF(lastip="$ENV{REMOTE_ADDR}",0,1) );
} else {
$sql_set = qq( gerechtigkeit = gerechtigkeit + IF(lastip="$ENV{REMOTE_ADDR}",0,"$in{gn}"),
visits = visits + IF(lastip="$ENV{REMOTE_ADDR}",0,1),
lastip = "$ENV{REMOTE_ADDR}" );
$sql_set = qq( gerechtigkeit = gerechtigkeit + 1,
visits = visits + 1,
lastip = "$ENV{REMOTE_ADDR}" )
if ($ENV{REMOTE_ADDR} =~ /62\.146\.116\./ && $SE{app} eq "bodenseeferien.dreamway.net" && $in{gn} )
}
# aufzeichnen
breakpoint qq(
INSERT INTO
travel_stats
SET
$sql_set,
travel_stats.gid = ?,
travel_stats.jahr = ?,
travel_stats.monat = ?,
werbeaktion = ?,
mandant = ?
ON DUPLICATE KEY UPDATE
$sql_set
) , $in{filter_mandant}, SE::Mandanten() if $in{bmdebug} == 1;
if ( $ENV{REMOTE_HOST} !~ /dreamway|oberstdorf/ ) {
if ( $ENV{HTTP_REFERER} ne "" || ($ENV{REMOTE_ADDR} =~ /62\.146\.116\./ && $SE{app} eq "bodenseeferien.dreamway.net" && $in{gn} ) ) {
if ( $stats->{lastip} ne $ENV{REMOTE_ADDR} || $in{_travel_redirect} || ($ENV{REMOTE_ADDR} =~ /62\.146\.116\./ && $SE{app} eq "bodenseeferien.dreamway.net" && $in{gn} ) ) {
my $sql_new = qq(
INSERT INTO
travel_stats
SET
$sql_set,
travel_stats.gid = ?,
travel_stats.jahr = ?,
travel_stats.monat = ?,
werbeaktion = ?,
mandant = ?
ON DUPLICATE KEY UPDATE
$sql_set
);
my $sth_new = $dbh->prepare($sql_new);
$sth_new->execute(
$in{gid}, $jahr, $monat,
$value[42] || 0,
( $in{filter_mandant} || SE::Mandanten() )
) || &mysql_error($sth_new);
$sth_new->finish;
}
}
}
}
}
# Stammdaten laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
%VERMIETER = ();
require SE::Travel::Betriebe;
my $treffer = getBetriebe(
id => $in{gid},
mit_pauschalen => 1,
plattform => $mandant_platform,
DB_readonly => 1,
mandant => $SE{mandanten_vorlage}
);
%VERMIETER = %{$treffer};
require SE::Lib::Sprachen;
my $vtext = getSprachen( nr => 1, objekt => $in{gid}, DB_readonly => 1, );
$VERMIETER{text} = $vtext->{ $PAGE{language} } if $PAGE{language} ne "de";
$VERMIETER{sterne_text} = $TRAVEL{sterne}->{$treffer->{sterne}};
$VERMIETER{kategorie_text} = $TRAVEL{kategorien}->{$treffer->{kategorie}};
#temp. bugfix bei gesyncten betrieben
$VERMIETER{sterne} = $VERMIETER{sterne_cache};
# Merkmale dieses Betriebs laden
require SE::Travel::Merkmale;
my @merkmale_betrieb = getMerkmale(
mandant => $mandant_platform,
betrieb => $VERMIETER{gid},
verwendung => "betrieb",
online => 1,
DB_readonly => 1,
);
my @aktive_merkmale;
foreach my $m ( @merkmale_betrieb ) {
push @aktive_merkmale, $m->{id};
$VERMIETER{merkmale_byid}[$m->{id}] = 1;
}
require SE::Lib::Sprachen;
my $sprachen = getSprachen(
objekt => \@aktive_merkmale,
nr => [2,3,4],
sprache => $PAGE{language},
DB_readonly => 1,
);
my @merkmale;
my @merkmale2;
my $merkmale_id;
foreach my $m ( @merkmale_betrieb ) {
my $name = $sprachen->{$PAGE{language}}->{$m->{id}}->{2} ? $sprachen->{$PAGE{language}}->{$m->{id}}->{2} : $m->{name};
my $gruppe = $sprachen->{$PAGE{language}}->{$m->{id}}->{3} ? $sprachen->{$PAGE{language}}->{$m->{id}}->{3} : $m->{gruppe};
my $text = $sprachen->{$PAGE{language}}->{$m->{id}}->{4} ? $sprachen->{$PAGE{language}}->{$m->{id}}->{4} : $m->{text};
push @merkmale, $name;
push @merkmale2, {
name => $name,
gruppe => $gruppe,
text => $text
}
}
@merkmale = sort @merkmale;
@merkmale2 = sort { $a->{gruppe} cmp $b->{gruppe} || $a->{name} cmp $b->{name} } @merkmale2;
$VERMIETER{merkmale} = "";
foreach my $merkmal ( @merkmale ) {
$VERMIETER{merkmale} .= "$merkmal ";
}
$VERMIETER{merkmale_arrayref} = \@merkmale;
$VERMIETER{merkmale_hashref} = \@merkmale2;
# $VERMIETER{merkmale_byid} = \@aktive_merkmale;
$TRAVEL{database} = connectDatenbank( server => connectMandanten(), readonly => 1, datentyp => "Travel::Vorlage" );
my $optional = getBetriebe(
id => $in{gid},
plattform => $mandant_platform,
DB_readonly => 1,
);
$TRAVEL{maximg} = $optional->{maximg};
$TRAVEL{maximg2} = $optional->{maximg2};
$TRAVEL{user} = $optional->{user};
$TRAVEL{optional} = $optional->{optional};
# Email senden bei Anfrage
my $vermieter_mail = $VERMIETER{email} ? $VERMIETER{email} : $VERMIETER{emailadresse};
my $vermieter_bccmail;
# OATS
$vermieter_mail = "servicecenter\@oats.de" if $SE{app} eq "oberallgaeu-ferien.de";
$vermieter_bccmail = "buchung\@oats.de" if $SE{app} eq "oberallgaeu-ferien.de";
if ( $in{travel_action} eq "send" && $VERMIETER{fax} =~ /\d{3}/
&& $ENV{HTTP_REFERER} !~ /travel_action=send/ && $TRAVEL{optional} =~ /F/ ) {
if ($in{as_chksum}) {
require SE::Lib::Misc;
if (&check_antispam() != 1 || $ENV{HTTP_REFERER} == "" ) {
&antispam_message();
}
}
# FormToFax
require SE::Lib::Faxgateway;
import SE::Lib::Faxgateway;
require Encode;
&getFaxUserKonto($VERMIETER{gid}, 'travel' ); # Verschickt eine mail an support@dreamway, wenn Konto aufgebraucht ist
if ( &hasFaxgateway() ) {
require SE::Lib::Pdf; # PDF API
my $pdf=SE::Lib::Pdf->new( undef, [595,842], [30, 740] );
$pdf->se_text(Encode::encode("iso-8859-1","Buchungsanfrage Quartiersuche $SE{app}"), -25, 35, 790, 'arial_bold', 18);
$pdf->se_text(Encode::encode("iso-8859-1",'Anfrage für:'), -13, 35, 750, 'arial', 10);
my $anschrift = Encode::encode("iso-8859-1",qq( $VERMIETER{betriebsname}
$VERMIETER{vorname} $VERMIETER{nachname}
$VERMIETER{strasse} $VERMIETER{hausnummer}
$VERMIETER{plz} $VERMIETER{ort}
Telefon $VERMIETER{telefonvorwahl} $VERMIETER{telefon}
Telefax $VERMIETER{faxvorwahl} $VERMIETER{fax} ));
my ($tx,$ty) = $pdf->se_textbox($anschrift,150,750,400,'arial',10);
foreach my $key (sort keys %in) {
if ($key =~ /^travel__\w+_/) {
my $key2 = $key;
$key2 =~ s/^travel__\w+_(.+)$/$1/;
$key2 =~ s/_/ /;
$pdf->se_text(Encode::encode("iso-8859-1","$key2:"), -13, 35, $ty, 'arial', 10);
($tx,$ty) = $pdf->se_textbox(substr(Encode::encode("iso-8859-1",$in{$key}),0,500),150,$ty,400,'arial',10); # max 500 Zeichen... damit keine mega Fax verschickt werden
}
}
my $faxnummer = $VERMIETER{faxvorwahl} . $VERMIETER{fax};
$faxnummer =~ s/[^\d]//g;
my $fax = SE::Lib::Faxmail->new(
To => $faxnummer,
PDF => $pdf->stringify
);
$fax->send;
&logSendFax ( $fax, gid => $VERMIETER{gid} );
&setFaxUserKonto( -1, $VERMIETER{gid}, 'travel' );
}
#&http_header;
} elsif ($in{travel_action} eq "send" && $ENV{HTTP_REFERER} !~ /travel_action=send/ && $vermieter_mail =~ /\@/) {
if ($in{as_chksum}) {
require SE::Lib::Misc;
if (&check_antispam() != 1) {
&antispam_message();
}
}
require MIME::Lite;
my $body;
my $body_txt;
my $antwortemail = $in{travel__6_Email} =~ /\@/ ? $in{travel__6_Email} : qq(quartiersuche\@$SE{app});
my $msg = MIME::Lite->new(
From => "$antwortemail",
To => "$vermieter_mail",
Bcc => "$vermieter_bccmail",
Type => "multipart/mixed",
Subject => "Buchungsanfrage Quartiersuche $SE{app}"
);
# --- Inhalt generieren
my $adresse = qq($VERMIETER{betriebsname}
$VERMIETER{vorname} $VERMIETER{nachname}
$VERMIETER{strasse} $VERMIETER{hausnummer}
$VERMIETER{plz} $VERMIETER{ort}
Telefon $VERMIETER{telefonvorwahl} $VERMIETER{telefon}
Telefax $VERMIETER{faxvorwahl} $VERMIETER{fax}
);
$body .= qq(
Der Absender dieser Anfrage hat keine Email angegeben, bitte kontaktieren Sie den Gast telefonisch oder auf dem Postweg. Bitte antworten Sie nicht direkt auf diese Email, da Ihre Antwort dann an die Adresse $antwortemail gesandt wird.
);
$body_txt .= qq(-- Wichtiger Hinweis ---------------------------------------------------
Der Absender dieser Anfrage hat keine Email angegeben,\n
bitte kontaktieren Sie den Gast telefonisch oder auf dem Postweg.\n
Bitte antworten Sie nicht direkt auf diese Email, da Ihre Antwort\n
dann an die Adresse $antwortemail gesandt wird.\n\n ) unless $in{travel__6_Email} =~ /\@/;
$adresse =~ s/ //g;
$adresse =~ s/
//g;
$adresse =~ s/^\s+//gi;
$body_txt .= qq(Anfrage für
-------------------------------------------------
$adresse
\n
Inhalt der Anfrage
-------------------------------------------------\n);
foreach my $key (sort keys %in) {
if ($key =~ /^travel__\w+_/) {
my $key2 = $key;
$key2 =~ s/^travel__[A-Za-z0-9]+_(.+)$/$1/;
$key2 =~ s/_/ /;
$body .= qq(