#!/usr/bin/perl

# ==========================================================================================
# Copyright (c) 1998-2002 HIS Internet Soft GmbH, info@his-webshop.de. All rights reserved.
# http://www.his-webshop.de/
# ..........................................................................................
# HIS WebShop 2.50 -- Online Shop mit Warenkorbsystem
# Version: 26.03.2002
#
# ----- LIZENZBESTIMMUNG ------
#
# 1. Dieses Programm (HIS WebShop) darf nur unter folgenden Bedingungen eingesetzt
#    werden:
#    (1) Die Internet Domain des Shops muss für das HIS WebShop Shopsystem
#        lizensiert sein (Ausstellung bei: info@his-webshop.de).
#    (2) Eine Lizenz ist immer gültig für nur einen Shop. Werden mehrere Shops
#        unterschiedlicher Firmen auf einer Domain betrieben, so muss für jeden
#        einzelnen Shop das Shopsystem lizensiert werden (Rabatte sind möglich!).
#
#    Der unbegrenzte Einsatz des Shopsystems ist erst nach Eingabe eines Registrier Keys
#    möglich. Ein Registrier Key gilt dabei immer für eine bestimmte Domain.
#    Beim Erwerb einer Lizenz erhalten Sie den gültigen Registrier Key für die Domain.
#    Aktuelle Konditionen zum Erwerb einer Lizenz finden Sie auf der HIS WebShop
#    Homepage: http://www.his-webshop.de/
#
# 2. Der Konfigurations-Teil darf geändert werden. Alle anderen Teile des Quellcodes sind
#    urherberrechtlich geschützt. Eine Änderung bedarf der Einwilligung des Autors.
#
# 3. Die Weitergabe des Programms an Dritte ist nicht gestattet.
# ==========================================================================================

# ==============================KONFIGURATIONS-TEIL BEGINN==================================

# ==========================================================================================
# DIE FOLGENDEN VARIABLEN BITTE ANPASSEN!
# Wenn das Skript NICHT laufen sollte, liegt es meistens an fehlerhaften
# Konfigurationsvariablen.
# WICHTIG:
# Bei $email muessen fuer die Zuweisung 'einfache' Anfuehrungsstriche gesetzt werden.
# Bei allen anderen Strings genuegen "doppelte" Anfuehrungsstriche.
# ==========================================================================================

# ==============================KONFIGURATIONS-TEIL BEGINN==================================

# ==========================================================================================
# DIE FOLGENDEN VARIABLEN BITTE ANPASSEN!
# Wenn das Skript NICHT laufen sollte, liegt es meistens an fehlerhaften
# Konfigurationsvariablen.
# WICHTIG:
# Bei $email muessen fuer die Zuweisung 'einfache' Anfuehrungsstriche gesetzt werden.
# Bei allen anderen Strings genuegen "doppelte" Anfuehrungsstriche.
# ==========================================================================================

# Ersetzen Sie www.firma.de durch Ihre Domain!!!!

$rc{"www.hindernisbau-sickinger.de"}="596-751-941-7612";                     # Hier geben Sie Ihren 13-stelligen Registrier-Key ein!!!! WICHTIG !!!!

$email='info@abel-consulting.de';                                # Ihre E-Mail (Wichtig fuer die Bestellungsmail)
$bcc_email='';                                              # Die E-Mail an den Shopinhaber kann zusätzlich als BCC (Blind Carbon Copy)
                                                            # zum Beispiel an einen Administrator verschickt werden.

$profiledirectory="./kunden/";                              # Verzeichnis, wo Kundendaten (Profile fuer Warenkorb)
                                                            # gespeichert werden sollen.
$tempdirectory="./template/";                               # Verzeichnis, wo sich die Templates (HTML und Mail) befinden.
$datadirectory="./daten/";                                  # Verzeichnis, wo sich die aus einer Datenbank
                                                            # exportierte Textdatei befindet.


$globaltxt="./daten/global.txt";                            # Pfad zur Konfig. Datei mit globalen Variablen!
                                                            # Aufbau der Datei:
                                                            # MWST;16
                                                            # WAEHRUNG;DM
                                                            # usw.
                                                            # In den Templates können die Globalen Variablen dann so
                                                            # verwendet werden: [G_MWST] [G_WAEHRUNG] usw.

$max_minuten_inaktiv=30;                                    # Wenn laenger als $max_minuten_inaktiv kein Zugriff auf einen
                                                            # Warenkorb registriert wurde, wird das Profil geloescht. Voreinstellung: 30 Minuten.
$min_userid=1000;                                           # Die minimale User-ID (Bestellnr.), die vergeben wird.
$max_userid=9999;                                           # Die max. User-ID (Bestellnr.), die vom System vergeben wird.

$sendmail_def=0;                                            # 0: Mails per UNIX-Programm Sendmail verschicken
                                                            # 1: Mails per SMTP-Server verschicken

# ------- Falls sendmail_def=0 ausgewählt ---------
$mailprog = "/usr/lib/sendmail";                            # Externes Mail-Programm sendmail. Pfad kann auch z.B. auf Ihrem
                                                            # Host auch "/usr/sbin/sendmail" sein.
# -------------------------------------------------

# ------- Falls sendmail_def=1 ausgewählt ---------
$mail_smtp_server="smtp.abel-consulting.de";                     # Mail-Server für ausgehende (Bestellungs) Mails
                                                            # z.B. mail.IhreDomain.de
# -------------------------------------------------


$subject_user_mail="Ihre Bestellung Nr. [USER_ID][ORDERNR] bei Hindernisbau Sickinger";   # Betreff der Kundenmail.
$subject_shop_mail="Bestellung Nr. [USER_ID][ORDERNR] bei Hindernisbau Sickinger";        # Betreff der Bestellungseingangsmail.

$dif_porto=1;                                               # Wählen Sie hier aus, ob die Versandkosten fest sind
                                                            # ($dif_porto=0), oder ob der Kunde selber die
                                                            # Versandkostenart über eine Combo-Box auswählen kann
                                                            # (z.B. Deutschland/Europa/Sonstige)

# ------- Falls dif_porto=0 ausgewählt ---------
$versandk_hoehe=5.00;                                       # Betrag der Versandkosten für dif_porto=0
                                                            # => feste Versandkosten

$versandk_frei_ab="500.00";                                 # Mind. Bestellsumme ab der der Versand kostenlos ist.
                                                            # => nur für feste Versandkosten (dif_porto=0)
# -----------------------------------------------

# ------- Falls dif_porto=1 ausgewählt ----------

@porto_daten=(                                              # Betrag der Versandk. für dif_porto=1
"Bankeinzug;8.00;500.00",                                  # => Geben Sie in jeder Zeile
"Vorkasse;8.00;500.00"

);                                   # an!

# -----------------------------------------------


$min_order_typ=0;                                           # Wählen Sie hier:
                                                            # 0: Mindestbestellmengen werden ignoriert
                                                            # 1: Mindestbestellmenge darf nicht unterschritten werden,
                                                            #    sonst Fehlermeldung!
                                                            # 2: Wenn Mindestbestellmenge unterschritten wird, wird
                                                            #    ein Mindermengen-Zuschlag erhoben.
$min_order="30.00";                                         # Mindestbestellmenge
$min_order_zuschlag="10.00";                                # Mindermengen-Zuschlag!


@currency=(                                                 # Währungsumrechnungskurse
"Euro=1.00",                                                # => Geben Sie in jeder Zeile
"Dollar=0.511292");                                         # "WÄHRUNG=UMRECHNUNGSKURS"
                                                            # an! Ausgabe: [PREIS_DM], [PREIS_Euro] etc.

@pichttp=(                                                  # HTTP-Verzeichnis für Bilder (also URL aus der Sicht des CGI-Verzeichnisses)
"/artikelbilder/"                                           # Alle Bilder werden in der Form ArtNr.gif hochgeladen, bei,
);                                                          # Art.Nr 3333 => 3333.gif
                                                            # Falls Sie versch. Bildertypen anlegen möchten (z.B. ein Verz. für
                                                            # kleine Bilder, ein anderes für grosses Bilder), geben Sie
                                                            # diese durch Komma getrennt jeweils in doppelten Anführungsstrichen
                                                            # an. In den Vorlagen können sie Bilder so einbinden:
                                                            # [PIC1], [PIC2], [PIC3] usw.

@picverz=(                                                  # Server-Verzeichnis für Bilder (also Pfad aus der Sicht des CGI-Verzeichnisses)
"../artikelbilder/");
                                    # => muss an die Variable @pichttp angepasst werden.
                                       # das Skript kontrolliert anhand des Server-Verz., ob das Bild
                                                            # Art.Nr existiert und gibt dann das HTML-Verzeichnis in der
                                                            # Ausgabe-HTML aus.


@pic_field_name=(
  "BILD"
  );                                                    # Geben Sie hier das Datenbankfeld an, in dem die Namen
                                                            # der Produktgrafiken angegeben sind. Einfachste Lösung:
                                                            # Verwenden Sie die Artikel-Nr. "NR" als Name der Grafik
                                                            # Die Grafik könnte dann z.B. heissen: 3456.gif

$default_pic="0000.gif";                                    # Bild, das geladen wird, falls das Bild ArtNr.gif nicht vorhanden sind

$use_default_pic=1;                                         # Wenn ein Artikel-Bild nicht vorhanden ist, soll dann
                                                            # Default-Pic geladen werden, oder gar kein Bild?
                                                            # 1: Default-Pic laden!
                                                            # 2: kein Bild ausgeben!

$bestand_verwaltung=0;                                      # 1: Bestand-Verwaltung benutzen
                                                            # 0: keine Bestand-Verwaltung

$fehlermeldung_bei_bestand_von_null=1;                      # Hier wird angegeben, ob z.B. eine Bestellung von Menge "1"
                                                            # bei einem Bestand von "0" nicht zugelassen werden soll,
                                                            # oder trotzdem toleriert werden soll. Letzteres kann z.b.
                                                            # sinnvoll sein, wenn der Shopinhaber sehr schnell das
                                                            # Produkt nachbestellen kann!

$mengen_im_warenkorb_addieren=0;                            # Beispiel:
                                                            # Artikel 3456 ist bereits mit der Menge 1 im Warenkorb
                                                            # und wird nochmals in den Warenkorb gelegt.
                                                            # Soll die Menge addiert werden ( = Menge 2) oder soll
                                                            # die Menge bei 1 bleiben?

$admin_passwort="ac";                                   # Admin-Passwort!
                                                            # Das Admin.Menü kann gestartet werden über:
                                                            # /cgi-bin/his-webshop.pl?admin=<admin passwort>

$no_variants="NR,BILD,KATEGORIE,TITEL,PREIS1,PREIS2,PREIS3,ZUBEHOER1,ZUBEHOER2";

                          # Geben Sie hier die Felder ein, die generell keine Artikel-Varianten
                                                            # (werden mit / oder mit * getrennt) enthalten.


@html_convert=(                                             # Geben Sie hier an, welche "Sonderzeichen" in HTML-Entitäten konvertiert
  "/=-"
  );                                                # werden sollen. Die Ausgabe muss dann über NAME_HTML bzw. VARIABLE_HTML
                                                            # erfolgen







$use_multiline_csv=0;                                       # Geben Sie hier an, ob in der CSV Datei ein Artikel
                                                            # (z.B. durch die Beschreibung) mehrere Zeilen umfasst.
                                                            # Wenn Sie sicher sind, dass ein Artikel immer genau innerhalb
                                                            # einer Zeile definiert ist, kann die Einstellung auch auf 0
                                                            # gestellt werden (Datenbank arbeitet dann deutlich schneller!!!)

$shoppl="/cgi-bin/reithindernisse.pl";                          # URL zum Skript


$post_order_mail_to_script_url="";                          # Wird hier eine URL zu einem Script angegeben, so wird keine
                                                            # Bestellmail an den Shopbetreiber geschickt. Stattdessen wird
                                                            # der Text an das Script geschickt (POST).
                                                            # Der Inhalt der Mail wird in der Variablen "mailtext" übermittelt

# ==========================================================================================
# Hier muessen die Felder der Datenbank IN DER KORREKTEN REIHENFOLGE definiert werden.
# Reservierte Felder, die exakt so geschrieben werden muessen sind:
# NR und PREIS
# Alle übrigen Felder aus Ihrer Datenbank koennen frei benannt werden. In den
# Templates kann man dann auf die Variablen jeweils mit [VARIABLE] zugreifen.
# ==========================================================================================

@keyw=(
"NICHT_LIEFERBAR",
"NR",
"BILD",
"KATEGORIE",
"TITEL",
"PREIS1",
"PREIS2",
"PREIS3",
"ZUBEHOER1",
"ZUBEHOER2",
"LEER"
);

# ==========================================================================================
# Hier muessen die Felder der Kunden-Datenbank IN DER KORREKTEN REIHENFOLGE definiert werden.
# Alle Felder aus Ihrer Datenbank koennen frei benannt werden. In allen
# Templates kann man dann auf die Variablen jeweils mit [VARIABLE] zugreifen.
#
# Sind Sie interessiert am "HIS WebShop Kunden Modul"? Das Kunden-Modul können Sie zur
# besseren Kundenbindung für Ihre Stammkunden einsetzen. Optionaler Login in den Shop,
# namentliche Begrüssung, bereits vorausgefüllte Bestellformulare etc.
# Kosten für das Kunden-Modul: 150,00 DM + MwSt. (Preis vom 24.01.00, ohne Gewähr!)
# Kontaktieren Sie uns: his-soft@shoppark.de
# ==========================================================================================

$use_kunden_db=0;                    # Geben Sie hier an, ob Sie das Kundenmodul nutzen
                                     # möchten!
                                     # 0: kein Kundenmodul nutzen
                                     # 1: Kundenmodul für Stammkunden nutzen!
                                     #    (das Kundenmodul muss dazu unbedingt installiert
                                     #     werden!)
@userf= (
  "U_USER",
  "U_PASS",
  "U_ANREDE",
  "U_NAME",
  "U_EMAIL",
  "U_STRASSE",
  "U_PLZ",
  "U_ORT",
  "U_LAND",
  "U_LISTE",
  "U_ORDERS"
);

$user_login_field="U_USER";
$user_pass_field="U_PASS";

# ==========================================================================================
# Hier muessen die Felder der Partner-Datenbank IN DER KORREKTEN REIHENFOLGE definiert
# werden. Alle Felder koennen frei benannt werden.
#
# Sind Sie interessiert am "HIS WebShop Partnerprogramm Modul"? Das Partnerprogramm-Modul
# können Sie zur Einrichtung eines professionellen Partner-Programms einsetzen.
# Kosten für das Partnerprogramm-Modul: 150,00 DM + MwSt. (Preis vom 24.01.00, ohne Gewähr!)
# Kontaktieren Sie uns: his-soft@shoppark.de
# ==========================================================================================

$use_partner_db=0;                   # Geben Sie hier an, ob Sie das Partnerprogramm-Modul nutzen
                                     # möchten!
                                     # 0: kein Partnerprogramm-Modul nutzen
                                     # 1: Partnerprogramm-Modul nutzen!
                                     #    (das Partnerprogramm-Modul muss dazu unbedingt installiert
                                     #     werden!)


$partner_provision=5;                # Provison in Prozent!

@puserf= (
  "P_USER",
  "P_PASS",
  "P_ANREDE",
  "P_NAME",
  "P_EMAIL",
  "P_STRASSE",
  "P_PLZ",
  "P_ORT",
  "P_LAND",
  "P_LISTE",
  "P_ORDERS"
);

$partner_login_field="P_USER";
$partner_pass_field="P_PASS";

# ==============================KONFIGURATIONS-TEIL ENDE====================================



# =================================HAUPTPROGRAMM BEGINN=====================================

if ($use_kunden_db==1) {                                    # Falls Stamm-Kunden Modul...
  require "kunde.pl";                                       # Modul einbinden!
}

if ($use_partner_db==1) {                                    # Falls Stamm-Kunden Modul...
  require "partner.pl";                                      # Modul einbinden!
}

$fe[0]="Content-type: text/html\n\n<html><body>Ein Fehler ist aufgetaucht.\n\nBitte <a href='http://www.reit-hindernisse.de'>wiederholen Sie Ihre Suche.</a></body></html>";
$fe[1]="Content-type: text/html\n\n<html><body>Ein Fehler ist aufgetaucht.\n\nBitte <a href='http://www.reit-hindernisse.de'>wiederholen Sie Ihre Suche.</a></body></html>";
$fe[2]="Content-type: text/html\n\n<html><body>Ein Fehler ist aufgetaucht.\n\nBitte <a href='http://www.reit-hindernisse.de'>wiederholen Sie Ihre Suche.</a></body></html>";

$start_tage = 2450902;                                      # Absolute Tage

# Vorlagen befinden sich in dem Verzeichnis $tempdirectory und haben bis auf
# $template_mail die Endung ".htm"
$template_error="temerror";                                 # Fehler-Vorlage
$template_send="temsend";                                   # "Danke für Ihre Bestellung"-Template
$template_basket="tembaske";                                # Warenkorb-Template
$template_order="temorder";                                 # Bestellugsseite-Template
$template_shop_mail="order.txt";                            # Bestellungsmail-Template für Shop-Inhaber
$template_user_mail="mail.txt";                             # Bestellungsmail-Template für User
$template_partner_mail="mpartner.txt";

$articledat=$datadirectory."hindernisse.csv";                   # Artikel-Datenbank
$kundetxt=$datadirectory."kunden.txt";                      # Stammkunden-Datenbank
$partnertxt=$datadirectory."partner.txt";                   # Partner-Datenbank
$kundedat=$profiledirectory."kunden.dat";                   # Kunden-Datenbank
$statistikdat=$datadirectory."statistik.txt";
$orderstat=$datadirectory."orderstat.txt";

($id_article_quantity,                                      # Zusaetzliche Arrayindizes fuer Artikel
 $id_article_newquantity,
 $id_article_apreis,
 $id_article_sum,
 $id_article_binfo)=$#keyw+1..$#keyw+5;



($id_global_skript,                                         # Index fuer globale Variablen Array
 $id_global_userid,
 $id_global_remotehost,
 $id_global_versandkosten,
 $id_global_versandkfreiab,
 $id_global_sumall,
 $id_global_sumallv,
 $id_global_hit_start,
 $id_global_hit_end,
 $id_global_hit_max,
 $id_global_hit_menu,
 $id_global_hit_forward,
 $id_global_hit_back,
 $id_global_artikel_anz,
 $id_global_content,
 $id_global_porto_auswahl,
 $id_global_porto,
 $id_global_error,
 $id_global_referer,
 $id_global_shopemail,
 $id_global_ordernr,
 $id_global_min_order,
 $id_global_min_order_zuschlag,
 $id_global_query,
 $id_global_provision,
 $id_global_bonus_nr,
 $id_global_bonus_value,
 $id_global_bonus_pass,
 $id_global_bonus_email,
 $id_global_bonus_message,
 $id_global_happy_hour)=(0..30);
 $last_id_global=30;


($id_kunde_remotehost,                                      # Index fuer Kunden Array
 $id_kunde_kundennr,
 $id_kunde_tage,
 $id_kunde_minuten,
 $id_kunde_userdata,
 $id_kunde_partnerdata,
 $id_kunde_global)=(0..6);

($id_order_date,
 $id_order_ordernr,
 $id_order_sum,
 $id_order_provision,
 $id_order_pid,
 $id_order_status)=(0..5);

%multi= (
   "MENGE", 1,                  # Ok
   "NEUE_MENGE", 1,             # Ok
   "APREIS",1,
   "SUMME", 1,                  # Ok
   "BINFO",1,
   "SKRIPT",5,                  # Ok
   "USER_ID",5,                 # Ok
   "HOST",5,                    # Ok
   "VERSANDKOSTEN",5,           # Ok
   "VERSANDKOSTEN_FREI_AB",5,   # Ok
   "GESAMTSUMME",5,             # Ok
   "GESAMTSUMME_VERSAND",5,     # Ok
   "HIT_START",5,
   "HIT_END",5,
   "HIT_MAX",5,
   "HIT_MENU",5,
   "HIT_FORWARD",5,
   "HIT_BACK",5,
   "ARTIKEL_ANZ",5,
   "CONTENT",5,
   "PORTO_AUSWAHL",5,
   "PORTO",5,
   "ERROR_INHALT",5,            # Ok
   "REFERER",5,
   "SHOPEMAIL",5,
   "MIN_ORDER",5,
   "MIN_ORDER_ZUSCHLAG",5,
   "QUERY",5,
   "HAPPY_HOUR",5,
   "PROVISION",5,
   "BONUS_NR",5,
   "BONUS_PASS",5,
   "BONUS_VALUE",5,
   "BONUS_EMAIL",5,
   "BONUS_MESSAGE",5,
   "ORDERNR",5,
   "ORDERKEY",6,                # Ok
   "ORDERVALUE",6,               # Ok
   "RORDER_DATE",8,
   "RORDER_SUM",8,
   "RORDER_ORDERNR",8,
   "RORDER_PROVISION",8,
   "RORDER_STATUS",8,
   "RORDER_PID",8,
);

%index= (
  "MENGE",$id_article_quantity,
  "NEUE_MENGE",$id_article_newquantity,
  "APREIS",$id_article_apreis,
  "SUMME",$id_article_sum,
  "BINFO",$id_article_binfo,
   "SKRIPT",$id_global_skript,
   "USER_ID",$id_global_userid,
   "HOST",$id_global_remotehost,
   "VERSANDKOSTEN",$id_global_versandkosten,
   "VERSANDKOSTEN_FREI_AB",$id_global_versandkfreiab,
   "GESAMTSUMME",$id_global_sumall,
   "GESAMTSUMME_VERSAND",$id_global_sumallv,
   "HIT_START",$id_global_hit_start,
   "HIT_END",$id_global_hit_end,
   "HIT_MAX",$id_global_hit_max,
   "HIT_MENU",$id_global_hit_menu,
   "HIT_FORWARD",$id_global_hit_forward,
   "HIT_BACK",$id_global_hit_back,
   "ARTIKEL_ANZ",$id_global_artikel_anz,
   "CONTENT",$id_global_content,
   "PORTO_AUSWAHL",$id_global_porto_auswahl,
   "PORTO",$id_global_porto,
   "ERROR_INHALT",$id_global_error,
   "REFERER",$id_global_referer,
   "SHOPEMAIL",$id_global_shopemail,
   "MIN_ORDER",$id_global_min_order,
   "MIN_ORDER_ZUSCHLAG",$id_global_min_order_zuschlag,
   "QUERY",$id_global_query,
   "HAPPY_HOUR",$id_global_happy_hour,
   "PROVISION",$id_global_provison,
   "BONUS_NR",$id_global_bonus_nr,
   "BONUS_PASS",$id_global_bonus_pass,
   "BONUS_VALUE",$id_global_bonus_value,
   "BONUS_EMAIL",$id_global_bonus_email,
   "BONUS_MESSAGE",$id_global_bonus_message,
   "ORDERNR",$id_global_ordernr,
   "ORDERKEY",0,
   "ORDERVALUE",1,
   "RORDER_DATE",$id_order_date,
   "RORDER_SUM",$id_order_sum,
   "RORDER_ORDERNR",$id_order_ordernr,
   "RORDER_PROVISION",$id_order_provision,
   "RORDER_STATUS",$id_order_status,
   "RORDER_PID",$id_order_pid,
);

for ($i=0;$i<=$#pichttp;$i++) {
   $j=$i+1;
   $multi{"PIC$j"}=5;
   $index{"PIC$j"}=$last_id_global+$j;
   $global[$last_id_global+$j]=$pichttp[$i];
}

if ($ENV{'REQUEST_METHOD'} eq "GET") { $buffer = $ENV{'QUERY_STRING'}; }
else { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});  }

if (!($buffer)) {$buffer=substr($ENV{'PATH_INFO'},1,length($ENV{'PATH_INFO'}));}
if (!($buffer)) {$buffer=@ARGV; }



for ($i=0;$i<=$#keyw;$i++) {                                # Reservierte Keywoerter suchen
  if ($keyw[$i] eq "NR")     {$id_article_id=$i;}           # Art. Nr
  elsif ($keyw[$i] eq "PREIS")   {$id_article_costs=$i;}    # Preis
  $multi{$keyw[$i]}=1;                                      # Typ speichern, immer "1"
  $index{$keyw[$i]}=$i;                                     # Feldindex speichern
}

for ($i=0;$i<=$#userf;$i++) {                               # Reservierte Keywoerter suchen
 $uindex{$userf[$i]}=$i;                                    # Feldindex speichern
}
for ($i=0;$i<=$#puserf;$i++) {                              # Reservierte Keywoerter suchen
 $pindex{$puserf[$i]}=$i;                                   # Feldindex speichern
}

@kunde_dat=&read_data($kundedat);                           # Einlesen der Kundendaten


@article_dat=&read_data($articledat);                       # Artikel holen
$global[$id_global_artikel_anz]=$#article_dat+1;


@happy=&read_data($datadirectory."happy.txt");
@happy_today=split(/\,/,$happy[$mday]);
foreach $happy_today (@happy_today) {
  if ($happy_today==$hour) {
    $global[$id_global_happy_hour]=$happy_today;
  }
}


$#nvpairs=-1;                                                         # Paare leeren
($now_tage,$now_minuten,$mday,$month,$year,$hour,$minute)=&now;       # Berechnung absoluter Tage und aktueller Minuten

%input=();                                                            # leerer Input

if ($ENV{CONTENT_TYPE}=~/multipart\/form-data/i) {
   ($content,$ufile)=&Parse_Multi;
    if ($content ne "") {
     $ufile=&get_file($ufile);
   }
} else {
  $buffer=&ReadParse($buffer,*input);                                   # Einlesen der Formulareingaben
}

#$input{"t"}="temdd";
#$input{"f2"}="PREIS";
#$input{"c2"}="";
#$input{"f1"}="*NAME";
#$input{"c1"}="epson";
#$input{"f"}="HERSTELLER";
#$input{"c"}="";
#$input{"t"}="temgroup";


$#basket_dat_new=-1;                                                  # leerer Array für neu in den Warenkorb gelegte Artikel

# Bereitgestellte Funktionen im Partnerprogramm-Modul
if ($input{"pid"} ne "") {
  $buffer.="&G_pid=".$input{"pid"};
  $input{"G_pid"}=&login_puser($input{"pid"});
}

# Speichern von globalen Variablen
@keyval=&get_input($buffer);

foreach $keyval (@keyval) {
  @field=split(/\;/,$keyval);                             # Felder ermitteln
  if ($field[0]=~/^G_(.*)/) {
    $global{$field[0]}=$field[1];
  }
}


if ($CGI{"update"} ne "") {
  &pic_update($CGI{"update"},$content,$ufile,$CGI{"pass"});exit;
}

$REMOTE_HOST=$ENV{'REMOTE_ADDR'};                           # Remote Host ermitteln
$global[$id_global_remotehost]=$REMOTE_HOST.'#'.$ENV{'HTTP_VIA'}.'#'.$ENV{'REMOTE_HOST'}.'#'.$ENV{'HTTP_USER_AGENT'};  # Zur Identifik. Remote Host und HTTP Via (proxys) verwenden
$global[$id_global_remotehost]=~s/\;/\,/g;
$global[$id_global_userid]=&get_user_id;                    # User-Id
$global[$id_global_versandkosten]=$versandk_hoehe;          # Versandkosten
$global[$id_global_versandkfreiab]=$versandk_frei_ab;       # Freibetrag fuer Versandkosten
$global[$id_global_skript]=$shoppl;                         # Name des Skripts
$global[$id_global_referer]=$ENV{'HTTP_REFERER'};
$global[$id_global_shopemail]=$email;
$global[$id_global_min_order]=$min_order;
$global[$id_global_min_order_zuschlag]=$min_order_zuschlag;
$global[$id_global_query]=$buffer;


$basketdat=&get_basketdat($global[$id_global_userid]);      # Name des Warenkorbs des Kunden ermitteln
@basket_dat=&read_data($basketdat);                         # Warenkorb des Kunden einlesen
$#basket_dat_new=-1;                                        # Leeren Warenkorb für "neu in den Warenkorb gelegte Artikel"
if ($dif_porto!=0) {                                        # Falls Versandk. vom Kunden auswählbar...
  $portodat=&get_portodat($global[$id_global_userid]);      # Name des Files ermitteln, in dem die Versandk. gespeichert sind
  @porto=&read_data($portodat);                             # Daten einlesen
  $porto=$porto[0];                                         # Versandk.art = 1. Zeile
}

if ($input{"pic_show"}==1) {&pic_show_or_kill(0);exit}
if ($input{"pic_kill"}==1) {&pic_show_or_kill(1);exit}
if ($input{"empty"} ne "") {unlink "$basketdat";$#basket_dat=-1}

if ($input{"required"} ne "") {
   &kontrolliere_required;                                   # benötigte Felder kontrollieren
}

if (defined($input{"u_login"})) {                           # Falls Login....
  &kunde_login($input{"u_login"},$input{"u_pass"});         # Funktion kunde_login aufrufen!
}

if (defined($input{"p_login"})) {                           # Falls Login....
  &partner_login($input{"p_login"},$input{"p_pass"});         # Funktion kunde_login aufrufen!
}


@glob=&read_data($globaltxt);
foreach $glob (@glob) {
  @d=split(/\;/,$glob);
  $input{"G_$d[0]"}=$d[1];
}

# Bereitgestellte Funktionen im Kunden-Modul
if ($input{"setkundencookie"}>0) {
   &set_kunden_cookie($input{"setkundencookie"});
}
if ($input{"send_pw_login"} ne "" || $input{"send_pw_email"} ne "") {&send_pw($input{"send_pw_login"},$input{"send_pw_email"});}
if ($input{"deletekundencookie"}==1) {&delete_kunden_cookie;}
if ($input{"readkundencookie"}==1) {&read_kunden_cookie;}


if ($input{"adduser"}==1)   {                               # Anmeldung eines neuen Kunden
   &adduser;
}
if ($input{"deleteuser"}==1) {                              # Kunde löschen
   &deleteuser;
}
if ($input{"edituser"}==1) {                                # Kunde editieren
   &edituser;
}
if ($input{"logout"}==1)   {                                # Kunde Logout
   &logout;
}
if ($input{"adduser_partner"}==1)   {&adduser_partner;}
if ($input{"deleteuser_partner"}==1) {&deleteuser_partner;}
if ($input{"edituser_partner"}==1) {&edituser_partner;}
if ($input{"logout_partner"}==1)   {&logout_partner;}


srand(time);
if (int(rand(100))==1) {
  opendir (VERZ, "$profiledirectory");
  @datei= grep (!/^\.\.?$/, readdir VERZ);
  closedir VERZ;
  foreach $datei (@datei) {
    $age=-M $profiledirectory.$datei;
    if ($age>1) {
      unlink $profiledirectory.$datei;
    }
  }
}

if ($input{"update"} ne "") {&update($input{"update"},$input{"pass"})}
if ($input{"admindelete"} ne "") {&admindelete($input{"pass"});}
if ($input{"add_to_db"} ne "") {&add_to_db($input{"add_to_db"})}
if ($input{"admin"} eq $admin_passwort && $admin_passwort ne "") {&admin;}

if ($input{"show_prov"} ne "") {

   $code=qq!<html><body><h1>Partner-Bestellungen in $input{"month"}/$input{"year"}</h1>!;
   $code.="<table width=800><tr><td>Datum</td><td>Nr</td><td>Status</td><td>Summe</td><td>Provis.</td><td>Beschreibung</td><td>PID</td></tr>";
   $code.="[REPEAT_RORDER]";
   $code.="<tr><td>[RORDER_DATE]</td><td>[IF_('[RORDER_ORDERNR]'>0)][RORDER_ORDERNR][IF_END]</td><td>[RORDER_STATUS]</td><td>[RORDER_SUM]</td><td>[PRINTF([RORDER_SUM]*[RORDER_PROVISION]/100)]</td><td>[IF_('[RORDER_ORDERNR]' eq '-')]Gutschrift[IF_END][IF_('[RORDER_ORDERNR]' ne '-')][RORDER_ORDERNR][IF_END]</td><td>[RORDER_PID]</td></tr>";
   $code.="[REPEAT_RORDER_END]";
   $code.="</table><p>";

    if ($input{"show_prov_pid"} eq "ALL") {
     $all_partner="ALL";
   } else  {
     $all_partner=$input{"show_prov_pid"};
   }
   print "Content-type: text/html\n\n";
   print &parse_line($code);
   exit;
}


if ($input{"pay_partner"} ne "") {
  if ($input{"pass"} ne $admin_passwort) {&abbruch("Falsches Passwort");}
  &pay_partner($input{"pay_partner"},$input{"sum_pay_partner"});
}
if ($input{"correct_prov"} ne "") {
  if ($input{"pass"} ne $admin_passwort) {&abbruch("Falsches Passwort");}
  &pay_partner($input{"correct_prov"},&format_sum($input{"minus_prov"}*$partner_provision/100),$input{"reason_prov"});
}

if ($input{"status_ordernr"} ne "") {
  if ($input{"pass"} ne $admin_passwort) {&abbruch("Falsches Passwort");}
  &set_status($input{"status_ordernr"},$input{"new_status"});
}
if ($input{"ChangeBonusStatNr"} ne "") {
  &change_gutschein_status($input{"pass"},$input{"ChangeBonusStatNr"},$input{"BonusBezahlt"},$input{"BonusEingeloest"});
}

if ($input{"send_order"}) {                                 # Falls Aktion "Mail verschicken"
  &send_mail;                                               # Mails versenden
  &output_order;                                            # Nachricht ausgeben
  exit;
} elsif ($input{"order"} ne "" || $input{"order.x"} ne "") {                                # Falls Aktion "Bestellseite"
  &special_request("","",$template_order);                  # Bestellungsseite ausgeben
} else {
  if ($cdmodul_ist_aktiv==0) {
    &special_request($input{"f"},$input{"c"},$input{"t"},$input{"start"},$input{"dif"},$input{"aliste"});
  } else {
   1;
  }
}



sub admin {
 print "Content-type: text/html\n\n";
 print "<html><body>";
 print "<h3>WebShop Administration:</h3>";
 print qq!<ol><li><form action="$shoppl" method="POST">!;
 print qq!<input type="hidden" name="pass" value="$admin_passwort">!;
 print qq!<b>Artikel editieren:</b><br>!;
 print qq!Artikel-Nr.: <input type="text" name="update" size=10">\n!;
 print qq!<input type="submit" value="Artikel editieren">!;
 print qq!</Form>!;
 print qq!<li><form action="$shoppl" method="POST">!;
 print qq!<input type="hidden" name="pass" value="$admin_passwort">!;
 print qq!<input type="submit" name="update" value="Neuen Artikel eintragen">!;
 print qq!</form>!;


 if ($use_partner_db==1) {
   print qq!<li><form action="$shoppl" method="POST">!;
   print qq!<input type="hidden" name="pass" value="$admin_passwort">!;
   print qq!<b>Status einer Bestellung setzen:</b><br>!;
   print qq!<table><tr><td>Bestell-Nr.:</td><td><input type="text" name="status_ordernr" size=20></td></tr>!;
   print qq!<tr><td valign=top>Neuer Status:</td><td><input type="text" name="new_status" size=20><br><font size=2>(z.b. "OK" oder "Bestellung ungültig" etc.)</td></tr></table>!;
   print qq!<input type=submit value="Status eintragen">!;
   print qq!</form>!;
   print qq!<li><form action="$shoppl" method="POST">!;
   print qq!<input type="hidden" name="pass" value="$admin_passwort">!;
   print qq!<b>Provisions-Korrekturen durch Stornierungen oder zurückgesendete Waren eintragen:</b><br>!;
   print qq!<table><tr><td>Partner-ID (PID):</td><td><input type="text" name="correct_prov" size=20></td></tr>!;
   print qq!<tr><td valign=top>Warenwert-Minderung um einen Betrag von:</td><td><input type="text" name="minus_prov" size=20></td></tr>!;
   print qq!<tr><td valign=top>Begründung:</td><td><input type="text" name="reason_prov" size=20></td></tr>!;
   print qq!</table>!;

   print qq!<input type=submit value="Status eintragen">!;
   print qq!</form>!;
   print qq!<li><form action="$shoppl" method="POST">!;
   print qq!<input type="hidden" name="pass" value="$admin_passwort">!;
   print qq!<b>Überweisung an Partner (Reseller) eintragen:</b><br>!;
   print qq!<table><tr><td>Partner-ID (PID):</td><td><input type="text" name="pay_partner" size=20></td></tr>!;
   print qq!<tr><td>Überwiesener Betrag:</td><td><input type="text" name="sum_pay_partner" size=10></td></tr></table>!;
   print qq!<input type="submit" value="Überweisung an Partner eintragen">!;
   print qq!</form>!;

   print qq!<li><form action="$shoppl" method="POST">!;
   print qq!<input type="hidden" name="show_prov" value="1">!;
   print qq!<input type="hidden" name="pass" value="$admin_passwort">!;
   print qq!<b>Übersicht aller Bestellungen über das Partnermodul:</b><br>!;
   print qq!<table><tr><td>Monat</td><td><input type="text" name="month" value="$month" size=10></td></tr>!;
   print qq!<tr><td>Jahr</td><td><input type="text" name="year" value="$year" size=10></td></tr>!;
   print qq!<tr><td>Partner-ID (PID):</td><td><input type="text" name="show_prov_pid" value="ALL" size=10></td></tr></table>!;
   print qq!<input type="submit" value="Übersicht anzeigen">!;
   print qq!</form>!;
 }
 print qq!</ol>!;
 print "</body></html>";
 exit;
}


sub pic_update {
 local($nr,$content,$ufile,$pass)=@_;
 $picnr=$CGI{"pic"};

 $this_pic=$nr;
  @a=split(/ \* /,$this_pic);
 $this_pic=$a[0];

 $this_pic=~s/\s//g;
 $this_pic=~s/[\\\/]//g;


 $endung="";
 if ($ufile=~/\.gif/i) {$endung=".gif";}
 if ($ufile=~/\.jpg/i) {$endung=".jpg";}

 if ($ufile eq "") {
   unlink "$picverz[$picnr]$this_pic.gif";
   unlink "$picverz[$picnr]$this_pic.jpg";
 } else {
   open(f,">$picverz[$picnr]$this_pic$endung");
   binmode f;
   print f $content;
   close(f);
 }


 &update($nr,$pass);
}

sub admindelete {
  local($pass)=@_;
  if ($pass ne $admin_passwort) {&abbruch("Falsches Passwort");}
  &get_input;
  foreach $keyval (@keyval) {
    @field=split(/\;/,$keyval);                             # Felder ermitteln
    if ($field[0]=~/^delete_(.*)/) {
     $del{$1}="ok";

     }
   }
  $#new_article_dat=-1;
  foreach $article_dat (@article_dat) {
     @a=split(/\;/,$article_dat);
     if ($del{$a[$id_article_id]} eq "") {
       push(@new_article_dat,$article_dat);
     }
  }
  @article_dat=@new_article_dat;
  &save_array($articledat,"article",@article_dat);
}

sub update {
  local($nr,$pass)=@_;

  if ($pass ne $admin_passwort) {&abbruch("Falsches Passwort");}
  @adata=&get_article_data($nr);


  $do_update=0;
  foreach $keyw (@keyw) {
    if (defined($input{"update_$keyw"})) {
      $adata[$index{$keyw}]=$input{"update_$keyw"};
      $do_update=1;
    }
  }
  $gef=0;
  if ($do_update==1) {
    foreach $article_dat (@article_dat) {
      @a=split(/\;/,$article_dat);
      if ($a[$id_article_id] eq $nr) {
        $article_dat=join(';',@adata);
        $gef=1;
      }
    }
    if ($gef==0) {
      push(@article_dat,join(';',@adata));
    }
    &save_array($articledat,"article",@article_dat);
  }
  $#article=-1;
  push(@article,join(';',@adata));

  if ($input{"exit_update"}==1 || $CGI{"exit_update"}==1) {return;}

  $table=qq!<form action="$shoppl" method="POST">\n!;
  $table.=qq!<input type="hidden" name="update" value="$nr">\n!;
  $table.=qq!<input type="hidden" name="pass" value="$admin_passwort">\n!;
  $table.=qq!<table border="0">\n!;
  $i=0;
   foreach $keyw (@keyw) {
    $value="$adata[$i]";
    if ($input{$keyw} ne "") {$value=$input{$keyw}}
    if ($keyw eq "NR" && $nr eq "neu") {$value=time;}

    if ($keyw ne "BESCHREIBUNG") {
      $table.=qq!<tr><td><b>$keyw</b><br><input type="text" name="update_$keyw" size=50 value="$value"></td></tr>\n!;
    } else {
      $value=~s/\<br\>/\n/g;
     $table.=qq!<tr><td><b>$keyw</b><br><textarea name="update_$keyw" cols=100 rows=6 wrap="on">$value</textarea></td></tr>\n!;

    }
    $i++;
  }
  $table.="</table>";
  $table.=qq!<input type="submit" value="Artikel ändern">!;
  $table.="</form>\n";

  $i=-1;
#  foreach $pichttp (@pichttp) {
#    $i++;$j=$i+1;
#    $table.=qq![REPEAT_ARTIKEL]<form action="$shoppl" method="POST" enctype="multipart/form-data">\n!;
#    $table.=qq!<input type="hidden" name="update" value="$nr">\n!;
#    $table.=qq!<input type="hidden" name="pass" value="$admin_passwort">\n!;
#    $table.=qq!<input type="hidden" name="pic" value="$i">\n!;
#    $table.=qq![PIC$j]<br><b>$pichttp[$i]</b><br>!;
#    $table.=qq!<input type=file name="UploadedFile" size=30><br>\n!;
#    $table.=qq!<input type="submit" value="Bild Upload">!;
#    $table.=qq!</form>[REPEAT_ARTIKEL_END]!;
#  }

  print "Content-type: text/html\n\n";
  print "<html><body>".&parse_line($table)."</body></html>";
  exit;
}



# ==========================================================================================
# Hinzufügen eines Eintrags in die Datenbank über ein Web-Formular!
# ==========================================================================================

sub add_to_db {
  local($db)=@_;


  $#new_entry=-1;
  foreach $keyw (@keyw) {
    if ($input{"$keyw"} ne "") {
      $new_entry[$index{$keyw}]=$input{"$keyw"};
    }
  }

  open(f,">>$datadirectory$db");
  print f join(';',@new_entry)."\n";
  close(f);
}

# ==========================================================================================
# Funktion zum Entfernen "überflüssiger" Bilder, also i.d.R. Grafiken, die zu Artikeln
# gehören, die gelöscht wurden.
# ==========================================================================================

sub pic_show_or_kill {
  local($pic_kill)=@_;
  foreach $article_dat (@article_dat) {
    @array=split(/\;/,$article_dat);
    $array[$index{"NR"}]=~s/\s//g;
    $array[$index{"NR"}]=~s/[\\\/]//g;
    $is_ok{$array[$index{"NR"}]}=1;
  }

  print "Content-type: text/html\n\n";
  print "<html><body>";
  $ok=1;
  foreach $picverz (@picverz) {
    opendir (VERZ, "$picverz");
    @datei= grep (!/^\.\.?$/, readdir VERZ);
    closedir VERZ;

    foreach $datei (@datei) {
      if ($datei=~/\.gif$/i || $datei=~/\.jpg$/) {
        $d=$datei;
        $d=~s/\.gif//gi;
        $d=~s/\.jpg//gi;
        if ($is_ok{$d}==0 && $datei ne $default_pic) {
          if ($pic_kill==0) {
            $ok=0;
            print "Die Datei $picverz$datei kann gelöscht werden.<br>\n";
          } else {
            $ok=0;
            unlink "$picverz[0]$datei";
            print "Die Datei $picverz$datei wurde gelöscht.<br>\n";
          }
        }
      }
    }
  }
  if ($ok==1) {
    print "Alles in Ordnung!";
  }
}


# ==========================================================================================
# Kontrolle der Felder der Bestellungsseite, die zwingend einen Inhalt haben müssen.
# Um diese Felder zu definieren, kann das Formular auf der Bestellseite ein HIDDEN-Feld mit
# Namen "required" enthalten. Beispiele:
# <input type=hidden name="required" value="Name,Email,Strasse">
# ==========================================================================================

sub kontrolliere_required {
  local($required,@required);

  $c=&CC_Verify($input{"Kartentyp"},$input{"Kartennummer"});
  if ($c==0) {
    &abbruch("Die Kreditkarten-Daten sind leider ungültig.");
  }

  $required=$input{"required"};                             # Das Feld mit Namen "requried" einlesen
  @required=split(/\,/,$required);                          # Felder ermitteln
  foreach $required (@required) {                           # Alle Felder durchlaufen
    if ($input{$required} eq "") {                          # Falls das angegebene Feld nicht ausgefüllt wurde...
      &abbruch("Bitte füllen Sie das Feld <b>$required</b> aus. Vielen Dank!")        # Fehlermeldung ausgeben!
    }
  }
}

# ==========================================================================================
# Ermittelt die User-ID des Benutzers
# ==========================================================================================

sub get_user_id {
  if ($input{"userid"} ne "") {                                   # Falls UserId per Formulareingabe uebergeben wird...
    return &search_user($input{"userid"});
  }
  else {
    return &search_user("");                                    # Ansonsten UserId suchen
  }
}


# ==========================================================================================
# Kontrolliert, ob zwei Angaben (zusammengesetzt aus REMOTE_HOST und HTTP_VIA) vom selben
# Kunden stammen (inkl. Proxy Test!)
# ==========================================================================================

sub check_equal {
  local($r1,$r2)=@_;                                        # Einlesen der zwei Angaben
  @host_http1=split(/\#/,$r1);                              # Angaben in REMOTE_HOST und HTTP_VIA zerlegen
  @host_http2=split(/\#/,$r2);
  if ($host_http1[3] ne $host_http2[3]) {return 0;}         # Browser gleich?
  if ($host_http2[1] eq ''  || $host_http1[1] eq '') {      # Falls keine HTTP_VIA Angabe => Keine Proxys, direkte Verbindung, einfach zu handeln
    @ip1=split(/\./,$host_http1[0]);
    @ip2=split(/\./,$host_http2[0]);
    if  ( ( ($ip1[0]==195 && $ip1[1]==14) || ($ip1[0]==194 && $ip1[1]==8)) &&
          ( ($ip2[0]==195 && $ip2[1]==14) || ($ip2[0]==194 && $ip2[1]==8))) {return 1;}
    if ($ip1[0] ne $ip2[0] || $ip1[1] ne $ip2[1] || $ip1[2] ne $ip2[2]) {return 0;}       # Falls IPs ungleich => nicht derselbe Kunde
    return 1;                                               # Ansonsten ist es derselbe Kunde
  }

  if ($host_http1[1] eq $host_http2[1]) {return 1;}         # Falls HTTP_VIA gleich => derselbe Kunde
  @http_via1=split(/ /,$host_http1[1]);                     # HTTP_VIA z.B.: "HTTP/1 speth13.dort01.t-online.de"
  @http_via2=split(/ /,$host_http2[1]);
  @p1=split(/\./,$http_via1[1]);                            # Untersucht werden soll der Teil: speth13.dort01.t-online.de
  @p2=split(/\./,$http_via2[1]);
  if ($p1[1] ne $p2[1]) {return 0;}                         # 2. Teil untersuchen
  if ($p1[2] ne $p2[2]) {return 0;}                         # 3. Teil untersuchen
  $first1=$p1[0];                                           # 1. Teil untersuchen
  $first2=$p2[0];
  $min=length($first1);                                     # min. Zeichenfolge ermitteln
  if (length($first2)<$min) {$min=length($first2)}
  $first1=substr($first1,0,$min-2);                         # jeweils vom 1. Teil nur die ersten Zeichen verwenden
  $first2=substr($first2,0,$min-2);
  if ($first1 ne $first2) {return 0;}                       # Zeichenketten vergleichen
  return 1;
}

sub get_global_data {
  local($g)=@_;
  @global_keyvalues=split(/\~/,$g);
  foreach $global_keyvalues (@global_keyvalues) {
    @kv=split(/\=/,$global_keyvalues);
    if (!defined($input{"$kv[0]"})) {
      $input{"$kv[0]"}=$kv[1];
      $global{$kv[0]}=$kv[1];
    }
  }
}

sub get_global_data_string {
  local($g);
  foreach $key (sort(keys %global)) {
    $global{$key}=~ s/\cM\n/ /g;
    $g.=$key. '='. $global{$key}. "~";
  }
  return $g;
}

# ==========================================================================================
# Sucht nach einem User und gibt dessen Kunden-Nr. zurueck.
# Wenn User nicht in Liste oder laenger als max_minuten_inaktiv in Liste, wird auf die
# Prozedur create_new_kunde verwiesen.
# Wenn der User gefunden wurde und im Bereich max_minuten_inaktiv ist, wird der alte Eintrag
# geloescht, der User mit neuer Zeit am Anfang der Liste eingefuegt und die Kundennummer
# zurueckgegeben.
# ==========================================================================================

sub search_user {
  local($opt_id)=@_;
  local($is_equal);

  $knr=0;
  $#new_kunde_dat=-1;
  foreach $kunde_dat (@kunde_dat) {
    $kunde_dat=~s/\[USER_ID\]/$min_userid/g;
     @kunde=split(/\;/,$kunde_dat);                      # Kundendaten holen
    $vergangene_minuten=$now_tage*24*60+$now_minuten-($kunde[$id_kunde_tage]*24*60+$kunde[$id_kunde_minuten]);
     if ($vergangene_minuten<=$max_minuten_inaktiv) {      # Vergangene Minuten mit eingestellter Zeit vergleichen

      $is_equal=0;
      if ($opt_id eq "") {
        if (&check_equal($kunde[$id_kunde_remotehost],$global[$id_global_remotehost])==1) {    # Falls IP-Adresse+HTTP_VIA uebereinstimmen
          $is_equal=1;
        }
      } else {
        if ($opt_id eq $kunde[$id_kunde_kundennr]) {
          $is_equal=1;
        }
      }
     if ($is_equal==1) {
        $kunde[$id_kunde_tage]=$now_tage;                   # Kundendaten zuweisen
        $kunde[$id_kunde_minuten]=$now_minuten;
        &get_global_data($kunde[$id_kunde_global]);
        $kunde[$id_kunde_global]=&get_global_data_string;
        $knr=$kunde[$id_kunde_kundennr];
        @user_daten=split(/\|/,$kunde[$id_kunde_userdata]);
        @partner_daten=split(/\|/,$kunde[$id_kunde_partnerdata]);
      }
      push(@new_kunde_dat,join(';',@kunde));
    } else {
      $killdat=&get_basketdat($kunde[$id_kunde_kundennr]);     # Warenkorb holen
      unlink "$killdat";                                       # Warenkorb loeschen
      if ($dif_porto!=0) {
        $killdat2=&get_portodat($kunde[$id_kunde_kundennr]);   # Portodat
        unlink "$killdat2";                                    # löschen
      }
    }
  }

  if ($knr==0) {
    @nk=&create_new_kunde;
    if ($opt_id ne "" && $is_equal==0) {
      $nk[$id_kunde_kundennr]=$opt_id;
    }
    $nk[$id_kunde_global]=&get_global_data_string;
    push(@new_kunde_dat,join(';',@nk));
    @kunde_dat=@new_kunde_dat;
    $knr=$nk[$id_kunde_kundennr];
  }
  &save_array($kundedat,"kunde",@new_kunde_dat);          # Speichern
  return $knr;                                            # neuer Kunde
}


# ==========================================================================================
# Ein neuer Kunde wird erstellt und in die Kundenliste am Anfang eingefuegt.
# Falls die Kundenliste mehr als max_user Eintraege hat, werden die aeltesten Eintraege
# (stehen hinten) geloescht. Die Profil-Dateien werden ebenfalls geloescht.
# Anschliessend wird solange eine beliebige Zuf-Zahl aus dem Bereich min_userid-max_userid
# gewaehlt, bis es KEINE Profil-Datei zu der Kundennr. gibt. Der neue Kunde ist dann
# gefunden. Die Kunden-Felder werden gesetzt und er wird an den Anfang der Liste eingefuegt.
# ==========================================================================================

sub create_new_kunde {
  srand();                                                  # Zuf-Generator initialisieren

  &lock("stat");
  @s=&read_data($statistikdat);
  $found=0;
  foreach $s (@s) {
    @z=split(/\;/,$s);
    if ($z[0]=~/$mday\.$month\.$year/) {
      $z[1]++;
      $s=join(';',@z);
      $found=1;
    }
  }
  if ($found==0) {
    push(@s,join(';',"$mday.$month.$year",1));
  }
  &save_array($statistikdat,"statistik",@s);
  &unlock("stat");

  do {                                                      # Wiederhole solange...
    $zuf=int rand($max_userid-$min_userid+1)+$min_userid;   # und berechne eine Zuf-Zahl
    $basketdat=&get_basketdat($zuf);                        # und den dazugeh. Warenkorb
  } while (&exist($basketdat));                             # wie der Warenkorb exisitert
  &new($basketdat,$basketdat);                              # Warenk. ex. nicht. Wird also neu erstellt.
  if ($dif_porto!=0) {
    $portodat=&get_portodat($zuf);
    &new($portodat,$portodat);
  }
  $#new_kunde=-1;                                           # Kundendaten zuweisen
  $new_kunde[$id_kunde_remotehost]=$global[$id_global_remotehost];
  $new_kunde[$id_kunde_kundennr]=$zuf;
  $new_kunde[$id_kunde_tage]=$now_tage;
  $new_kunde[$id_kunde_minuten]=$now_minuten;
  return @new_kunde;
}


# ==========================================================================================
# Fuer eine Kundennr (Input) wird die zugehoerige Profil-Datei zurueckgegeben.
# ==========================================================================================

sub get_basketdat {
  local($filename)=@_;                                      # Kundennr. als Paramter
  while (length($filename)<7) {$filename="0".$filename;}   # "0.." am Anfang einfuegen
  return ($profiledirectory."k$filename.txt");              # Rückgabe
}

sub get_portodat {
  local($filename)=@_;                                      # Kundennr. als Paramter
  while (length($filename)<7) {$filename="0".$filename;}   # "0.." am Anfang einfuegen
  return ($profiledirectory."p$filename.txt");              # Rückgabe
}

# ==========================================================================================
# Gibt anhand der Art.Nr die Daten eines Artikels zurueck.
# ==========================================================================================

sub get_article_data {
 local($id)=@_;                                            # ID einlesen
 local(@article_fields,$article_dat);
  foreach $article_dat (@article_dat) {                     # Artikel durchlaufen
    @article_fields=split(/\;/,$article_dat);               # Felder ermitteln
    @id_search=split(/ \, /,$article_fields[$id_article_id]);

    foreach $id_search (@id_search) {
      if ($id_search eq $id) {           # Falls ID gefunden...

        $article_fields[$id_article_id]=$id_search;
        return @article_fields;                               # Artikel Daten zurückgeben
      }
    }
  }
  return -1;
}

sub by_groupby_num {
  @b = split(/\;/,$b);
  @a = split(/\;/,$a);
  $a[$groupby_index] <=> $b[$groupby_index];    # presuming integers
}


sub by_groupby {
  @b = split(/\;/,$b);
  @a = split(/\;/,$a);
  $a[$groupby_index] cmp $b[$groupby_index];    # presuming integers
}

sub aliste {
  local($t)=@_;

  @aliste=split(/\,/,$user_daten[$uindex{"U_LISTE"}]);
  foreach $aliste (@aliste) {
    $l{$aliste}=1;
  }

  $#article=-1;
  foreach $article_dat (@article_dat) {
    @afelder=split(/\;/,$article_dat);
    if ($l{$afelder[$id_article_id]}==1) {
        push(@article,$article_dat);
    }
  }

  $line=join("\n",&read_data("$tempdirectory$t.htm"));    # Vorlage einlesen
  $line=&parse_line($line);                               # Variablen ersetzen
  print "Content-type: text/html\n\n";
  print $line;                                            # ausgeben
  exit;
}

sub special_request {
  local($f,$c,$t,$start,$dif,$aliste)=@_;

  local(%group)=();

  if ($f ne "GRUPPE") {
    $lfile=$datadirectory."search.txt";
    $#slist=-1;
    push(@slist,$f,$c);
    $i=1;
    while ($input{"f$i"} ne "") {
      push(@slist,$input{"f$i"},$input{"c$i"});
      $i++;
    }
    open(f,">>$lfile");
    print f join(';',@slist,$dif)."\n";
    close(f);
  }

  &process_order;
  $global[$id_global_content]=$c;
  $global[$id_global_content]=~s/\\s/ /g;

  if ($aliste==1) {
   $global[$id_global_content]="Auftragsliste";
    $#new_article_dat=-1;
    @al=&read_data($orderstat);
    foreach $al (@al) {
      @aliste_dat=split(/\;/,$al);
      if ($aliste_dat[2] eq $user_daten[$uindex{"$user_login_field"}]) {
         $l{$aliste_dat[3]}=1;
      }
    }
    $#article=-1;
    foreach $article_dat (@article_dat) {
      @afelder=split(/\;/,$article_dat);
      if ($l{$afelder[$id_article_id]}==1) {
          push(@new_article_dat,$article_dat);
      }
    }
  } else {
    $groupby=$input{"groupby"};

    if ($input{"v"}=~/or/i) {
     $or_mode=1;
     } else {
      $or_mode=0;
    }
    $#new_article_dat=-1;


    $#search_c=-1;
    $i="";
    do {
      $f=$input{"f$i"};
      $cs=$input{"c$i"};


      if ($f=~/^\>\=/) {$input{"c$i"}=">=".$cs;$input{"f$i"}=~s/^\>\=//;}
      elsif ($f=~/^\<\=/) {$input{"c$i"}="<=".$cs;$input{"f$i"}=~s/^\<\=//;}
      elsif ($f=~/^\>/) {$input{"c$i"}=">".$cs;$input{"f$i"}=~s/^\>//;}
      elsif ($f=~/^\</) {$input{"c$i"}="<".$cs;$input{"f$i"}=~s/^\<//;}


      $cs=~ s/[öÖ]/[öÖ]/g;
      $cs=~ s/[äÄ]/[äÄ]/g;
      $cs=~ s/[üÜ]/[üÜ]/g;
      if ($input{"use_perl"}==0) {
        $cs =~ s/[.*?+]//g;
      }

      if ($input{"search"} eq "ALL") {
         if ($cs!~/"(.*?)"/) {
           $cs='"'.$cs.'"';
          }
      }

      while ($cs=~/"(.*?)"/) {
        $vor=$`;
        $hinter=$';
        $treffer=$1;
        $treffer=~s/ /\<_\>/g;
        $cs=qq!$vor$treffer$hinter!;
      }
      push(@search_c,$cs);
      $i++;
   } while ($f ne "");

   foreach $article_dat (@article_dat) {
      @afelder=split(/\;/,$article_dat);

      $i=0;
      $co=0;
      $mo=0;

      $#this_term_ok=-1;
      do  {
        $this_field_ok=0;
        if ($i>0) {
          $f=$input{"f$i"};
          $cs=$search_c[$i];
          $c=$input{"c$i"};
        } else {
          $f=$input{"f"};
          $cs=$search_c[0];
          $c=$input{"c"};
        }

        @felder=split(/\,/,$f);
        @terms = split(/\s+/, $cs);

        $term_or_mode=0;

        $#is_a_not_term=-1;
        $q=0;
        foreach $terms (@terms) {
          if ($terms=~/^or$/i || $terms=~/^ODER$/i) {
            $term_or_mode=1;
          }
          if ($terms=~/^and$/i || $terms=~/^UND$/i) {
            $terms="";
          }
          if ($terms=~/^-(.*)/) {
            $terms=$1;
            $is_a_not_term[$q]=1;
          }
          $q++;
        }

        $#this_term_ok=-1;
        foreach $felder (@felder) {
          if ($felder=~/^\*(.*)/) {
            $index=$index{"$1"};
            if ($#terms==-1) {
              $this_field_ok=1;
            }
            $q=0;
            foreach $terms (@terms) {
              $suche=$terms;
              $suche=~s/\<_\>/ /g;
              if ($afelder[$index]=~/$suche/i) {
                if ($is_a_not_term[$q]==0) {
                  $this_term_ok[$q]=1;
                } else {
                  $this_term_ok[$q]=-1;
                }
              } elsif ($is_a_not_term[$q]==1) {
                if ($this_term_ok[$q]!=-1) {
                  $this_term_ok[$q]=1;
                }
              }
              $q++;
            }
          } else {
            $this_field_ok=0;
            $index=$index{$f};
            if ($c=~/^(\<\=|\>\=|\>|\<)/) {
              $v=$1;
              $vergleich=$c;
              $vergleich=~s/[\>\<\=]//g;

              if ($vergleich eq "") {
                $this_field_ok=1;
              } elsif ( ($afelder[$index]>$vergleich && $v eq '>') ||
                   ($afelder[$index]<$vergleich && $v eq '<') ||
                   ($afelder[$index]>=$vergleich && $v eq '>=') ||
                   ($afelder[$index]<=$vergleich && $v eq '<=')
                 ) {$this_field_ok=1;}
            }
            elsif ($afelder[$index] eq $c || $c eq "") {
              $this_field_ok=1;
            }
          }
        }
        if ($#this_term_ok>=0) {
#          &abbruch($f.$article_dat.$or_mode);
          $this_field_ok=1;
          for ($zz=0;$zz<=$#terms;$zz++) {
             if ($this_term_ok[$zz]<=0) {$this_field_ok=0;}
          }
          if ($term_or_mode==1) {
            $this_field_ok=1;
          }
        }
        if ($this_field_ok==1) {$co++}

        $mo++;
        $i++;

         $f=$input{"f$i"};
        $c=$input{"c$i"};
      } while ($f ne "");


      if ($co==$mo || ($co>=1 && $or_mode==1)) {
        if (defined($index{"NICHT_LIEFERBAR"})==0 || $afelder[$index{"NICHT_LIEFERBAR"}]!=1) {
            if ($groupby eq "" || $group{$afelder[$index{$groupby}]}==0) {
            push(@new_article_dat,$article_dat);
          }
         if ($groupby ne "") {
           $group{$afelder[$index{$groupby}]}=1;
          }
        }
      }
    }


  }

  if ($t eq "") {$t=$template_basket}

  @basket=&format_warenkorb;
  @article=@new_article_dat;

  if ($groupby ne "") {
    $groupby_index=$index{$groupby};
    @article= sort by_groupby @article;
  }
  if ($input{"sort"} ne "") {
    $old_index=$groupby_index;
    $groupby_index=$index{$input{"sort"}};
    @article= sort by_groupby @article;
    $groupby_index=$old_index;
  }
  if ($input{"nsort"} ne "") {
    $old_index=$groupby_index;
    $groupby_index=$index{$input{"nsort"}};
    @article= sort by_groupby_num @article;
    $groupby_index=$old_index;
  }


  if ($start ne "") {
    if ($start eq "0") {
      srand();
      $start=int(rand( int($#article/$dif)+1));
      $start=$start*$dif+1;
    }
    if ($start>0) {
      $end=$start+$dif-1;
      if ($end-1>$#article) {$end=$#article+1}
    }

    $hit_menu="";
    for ($page=1;$page<=int($#article/$dif)+1;$page++) {
      $page_start=($page-1)*$dif+1;
      if ($page_start==1 && $#article==-1) {$page_start=0;}
      $page_end=$page_start+$dif-1;
      if ($page_end>$#article+1) {$page_end=$#article+1}
      $query=$global[$id_global_query];
      $query=~s/start=(\d+)/start=$page_start/g;
      if ($page_start!=$start) {
        $hit_menu.=qq!&#91;<a href="$global[$id_global_skript]?$query">$page_start - $page_end</a>&#93; !;
      }
    }

    # PAGE BACK ermitteln
    if ($start>1) {
      $vorher=$start-$dif;
      if ($vorher<1) {$vorher=1}
      $query=$global[$id_global_query];
      $query=~s/start=(\d+)/start=$vorher/g;
      $global[$id_global_hit_back]=$shoppl."?".$query;
   }


   if ($start+$dif<=$#article+1) {
      $forward=$start+$dif;
      $query=$global[$id_global_query];
      $query=~s/start=(\d+)/start=$forward/g;
      $global[$id_global_hit_forward]=$shoppl."?".$query;
    }



    $global[$id_global_hit_start]=$start;
    $global[$id_global_hit_end]=$end;
    $global[$id_global_hit_max]=$#article+1;
    $global[$id_global_hit_menu]=$hit_menu;

    $#new_article=-1;
    for ($i=$start-1;$i<=$end-1;$i++) {
      push(@new_article,$article[$i]);
    }
    if ($global[$id_global_hit_start]>$global[$id_global_hit_end]) {
      $global[$id_global_hit_start]=$global[$id_global_hit_end];
    }
    @article=@new_article;
  }

    $check_no_variants.="$no_variants,";
  foreach $article (@article) {
    @fields=split(/\;/,$article);
    $war_schon=0;
    for ($i=0;$i<=$#keyw;$i++) {

      if ($fields[$i]=~/ \/ / && $check_no_variants!~/$keyw[$i]\,/) {
        @auswahl=split(/ \/ /,$fields[$i]);
        $binfo{$keyw[$i]."-".$fields[$id_article_id]}.=qq!<select name="${keyw[$i]}_select$fields[$id_article_id]">!;
        $fields[$id_article_binfo].=qq!<select name="${keyw[$i]}_select$fields[$id_article_id]">!;
        foreach $auswahl (@auswahl) {
          $fields[$id_article_binfo].=qq!<option>$auswahl</option>!;
          $binfo{$keyw[$i]."-".$fields[$id_article_id]}.=qq!<option>$auswahl</option>!;
        }
        $fields[$id_article_binfo].=qq!</select> !;
        $binfo{$keyw[$i]."-".$fields[$id_article_id]}.=qq!</select> !;
        $binfoleer{$keyw[$i]}=qq!<input type="hidden" name="${keyw[$i]}_select$fields[$id_article_id]" value=" ">!;
        $article=join(';',@fields);
      } elsif ($fields[$i]=~/ \* / && $check_no_variants!~/$keyw[$i]\,/)  {

        @auswahl=split(/ \* /,$fields[$i]);
         if ($i!=$id_article_costs && $i!=$id_article_id) {
          $binfo{$keyw[$i]."-".$fields[$id_article_id]}.=qq!<select name="${keyw[$i]}_multipreis$fields[$id_article_id]">!;
          $fields[$id_article_binfo].=qq!<select name="${keyw[$i]}_multipreis$fields[$id_article_id]">!;
          for ($j=0;$j<=$#auswahl;$j++) {
            $binfo{$keyw[$i]."-".$fields[$id_article_id]}.=qq!<option value="$j">$auswahl[$j]</option>!;
            $fields[$id_article_binfo].=qq!<option value="$j">$auswahl[$j]</option>!;
          }
          $binfo{$keyw[$i]."-".$fields[$id_article_id]}.=qq!</select> !;
          $fields[$id_article_binfo].=qq!</select> !;
           $article=join(';',@fields);
        }
      }
    }
  }

  if ($cdmodul_ist_aktiv==1) {
    return @article;
  }

  $line=join("\n",&read_data("$tempdirectory$t.htm"));    # Vorlage einlesen
  $line=&parse_line($line);                                 # Variablen ersetzen
  if ($input{"noctype"}!=1) {
    print "Content-type: text/html\n\n";
  }
  print $line;                                              # ausgeben
  exit;
}


# ========================================================================================
# Redirect auf eine beliebige URL
# ==========================================================================================

sub redirect {
  $url=$_[0];
  print "Status: 302 Found\n";
  print "Location: $url\n";
  print "URI: <$url>\n";
  print "Content-type: text/html\r\n\r\n";
}

# ==========================================================================================
# Gibt die "Vielen Dank!" Seite aus, nachdem eine Bestellung abgeschickt wurde.
# Falls eine Redirect-Bedingung definiert wurde und diese zutrifft, wird ein Redirect
# ausgeführt. Dies können Sie nutzen, um die Bestellung auf ein SSL-Bestellformular
# für Kreditkarten-Daten weiterzuleiten.
# Beispiel:
# <form action="[SKRIPT]" method="GET">
# <input type=hidden name="redirect_url" value="Zahlung=Kreditkarte->https://www.IhreFirma.de/secure/creditcard.htm">
# ...
# </form>
# ==========================================================================================

sub output_order {

  # Bestandverwaltung!
  if ($bestand_verwaltung==1) {
    foreach $basket_dat (@basket_dat) {
      @f=split(/\;/,$basket_dat);
      $stock{$f[$id_article_id]}=$f[$id_article_quantity];
    }
    foreach $article_dat (@article_dat) {
       @f=split(/\;/,$article_dat);
       $f[$index{"STOCK"}]-=$stock{$f[$id_article_id]};
       if ($f[$index{"STOCK"}]<0) {
         $f[$index{"STOCK"}]=0;
       }
       $article_dat=join(';',@f);
    }
    &save_array($articledat,"article",@article_dat);
  }

  $rurl=$input{"redirect_url"};
  if ($rurl ne "") {
    @rtypes=split(/\;/,$rurl);
    foreach $rtypes (@rtypes) {
      @condition_url=split(/\-\>/,$rtypes);
      @keyvalue=split(/\=/,$condition_url[0]);
      $key=$keyvalue[0];
      $value=$keyvalue[1];
      if ($input{"$key"} eq $value) {
        &redirect($condition_url[1]);
        exit;
      }
    }
  }
  if ($input{"t"} ne "") {
    $template_send=$input{"t"};
  }
  $line=join("\n",&read_data("$tempdirectory$template_send.htm"));              # Vorlage einlesen
  $line=&parse_line($line);                                 # Varibalen ersetzen
  print "Content-type: text/html\n\n";
  print $line;                                              # ausgeben
}


# ==========================================================================================
# Liefert Menge zurück
# ==========================================================================================

sub get_menge {
  local($menge)=@_;                                         # String einlesen
  $menge=~s/\,/\./g;                                        # Bei der Menge "," durch "." ersetzen
  if ($menge>0) {return $menge};                            # Falls Wert > 0, Wert zurückgeben
  if (defined($menge) && $menge==0) {                       # Falls Menge=0
    if ($menge ne "" && $menge ne "0") {return 1;}          # Falls String nicht "0" oder leer, 1 zurückgeben
  }
  return 0;                                                 # sonst 0 zurückgeben
}

# ==========================================================================================
# Aktualisiert den Warenkorb.
# ==========================================================================================


sub add_basket {
  local($i)=@_;
  local($#basket_new)=-1;                                   # Leeren Warenkorb-Array erstellen
  @basket_new=&get_article_data($input{"id$i"});            # Daten aus Datenbank holen

  if (join('',@basket_new) eq '-1') {
    &abbruch(qq!Der Artikel $input{"id$i"} existiert nicht (mehr).!);
  }

  if ($basket_new[$index{"STOCK"}]<$input{"quantity$i"} && $bestand_verwaltung==1 && $fehlermeldung_bei_bestand_von_null==1) {
    &abbruch(qq!Sie möchten die Menge $input{"quantity$i"} des Artikels <b>$basket_new[$index{"NR"}]</b> bestellen, wir haben zur Zeit aber nur einen Bestand von $basket_new[$index{"STOCK"}] verfügbar.<p> Wenn Sie sich besonders für diesen Artikel interessieren, <a href="mailto:$email">kontaktieren Sie uns bitte per Mail</a>.!);
  }

  $basket_new[$id_article_quantity]=0;                      # zum vergleichen
  $basket_new[$id_article_costs]=~s/\,/\./g;                # Beim Preis "," durch "." ersetzen

  $basket_new[$id_article_quantity]=$input{"quantity$i"};   # Menge zuweisen
  $basket_new[$id_article_quantity]=~s/\,/\./g;             # Bei der Menge "," durch "." ersetzen

   foreach $keyw (@keyw) {
       if ($input{"${keyw}_select$basket_new[$id_article_id]"} ne "") {
         $basket_new[$index{$keyw}]=$input{"${keyw}_select$basket_new[$id_article_id]"};
         $basket_new[$index{$keyw}]=~s/\s\/\s/\//g;
      }
    }

  for ($j=0;$j<=$#keyw;$j++) {
   if ($input{"${keyw[$j]}_multipreis$basket_new[$id_article_id]"} ne "") {
     $mpreisnr=$input{"${keyw[$j]}_multipreis$basket_new[$id_article_id]"};
     foreach $basket_new (@basket_new) {
       if ($basket_new=~/ \* /) {
          @auswahl=split(/ \* /,$basket_new);
          $basket_new=$auswahl[$mpreisnr]
        }
      }
    }
  }


  if ($basket_new[$id_article_costs]=~/\?/) {
     @p=split(/\ /,$basket_new[$id_article_costs]);
     @pq=split(/\?/,$p[0]);
     $basket_new[$id_article_quantity]=$pq[1];
  }
  $basket_new=join(';',@basket_new);

  $gef=0;
  foreach $basket_dat (@basket_dat) {
    @bf=split(/\;/,$basket_dat);
    $old_quantity=$bf[$id_article_quantity];
    $bf[$id_article_quantity]=$basket_new[$id_article_quantity];
    if (join(';',@bf) eq join(';',@basket_new)) {
      $gef=1;
      if ($mengen_im_warenkorb_addieren==1) {
        $bf[$id_article_quantity]=$basket_new[$id_article_quantity]+$old_quantity;
      }
      $basket_dat=join(';',@bf);
    }
  }

  if ($gef==0) {
    push(@basket_dat,$basket_new);
    push(@basket_dat_new,$basket_new);
  }
}

sub process_order {
  local($i);
  local(@keys,@values,@field);

  $#keys=-1;
  $#values=-1;
  foreach $keyval (@keyval) {                               # Array keval durchlaufen
    @field=split(/\;/,$keyval);                             # Felder ermitteln
    push(@keys,$field[0]);                                  # key in Array keys speichern
    push(@values,$field[1]);                                # value in Array values speichern
  }

  $#basket_new=-1;
  for ($i=0;$i<=$#basket_dat;$i++) {
    $input{"wk_quantity$i"}=~s/\,/\./g;
    if ($input{"wk_delete$i"} ne "" || $input{"wk_delete$i.x"} ne "") {
      $input{"wk_quantity$i"}=0;
    }
    if ($input{"wk_quantity$i"} ne "" || $input{"ok$i"} ne "") {

      @basket_fields=split(/\;/,$basket_dat[$i]);
      if ($basket_fields[$id_article_quantity]!=$input{"wk_quantity$i"}) {

        if ($input{"wk_quantity$i"} ne "") {

          if ($basket_fields[$index{"STOCK"}]<$input{"wk_quantity$i"} && $bestand_verwaltung==1 && $fehlermeldung_bei_bestand_von_null==1) {
            &abbruch(qq!Sie möchten die Menge $input{"wk_quantity$i"} des Artikels <b>$basket_fields[$index{"NR"}]</b> bestellen, wir haben zur Zeit aber nur einen Bestand von $basket_fields[$index{"STOCK"}] verfügbar.<p> Wenn Sie sich besonders für diesen Artikel interessieren, <a href="mailto:$email">kontaktieren Sie uns bitte per Mail</a>.!);
          }
          $basket_fields[$id_article_quantity]=$input{"wk_quantity$i"};
          $basket_dat[$i]=join(';',@basket_fields);
        }
      }
      if ($input{"ok$i"} ne "") {
        foreach $keyw (@keyw) {
          if ($input{"${keyw}_select$i"} ne "") {
            $basket_fields[$index{$keyw}]=$input{"${keyw}_select$i"};
            $basket_fields[$index{$keyw}]=~s/\s\/\s/\//g;
          }

        }
        for ($j=0;$j<=$#keyw;$j++) {
          if ($input{"${keyw[$j]}_multipreis$i"} ne "") {
            $mpreisnr=$input{"${keyw[$j]}_multipreis$i"};
            foreach $basket_fields (@basket_fields) {
              if ($basket_fields=~/ \* /) {
                @auswahl=split(/ \* /,$basket_fields);
                $basket_fields=$auswahl[$mpreisnr]
              }
            }
          }
        }
      }
      if ($input{"wk_quantity$i"}!=0 || $input{"wk_quantity$i"} eq "") {push(@basket_new,join(';',@basket_fields))};
    } else {push(@basket_new,$basket_dat[$i]);}
  }
  @basket_dat=@basket_new;

  if ($input{"change"}==0) {                                # falls Aufruf NICHT vom Warenkorb kommt (keine Änderung, nur NEUE Artikel)
    $i=0;

###########################################################
## Überprüfung einer Übergabe durch:
## <a href="/cgi-bin/webshop.pl?Nr1234=3"> oder
## <input type=submit name="Nr1234" value="Bestellen">
##

    for ($k=0;$k<=$#keys;$k++) {                            # Alle Keys durchlaufen
       if ($keys[$k]=~/^NrAddWk$/) {
       $input{"id$i"}=$values[$k];
       $input{"quantity$i"}=1;
       if ($input{"MengeAddWk"} ne "") {$input{"quantity$i"}=$input{"MengeAddWk"}}
       &add_basket($i);
       $i++;
     }
     elsif ($keys[$k]=~/^Nr(.*)$/) {                           # Falls Key = NrXXX
        $nr_field=$1;

        if ($nr_field=~/\.y$/) {                           # Bei Übergabe durch "type=image" .y nicht berücksichtigen
          $menge=0;
        }
        elsif ($nr_field=~/\.x$/ && $war_schon{$nr_field}==0) {                        # Bei Übergabe durch "type=image" .x = Menge 1
          $nr_field=~s/\.x$//;
          $menge=1;
        } elsif ($war_schon{$nr_field}==0) {
          $menge=&get_menge($values[$k]);                   # Menge aus Value ermitteln
        }

        if ($menge>0 && $war_schon{$nr_field}==0) {                                     # Falls Menge>0
          $war_schon{$nr_field}=1;
          $input{"id$i"}=$nr_field;                         # Neuer Warenkorbeintrag mit NrXXX
          $input{"quantity$i"}=$menge;                      # und Menge
          &add_basket($i);
          $i++;                                             # nächster freier Platz
        }
      }
    }

##
###########################################################

###########################################################
## Überprüfung einer Übergabe durch:
## <select name="Def1">
## <option value="1234">Artikel1
## <option value="1235">Artikel2>
## </select>
## <input type=submit name="Menge1" value="Bestellen">
###

    for ($k=0;$k<=$#keys;$k++) {                            # Alle Keys durchlaufen
      if ($keys[$k]=~/^Def(.*)$/) {                         # Falls Key = DefXXX
        $defnr=$1;                                          # DefNr ermitteln
        $artnr=$values[$k];                                 # ArtikelNummer ist der Value
        $menge=&get_menge($input{"Menge$defnr"});           # Menge ermitteln
        if ($menge>0) {                                     # Falls Menge>0
          $input{"id$i"}=$artnr;                            # Neuer Warenkorbeintrag
          $input{"quantity$i"}=$menge;                      # Menge
          &add_basket($i);
          $i++;                                             # nächster freier Platz
        }
      }
    }

##
###########################################################
  }

    $i=0;
    while ($input{"id$i"} ne "") {                          # Alle Einträge des WKs durchlaufen, um $i auf einen freien Eintrag zu setzen
      $i++;
    }

###########################################################
## Manuelle Eingabe erlauben!
##


    $z=0;
    do {
      $#basket_new=-1;
      if ($z==0) {$nr="";} else {$nr=$z}
      for ($k=0;$k<=$#keys;$k++) {                            # Alle Keys durchlaufen
        if ($keys[$k]=~/add_(.*)$nr$/) {                     # Falls Key = add_XXXX
          $basket_new[$index{$1}]=$values[$k];
         }
      }
      if ($basket_new[$index{"MENGE"}]>0 || $basket_new[$index{"MENGE"}] ne "") {
          if ($basket_new[$index{"MENGE"}]==0) {$basket_new[$index{"MENGE"}]=1;}

           $gef=0;
    foreach $basket_dat (@basket_dat) {
      @bf=split(/\;/,$basket_dat);
      $old_quantity=$bf[$id_article_quantity];
      $bf[$id_article_quantity]=$basket_new[$id_article_quantity];
      if (join(';',@bf) eq join(';',@basket_new)) {
        $gef=1;
        if ($mengen_im_warenkorb_addieren==1) {
          $bf[$id_article_quantity]=$basket_new[$id_article_quantity]+$old_quantity;
        }
        $basket_dat=join(';',@bf);
      }
    }

    if ($gef==0) {

          push(@basket_dat,join(';',@basket_new));
          push(@basket_dat_new,join(';',@basket_new));

          }
      }
      $z++;
    } while (defined($input{"add_MENGE$nr"}) || $z<=1);
##
###########################################################


  &save_array($basketdat,$basketdat,@basket_dat);           # Warenkorb speichern
}


# ==========================================================================================
# Liest und formatiert die Variablen fuer den Warenkorb
# ==========================================================================================

sub format_warenkorb {
  local($is_mail,$divident)=@_;
  local($index);
  if ($divident==0) {$divident=1;}
  local(@article);                                          # Artikel Array erstellen
  $global[$id_global_sumall]=0;                             # Bestellsume auf "0" setzen
  $i=0;                                                     # Zähler auf 0 setzen
  $#article=-1;                                             # Artikel Array leeren

  $check_no_variants.="$no_variants,";

  $only_gutschein=1;
  foreach $basket_dat (@basket_dat) {
   @f=split(/\;/,$basket_dat);
   if ($f[$index{"NR"}]!~/G_(\d+)/) {
     $only_gutschein=0;
   }
  }

  foreach $basket_dat (@basket_dat) {                       # Warenkorbeinträge durchlaufen
    @fields=split(/\;/,$basket_dat);                        # Felder ermitteln
    $#article_fields=-1;                                    # Leeren Artikel Array erstellen

    foreach $keyw (@keyw) {
      $index=$index{$keyw};
      if ($fields[$index]=~/ \/ / && $check_no_variants!~/$keyw\,/)  {
        if ($is_mail==1) {
          $fausgabe= qq!Die Bestelldaten können noch nicht verschickt werden, da Sie noch Angaben im Warenkorb zu mindestens einem Artikel festlegen müssen. Im <a href="$shoppl">Warenkorb</a> können Sie dazu in einer!;
          $fausgabe.=qq! Auswahlbox die Einstellung auswählen. Anschliessend drücken Sie bitte jeweils auf den OK-Button neben der Auswahlbox.!;
          &abbruch($fausgabe);
        }
        @auswahl=split(/ \/ /,$fields[$index]);
        $article_fields[$index]=qq!<select name="${keyw}_select$i">!;
        foreach $auswahl (@auswahl) {
          $article_fields[$index].=qq!<option>$auswahl</option>!;
        }
        $article_fields[$index].=qq!</select> <input type=submit name="ok$i" value="OK">!;
      }
      elsif ($fields[$index]=~/ \* /  && $check_no_variants!~/$keyw\,/)  {
        if ($is_mail==1) {
          $fausgabe= qq!Die Bestelldaten können noch nicht verschickt werden, da Sie noch Angaben im Warenkorb zu mindestens einem Artikel festlegen müssen. Im <a href="$shoppl">Warenkorb</a> können Sie dazu in einer!;
          $fausgabe.=qq! Auswahlbox die Einstellung auswählen. Anschliessend drücken Sie bitte jeweils auf den OK-Button neben der Auswahlbox.!;
          &abbruch($fausgabe);
        }
        @auswahl=split(/ \* /,$fields[$index]);
        if ($index!=$id_article_costs && $index!=$id_article_id) {
          $article_fields[$index]=qq!<select name="${keyw}_multipreis$i">!;
          for ($j=0;$j<=$#auswahl;$j++) {
            $article_fields[$index].=qq!<option value="$j">$auswahl[$j]</option>!;
          }
          $article_fields[$index].=qq!</select> <input type=submit name="ok$i" value="Ok">!;
        }
        else {$article_fields[$index]=$auswahl[0];}
      } else {
        $article_fields[$index]=$fields[$index];
      }
    }

    $article_fields[$id_article_quantity]=$fields[$id_article_quantity];     # Menge
    $article_fields[$id_article_newquantity].=qq!<INPUT TYPE=TEXT SIZE=3 NAME="wk_quantity$i" VALUE="$fields[$id_article_quantity]">!; # Menge als Text Feld

    if ($fields[$id_article_costs]=~/\?/) {
      @p=split(/\ /,$fields[$id_article_costs]);
      foreach $p (@p) {
        @pq=split(/\?/,$p);
        if ($fields[$id_article_quantity]>=$pq[1]) {
          $article_fields[$id_article_sum]= &format_sum($fields[$id_article_quantity]*&format_sum($pq[0]/$divident));
        }
      }
    } else {
      $article_fields[$id_article_sum]=&format_sum($fields[$id_article_quantity]*&format_sum($fields[$id_article_costs]/$divident));    # Summe berechnen
    }

    $global[$id_global_sumall]+=$article_fields[$id_article_sum]; # Gesamtbestellsumme
    push(@article,join(';',@article_fields));                     # Neuen Artikel einfügen
    $i++;
  }


  if ($dif_porto==1) {                                      # Falls untersch. Versandk.art
    if ($input{"porto"} ne "") {                            # Falls Versandk.art angegeben
      $porto=$input{"porto"};                               # Versandk.art einlesen
      &save_array($portodat,"porto",$porto);                # ... und speichern
    }

    $gef=0;                                                 # Flag gefunden auf 0 sezten
    foreach $porto_daten (@porto_daten) {                   # Alle Versandk.arten durchlaufen
      @pdaten=split(/\;/,$porto_daten);
      if ($pdaten[0] eq $porto) {                           # Falls zur Zeit ausgewählte Versandk.art
        $gef=1;                                             # Flag gefunden auf 0 setzen
        last;
      }
    }
    if ($gef==0) {@pdaten=split(/\;/,$porto_daten[0]);}     # Falls nicht gefunden, Versandk. der 1.Zeile nehmen
    $porto=$pdaten[0];
    $this_porto=$pdaten[1];
    $global[$id_global_versandkfreiab]=$pdaten[2];
    $global[$id_global_versandkosten]=&format_sum($this_porto/$divident);        # sonst Versandkosten = Porto

    $ptext="";
    foreach $porto_daten (@porto_daten) {
      @pdaten=split(/\;/,$porto_daten);
      if ($pdaten[0] eq $porto) {$selec="SELECTED "} else {$selec=""}
      $ptext.= qq!<OPTION ${selec}VALUE="$pdaten[0]">$pdaten[0]!;
    }
    $ptext=qq!<select name="porto">$ptext</select>!;
    $global[$id_global_porto_auswahl]=$ptext;
    $global[$id_global_porto]=$porto;
  } else {
    $global[$id_global_versandkosten]=&format_sum($versandk_hoehe/$divident);        # sonst Versandkosten = Porto
  }

  if (($global[$id_global_min_order]/$divident)<=$global[$id_global_sumall] || $min_order_typ==0 || $min_order_typ==1) {
   $global[$id_global_min_order_zuschlag]="";
  }
   if (($global[$id_global_min_order]/$divident)<=$global[$id_global_sumall] && $min_order_typ==1) {
    $global[$id_global_min_order]="";
  }

  if ($global[$id_global_sumall]>=($global[$id_global_versandkfreiab]/$divident) && $global[$id_global_versandkfreiab]!=0) {    # Falls Summe > Versandk._frei_ab
    $global[$id_global_versandkosten]=0;                 # keine Versandkosten
  }
  if ($only_gutschein==1) {
    $global[$id_global_versandkosten]=0;
  }
  $global[$id_global_sumallv]=$global[$id_global_sumall]+$global[$id_global_versandkosten]+($global[$id_global_min_order_zuschlag]/$divident); # Summe inkl. Versandk. berechnen
  $global[$id_global_sumall]=&format_sum($global[$id_global_sumall]);           # Summe formatieren
  $global[$id_global_sumallv]=&format_sum($global[$id_global_sumallv]);         # Summe inkl. Versandk. formatieren
  $global[$id_global_versandkfreiab]=&format_sum($global[$id_global_versandkfreiab]);   # Versandk. frei ab formatieren
  if ($global[$id_global_versandkosten] ne "") {
    $global[$id_global_versandkosten]=&format_sum($global[$id_global_versandkosten]);   # Versandk.
  }
#   &abbruch($global[$id_global_sumall]);
  return @article;
}


# ==========================================================================================
# Der Parser fuer HTML und Mail Templates.
# Erkennt eine Reihe von Schluesselworten sowie die Befehle "IF" (mit OR Verknuepfung),
# "IFTHIS" und "REPEAT".
# ==========================================================================================

sub parse_line {
  local($linesave)=@_;
  local($array_typ,$vor_suche,$nachher,$ersetzen,$count,$i);
  local($leftright,$leftright_num);

  $linesave=~s/\%5BSKRIPT\%5D/\[SKRIPT\]/g;
  while ($linesave=~/\[((LEFT|RIGHT)=(\d+)_)?([^\]]+)\]\n?/) {
    $code=$4;
    $leftright=$2;
    $leftright_num=$3;
    local($vorher)=$`;
    local($nachher)=$';
    $code=~s/\n/ /g;

   while ($code=~/\[/) {
     do {
       $nachher=~/\]/;
       $code.=']'.$`;
       $nachher=$';
       $open=($code=~s/\[/\[/g);
       $close=($code=~s/\]/\]/g);
     } while ($open!=$close);
     $code=&parse_line($code);
   }

    $divident="";
     if ($code=~/(.*)\/([\d|\.]+)$/) {
       $code=$1;
       $divident=$2;
     }

     foreach $currency (@currency) {
       @c=split(/\=/,$currency);
       if ($code=~/(.*)_$c[0]$/) {
         $code=$1;
         if ($divident eq "") {$divident=1;}
         $divident=$divident*$c[1];
         $acurrency=$c[0];
       }
     }

     if ($code=~/(.*)_HTML$/) {
      $code=$1;
      $html=1;
     } else {$html=0;}

     if ($code=~/(.*)_TEXTAREA$/) {
      $code=$1;
      $textarea=1;
     } else {$textarea=0;}

     if ($code eq "HIS_ON") {
       $his_off=0;
     }
     if ($code eq "HIS_OFF") {
      $his_off=1;
     }

    if ($code=~/(.*)_URLENC$/) {
      $code=$1;
      $urlenc=1;
    } else {$urlenc=0;}

    if ($code=~/(.*)_KLEIN$/) {
      $code=$1;
      $klein=1;
    } else {$klein=0;}

     if ($code=~/(.*)_CD$/) {
      $code=$1;
      $cd=1;
    } else {$cd=0;}

    if ($code=~/(.*)_CDNAME$/) {
      $code=$1;
      $cdname=1;
    } else {$cdname=0;}

     if ($code=~/(.*)_FIRST$/) {
      $code=$1;
      $first=1;
    } else {$first=0;}

    if ($code=~/^IF(\d|)_(.*)/) {
      $ok=0;
      $if_nr=$1;
      @if=split(/_OR_/,$2);
      $if_field="";
      foreach $if (@if) {
        if ($if=~s/NOT_//==0) {$not_text="";$not=0} else {$not_text="NOT_";$not=1;}

        if ($if=~/PRINT\((.*)\)/) {
          $expr=$1;
          $expr=~s/\$/\$HIS_SCRIPT/g;
          $expr=~s/\<\</\[/g;
          $expr=~s/\>\>/\]/g;
          $expr=~s/\@/\@HIS_SCRIPT/g;
          $count=eval($expr);
          if ($count==0) {$count=-1}
          $if_field="PRINT";
        } elsif ($if=~/^\((.*)\)/) {
          $expr=$1;
          $expr=~s/\$/\$HIS_SCRIPT/g;
          $expr=~s/\<\</\[/g;
          $expr=~s/\>\>/\]/g;
          $expr=~s/\@/\@HIS_SCRIPT/g;


          $count=eval($expr);
          if ($count==0) {$count=-1}
          $if_field="";
       } else {
        $if_field=$if;
        $array_typ=$multi{"$if"};
        $index=$index{"$if"};
        if ($array_typ==1) {
           if ($#article>=0) {
             @array=split(/\;/,$article[$count[$array_typ]]);
           } else {
             @array=split(/\;/,$basket[$count[$array_typ]]);
           }
           if ($array[$index] eq "") {$count=-1} else {$count=0;}
        } else {
          if ($input{$if} ne "") {$count=0} else {$count=-1}
        }
        if ($if eq "ARTIKEL")   {$count=$#article}
        if ($if eq "WARENK")    {$count=$#basket}
        if ($if eq "NEW_ORDER") {$count=$#basket_dat_new;}
        if ($array_typ==5) {if ($global[$index] eq "" || $global[$index] eq "0.00") {$count=-1} else {$count=0;}}
        if ($if eq "ORDERDAT") {$count=$#keyval;}
        if ($if eq "KUNDE")      {$count=$#user_daten;}
        }
        if ($count!=-1 && $not==0) {$ok++}
        if ($count==-1 && $not==1) {$ok++}
      }
        if ($if_field ne "") {
          $nachher=~s/\[IF${if_nr}_${not_text}${if_field}_END\]\n?//; $nach_suche=$';
        } else {
          $nachher=~s/\[IF${if_nr}_${not_text}${if_field}END\]\n?//; $nach_suche=$';
        }
       if ($ok==0) {
         $linesave=$vorher.$nach_suche;
       } else {
        $linesave=$vorher.$nachher;
      }
    }
    elsif ($code=~/^REPEAT_(.*)/) {
      $array_typ=$multi{"$1"};
      $old_repeat_mode=$repeat_mode;
      if ($1 eq "ARTIKEL")   {$count=$#article;$repeat_mode=1;$array_typ=1}
      if ($1 eq "WARENK")    {$count=$#basket;$repeat_mode=2;$array_typ=1}
      if ($1 eq "NEW_ORDER") {$count=$#basket_dat_new;$repeat_mode=3;$array_typ=1}
      if ($1 eq "ORDERDAT")  {$count=$#keyval;$array_typ=6}
      if ($1 eq "RORDER") {
         $array_typ=8;
         $repeat_mode=8;
         if ($input{"month"} eq "") {$input{"month"}=$month;}
         if ($input{"year"} eq "") {$input{"year"}=$year;}
         @order_list=&get_order_list($input{"month"},$input{"year"},$partner_daten[$pindex{"$partner_login_field"}]);
         $count=$#order_list;
      }
      if ($1 eq "INFO")      {
         @array=split(/\;/,$article[$count[1]]);
         @subarray=split(/ \* /,$array[$index{"PREIS"}]);
         $count=$#subarray;
         $repeat_mode=4;
         $array_typ=2;
      }
      if ($1 eq "PARTNER")   {
         $count=0;
         $repeat_mode=5;
         $array_typ=7;
      }
      $repeat_keyword=$1;
      $nachher=~/\[REPEAT_${repeat_keyword}_END\]/;
      $vor_suche=$`;$nachher=$';
      $ersetzen="";
      for ($count[$array_typ]=0;$count[$array_typ]<=$count;$count[$array_typ]++) {
        $ersetzen.=&parse_line($vor_suche) ;
      }
      $repeat_mode=$old_repeat_mode;
      $linesave=$vorher.$ersetzen.$nachher;
    }
    else {
      $index=$index{"$code"};
      $array_typ=$multi{"$code"};

      if ($code eq "APREIS") {$index=$index{"PREIS"}};

      if ($leftright eq "LEFT")  {$left=$leftright_num;}  else {$left=0;}
      if ($leftright eq "RIGHT") {$right=$leftright_num;} else {$right=0;}

       if ($code=~/PIC(\d+)\_SCALE_(.*)/) {
        $code="PIC$1";
        $scale=$2;
      }
      if ($code=~/PIC(\d+)\_WIDTH_(.*)/) {
        $code="PIC$1";
        $do_width=$2;
      }


      $align="";
      if ($code=~/PIC(\d+)\_(.*)/) {
        $code="PIC$1";
        $align=" align=$2";
      }

        if ($code=~/PIC(\d+)/) {

          if ($repeat_mode==1) {@array=split(/\;/,$article[$count[1]])}
          if ($repeat_mode==2) {@array=split(/\;/,$basket[$count[1]])}
#         @array=split(/\;/,$article[$count[1]]);
         $pichttpnr=$1-1;                # PIC1 => $pichttp[0], PIC2 => $pichttp[1] usw.

         $this_pic=$array[$index{"$pic_field_name[$pichttpnr]"}];
         @a=split(/ \* /,$this_pic);
         $this_pic=$a[0];

         $this_pic=~s/\s//g;
         $this_pic=~s/[\\\/]//g;

         $file=$this_pic;
         $filegif=$this_pic.".gif";
         $filejpg=$this_pic.".jpg";
         $filename="";
         if    (&exist("$picverz[$pichttpnr]$file") && $this_pic ne "")    {$filename="$pichttp[$pichttpnr]$file";    ($width,$height)=&get_gif($picverz[$pichttpnr],$file)}
         elsif (&exist("$picverz[$pichttpnr]$filegif") && $this_pic ne "") {$filename="$pichttp[$pichttpnr]$filegif"; ($width,$height)=&get_gif($picverz[$pichttpnr],$filegif)}
         elsif (&exist("$picverz[$pichttpnr]$filejpg") && $this_pic ne "") {$filename="$pichttp[$pichttpnr]$filejpg"; ($width,$height)=&get_gif($picverz[$pichttpnr],$filejpg)}
         elsif ($use_default_pic==1) {$filename="$pichttp[$pichttpnr]$default_pic"; ($width,$height)=&get_gif($picverz[$pichttpnr],$default_pic)}

          if ($scale ne "") {
              $width=int($width/100*$scale);
              $height=int($height/100*$scale);
          }
            if ($do_width ne "" && $width!=0 && $height!=0) {
              $owidth=$width;
              $width=$do_width;
              $height=int($width/$owidth*$height);
          }

        if ($filename ne "") {
          $array[$index]=qq!<img src="$filename"$align alt="[KATEGORIE] [TITEL]" title="[KATEGORIE] [TITEL]">!;

          if ($width!=0 && $height!=0) {
             $array[$index]=qq!<img src="$filename"$align width=$width height=$height border=0 title="[KATEGORIE] [TITEL]" alt="[KATEGORIE] [TITEL]">!;
          }
        } else {
          $array[$index]="";
        }
      } else {
         if ($array_typ==1 || $array_typ==2) {
          if ($code=~/BINFO(\d+)/) {$array_typ=1;}
          if ($repeat_mode==1) {@array=split(/\;/,$article[$count[$array_typ]])}
          if ($repeat_mode==2) {@array=split(/\;/,$basket[$count[$array_typ]])}
          if ($repeat_mode==3) {@array=split(/\;/,$basket_dat_new[$count[$array_typ]])}
          if ($repeat_mode==4) {
            @array=split(/\;/,$article[$count[1]]);
            @array=split(/ \* /,$array[$index]);
            $array[$index]=$array[$count[2]];
          }
        };
        if ($repeat_mode==5) {
          if ($#partner_daten!=-1) {
            @array=@partner_daten;
          } else {
            @array=&get_partner_data($input{"G_pid"});
          }
          $index=$pindex{"$code"};
        }

        if ($array_typ==5) {@array=@global;};
        if ($array_typ==6) {@array=split(/\;/,$keyval[$count[$array_typ]])};
        if ($repeat_mode==8) {@array=split(/\|/,$order_list[$count[$array_typ]])};
      }
       if ($code=~/^(U_(.*))/ && $repeat_mode!=5) {
         $fieldname=$1;
         if ($fieldname=~/\=/) {
           @kv_ausgabe=split(/\-\>/,$fieldname);
           @kv=split(/\=/,$kv_ausgabe[0]);
           if ($user_daten[$uindex{$kv[0]}] eq $kv[1]) {
             $array[$index]=$kv_ausgabe[1];
             $uindex{$code}=1;
           } else {
             $array[$index]="";
           }
         } else {
           $array[$index]=$user_daten[$uindex{$1}];
         }
       }
       if ($code=~/^(P_(.*))/) {
         $fieldname=$1;
         if ($fieldname=~/\=/) {
           @kv_ausgabe=split(/\-\>/,$fieldname);
           @kv=split(/\=/,$kv_ausgabe[0]);
           if ($partner_daten[$pindex{$kv[0]}] eq $kv[1]) {
             $array[$index]=$kv_ausgabe[1];
             $uindex{$code}=1;
           } else {
             $array[$index]="";
           }
         } else {
           $array[$index]=$partner_daten[$pindex{$1}];
         }
       }

       if ($code eq "PREIS") {
         $array[$index]=&format_sum($array[$index]);
       }

       if ($code eq "APREIS") {
           @p=split(/\ /,$array[$id_article_costs]);
           foreach $p (@p) {
              @pq=split(/\?/,$p);
              if ($array[$id_article_quantity]>=$pq[1]) {
                $preis=&format_sum($pq[0]);
              }
           }
           if ($array[$id_article_quantity]==0) {
             @pq=split(/\?/,$p[0]);
             $preis=&format_sum($pq[0]);
           }
           $array[$index]=&format_sum($preis);
       }


      if ($index{"$code"} eq "" && $uindex{"$code"} eq "" && $pindex{"$code"} eq "" ) {
         $array[$index]=$input{"$code"};
      }

      if ($code=~/BINFO(\d+)/) {
         $array_typ=1;
         @array=split(/\;/,$article[$count[$array_typ]]);
         $nr=$1;
         $binfo=$array[$id_article_binfo];
         @binfo=split(/\<select/,$binfo);
         $array[$index]="<select ".$binfo[$nr];
       }
       if ($code=~/BINFO_(.*)/) {
         $array_typ=1;
         @array=split(/\;/,$article[$count[$array_typ]]);
         $array[$index]=$binfo{$1."-".$array[$id_article_id]};
       }

       if ($code=~/PRINT(L|C|F|I|T|)\((.*)\)/) {
        $mode=$1;
        $var=$2;
        $var=~s/\$/\$HIS_SCRIPT/g;
        $var=~s/\<\</\[/g;
        $var=~s/\>\>/\]/g;
        $array[$index]=eval($var);
        if ($mode eq 'I'){
          $array[$index]="";
        }
        if ($mode eq 'F') {
          $array[$index]=&format_sum($array[$index]);
        }
        if ($mode eq 'C') {
          $array[$index]=~ tr/a-z/A-Z/;
        }
        if ($mode eq 'L') {
          $array[$index]=~ tr/A-Z/a-z/;
        }
        if ($mode eq 'T') {
          $array[$index]=&format_tausender($array[$index]);
        }
      }
      if ($code=~/^\$/) {
         if ($code=~/\$FIELD_BASKET_(.*)\=(.*)/) {
           @array=split(/\;/,$basket_dat[$count[1]]);
           $array[$index{$1}]=eval($2);
           $basket_dat[$count[1]]=join(';',@array);
           @basket=&format_warenkorb;
         }
         $code=~s/\$/\$HIS_SCRIPT/g;
         $code=~s/\<\</\[/g;
         $code=~s/\>\>/\]/g;
         eval($code);
         if ($code=~/^\$HIS_SCRIPTG_(.*)\=/) {
            $variable_name=$1;
            $variable_name=~s/\s//g;
            $global{"G_".$1}=eval('$HIS_SCRIPTG_'.$variable_name);
            $input{"G_".$1}=$global{"G_".$1};
            &search_user($global[$id_global_userid]);
         }
         $array[$index]="";
      }

      if ($code eq "NO_VERSANDKOSTEN") {
         &abbruch("No Versandk!");
      }
      if (($code eq "GESAMTSUMME" || $code eq "GESAMTSUMME_VERSAND" || $code eq "VERSANDKOSTEN")
           && $divident==0) {
          &format_warenkorb(0,1);
          $array[$index{"GESAMTSUMME_VERSAND"}]=$global[$id_global_sumallv];
          $array[$index{"GESAMTSUMME"}]=$global[$id_global_sumall];
          $array[$index{"VERSANDKOSTEN"}]=$global[$id_global_versandkosten];
       }

      if ($divident!=0) {
        if ($code eq "SUMME") {
          if ($array[$id_article_costs]=~/\?/) {
            @p=split(/\ /,$array[$id_article_costs]);
            foreach $p (@p) {
              @pq=split(/\?/,$p);
              if ($array[$id_article_quantity]>=$pq[1]) {
                $preis=&format_sum($pq[0]/$divident);
              }
            }
            $array[$index]=&format_sum($preis*$array[$id_article_quantity]);
          } else {
            $array[$index]=&format_sum($array[$index{"PREIS"}]/$divident);
            $array[$index]=$array[$index]*$array[$id_article_quantity];
            $array[$index]=&format_sum($array[$index]);
          }

        }
        elsif ($code eq "GESAMTSUMME") {
          &format_warenkorb(0,$divident);
          $array[$index]=$global[$id_global_sumall];
        }
        elsif ($code eq "GESAMTSUMME_VERSAND") {
          &format_warenkorb(0,$divident);
          $array[$index]=$global[$id_global_sumallv];
        }
        elsif ($code eq "VERSANDKOSTEN") {
          &format_warenkorb(0,$divident);
          $array[$index]=$global[$id_global_versandkosten];
        }
        else {
           $array[$index]=&format_sum($array[$index]/$divident);
        }
      }

      if ($urlenc==1) {$array[$index]=&url_encode($array[$index]);}
      if ($cd==1) {$array[$index]=&cd_encode($array[$index]);}
      if ($cdname==1) {$array[$index]=&cdname_encode($array[$index]);}

      if ($klein==1) {
         $array[$index]=~ y/A-Z/a-z/;
         $array[$index]=~s/ /\-/g;
      }
      if ($first==1) {
        @a=split(/ \* /,$array[$index]);
        $array[$index]=$a[0];
      }
      if ($html==1) {
         foreach $html_convert (@html_convert) {
           @d=split(/\=/,$html_convert);
           $array[$index]=~s/$d[0]/$d[1]/g;
         }
      }
      if ($textarea==1) {
        $array[$index]=~s/<br>/\n/g;
      }
      if ($code eq "NEXT_REPEAT") {
        $count[1]++;
        $count[2]++;
        $array[$index]="";
      }
       if ($code eq "NEXT_INFO") {
        $count[2]++;
        $array[$index]="";
      }
       if ($code=~/^INCLUDE\=(.*)/) {
        $include_src=$1;
        $lines=join("\n",&read_data($include_src));
        $array[$index]=$lines;
      }
      if ($code=~/^INCLUDE_SCRIPT\=(.*)/) {
        $include_src=$1;
        if ($include_src=~/\?/) {
         @s=split(/\?/,$include_src);
         $include_src=$s[0];
         $include_query=$s[1];
        }
        $ENV{'QUERY_STRING'}="$include_query";
        open(f,"$include_src |");
        @include_lines=<f>;
        close(f);
        $array[$index]=join("\n",@include_lines);
        $array[$index]=~s/Content-Type: text\/html//ig;
      }
      if ($left!=0 || $right!=0) {$array[$index]=&correct_length($array[$index],$left,$right);}

      if ($his_off==1 && $code ne "HIS_OFF") {
        $array[$index]="*+~$code~+*";
       }

      $linesave=$vorher.$array[$index].$nachher;
    }
  }
  $linesave=~s/\*\+\~/[/g;
  $linesave=~s/\~\+\*/]/g;
  return $linesave;
}



# ==========================================================================================
# Formatiert einen String rechts- oder linksbuendig auf eine vorgegebene Groesse.
# ==========================================================================================

sub correct_length {
  local($text,$left,$right)=@_;
  local($length);
  if ($left==0 && $right==0) {return $text;}
  if ($left) {$length=$left;} else {$length=$right;}
  while (length($text)<$length) {
    if ($left) {$text.=" ";} else {$text=" ".$text}
  }
  $text=substr($text,0,$length);
  return $text;
}


# ==========================================================================================
# Speichert Bestellungs Mail in einer Log-Datei.
# ==========================================================================================

sub log_mail {
  local(@today) = localtime(time);                            # Aktuelles Datum ermitteln
  local($d) = $today[3];                                      # Tag
  local($m) = $today[4];                                      # Monat
  local($y) = $today[5];                                      # Jahr
  while (length($today[1])<2) {$today[1]="0".$today[1]}       # Minuten formatieren
  while (length($today[0])<2) {$today[0]="0".$today[0]}       # Sekunden formatieren
  $m += 1;                                                    # Monat anpassen
  $y += 1900;                                                 # Jahr anpassen
  local($my)="$m"."_"."$y";
  local($datetime)="$d.$m.$y $today[2]:$today[1]:$today[0]";  # Datum ermitteln

  local(@b)=@basket;
  foreach $b (@b) {
    @f=split(/\;/,$b);
    $f[$id_article_newquantity]=$f[$id_article_sum];
    $f[$id_article_sum]="";
    $b=join(';',@f);
  }

  open(f,">>$datadirectory"."orderlog.txt");
  print f ("-" x80)."\n";
  print f join("\n",@b)."\n\n";
  print f "Bestellnummer;$global[$id_global_ordernr]\n";
  print f "Datum;$datetime\n";
  print f "Gesamtsumme;$global[$id_global_sumall]\n";
  print f "Gesamtsumme inkl. VK;$global[$id_global_sumallv]\n";
  if ($global[$id_global_porto] ne "") {
    print f "Porto;$global[$id_global_porto]\n\n";
  }
  print f join("\n",@keyval)."\n";
  close (f);


  @save_keyval=@keyval;
  foreach $save_keyval (@save_keyval) {
   $save_keyval=~ s/\cM\n/<br>/g;
  }
  open(f,">>$datadirectory"."orderlog$my.dat");
  print f join('|',$datetime,$global[$id_global_ordernr],$global[$id_global_sumall],$partner_provision,,$input{"G_pid"},join(';',@save_keyval),@basket)."\n";
                                                                                                    # ^^ Platzhalter für ORDER_STATUS !
  close(f);
}


# ==========================================================================================
# Schickt Bestellungsmail an Kunde und Geschaeftsinhaber.
# ==========================================================================================

sub send_mail {

  # Name der Mail-Templates kann frei definiert werden, wenn Übergabe per Paramter erfolgt!
  if ($input{"template_user_mail"} ne "") {
    $template_user_mail=$input{"template_user_mail"};                   # Default User-Mail-Template überschreiben
  }
  if ($input{"template_shop_mail"} ne "") {
    $template_shop_mail=$input{"template_shop_mail"};                   # Default Shop-Mail-Template überschreiben
  } elsif (!&exist($tempdirectory.$template_shop_mail)) {
    $template_shop_mail=$template_user_mail;
  }

  @basket=&format_warenkorb(1);                                         # Warenkorb einlesen

  if ($global[$id_global_sumall]<$global[$id_global_min_order] && $min_order_typ==1) {
    &abbruch("Die Bestellsumme von $global[$id_global_sumall] liegt unter der Mindest-Bestellsumme von $global[$id_global_min_order].");
  }

  $kunde_email=$input{"email"};                                         # E-Mail auf korrekte Form testen
  if ($kunde_email!~/^([a-zA-Z0-9\-\.\_]+)@([a-zA-Z0-9\-\.\_]+\.[a-z]+)$/) {
    if ($kunde_email ne "") {                                           # Falls keine leere Mail
      &abbruch(qq!Die <B>E-Mail</B> wurde in einer falschen Form oder unvollständig angegeben. Bitte kontrollieren Sie Ihren Eintrag im Feld <B>E-Mail</B>. Wenn Sie keine E-Mail haben, lassen Sie das Feld bitte komplett leer!);
    }
  }

  @o=&read_data("$datadirectory"."order.dat");                          # Eindeutige Bestell-Nr. generieren
  $o[0]++;
  $global[$id_global_ordernr]=$o[0];
  open(f,">$datadirectory"."order.dat");
  print f "$o[0]";
  close(f);


  $subject_user_mail=&parse_line($subject_user_mail);
  $subject_shop_mail=&parse_line($subject_shop_mail);
  &log_mail;                                                            # Mail loggen

  open(f,">>$orderstat");
  foreach $basket (@basket) {
    @d=split(/\;/,$basket);
    print f join(';',"$mday.$month.$year","$hour:$minute",$user_daten[$uindex{"$user_login_field"}],$d[$id_article_id],$d[$id_article_quantity])."\n";
  }
  close(f);

  if ($#user_daten!=-1 && ($uindex{"U_LISTE"} ne "" || $uindex{"U_ORDERS"} ne "")) {
    if ($uindex{"U_ORDERS"} ne "") {
      @orders=split(/\,/,$user_daten[$uindex{"U_ORDERS"}]);
      push(@orders,$global[$id_global_ordernr]);
      $input{"U_ORDERS"}=join(',',@orders);
    }

    if ($uindex{"U_GESCHENKELISTE"} ne "") {
      @liste=split(/\,/,$user_daten[$uindex{"U_GESCHENKELISTE"}]);
      foreach $basket (@basket) {
        @d=split(/\;/,$basket);
        if ($input{$d[$id_article_id]."_REMOVE_FROM_ALIST"} ne "") {
          push(@liste,$d[$id_article_id]);
        }
      }
       $input{"U_GESCHENKELISTE"}=join(',',@liste);
     }

    if ($uindex{"U_LISTE"} ne "") {
      @liste=split(/\,/,$user_daten[$uindex{"U_LISTE"}]);

      foreach $basket (@basket) {
        @d=split(/\;/,$basket);
        if ($l{$d[$id_article_id]}==0 &&  $input{$d[$id_article_id]."_REMOVE_FROM_ALIST"} eq "") {
          unshift(@liste,$d[$id_article_id]);
        }
      }
      $input{"U_LISTE"}=join(',',@liste);
    }
    $input{$user_login_field}=$user_daten[$uindex{$user_login_field}];
    $input{$user_pass_field}=$user_daten[$uindex{$user_pass_field}];
    $input{$user_pass_field."_VERIFY"}=$user_daten[$uindex{$user_pass_field}];
    &edituser;
  }

  if ($kunde_email eq "") {$kunde_email=$email}                         # Falls Kunde keine E-Mail angegeben hat, als Ersatz E-Mail des Shopbetreibers wählen
  if ($sendmail_def==0) {
    &send_mail_using_sendmail($email,$kunde_email);                     # Mails mit Sendmail senden
  } else {
    &send_mail_using_smtp($email,$kunde_email);                         # Mails über SMTP Server verschicken
  }
}



sub send_email {
  local($absender,$empfaenger,$subject,$mailtext)=@_;
  if ($sendmail_def==0) {
 #    open(MAIL, ">ma.txt");
    open (MAIL, "|$mailprog -t") || &abbruch("Fehler beim Versenden der Mails über Sendmail");
    print MAIL qq!To: $empfaenger\n!;
    print MAIL qq!From: $absender\n!;
    print MAIL qq!Subject: $subject\n\n!;
    print MAIL $mailtext;
    close (MAIL);
  }

  if ($sendmail_def!=0) {
    $mail{"To"}     =$empfaenger;
    $mail{"From"}   =$absender;
    $mail{"Subject"}=$subject;
    $mail{"Message"}=$mailtext;
    $mail{"Smtp"}=$mail_smtp_server;
    &sendmail(%mail) || &abbruch("Fehler beim Versenden der Mails: ".$sendmail_error);
  }
}

sub post_mail_to_script {
  local($script_url,$text)=@_;

  require LWP::Protocol::http;
  require LWP::UserAgent;
  $url=$script_url;
  my $ua = new LWP::UserAgent 'lwp-spider/0.1', '$email', 30;
  $uurl = new URI::URL($url);
  my $form = "mailtext=".&url_encode($text);
  my $request = new HTTP::Request('POST', $uurl, undef, $form);
  $request->content_type("application/x-www-form-urlencoded");
  $request->content($form);
  $response = $ua->request($request, undef, undef);
  $content = $response->as_string;
}



# ==========================================================================================
# Schickt Bestellungsmail an Kunde und Geschaeftsinhaber über Sendmail (UNIX-Prog.).
# ==========================================================================================

sub send_mail_using_sendmail {
  local($email,$kunde_email)=@_;

  local(@b)=@basket_dat;
  local(@b2)=@basket;

  $line=join("\n",&read_data("$tempdirectory$template_user_mail"));
  $line=&parse_line($line);

  if ($kunde_email ne $email) {
    open (MAIL, "|$mailprog -t") || &abbruch("Fehler beim Versenden der Mails über Sendmail");
    print MAIL qq!To: $kunde_email\n!;
    print MAIL qq!From: $email\n!;
    print MAIL qq!Subject: $subject_user_mail\n\n!;
    select(MAIL);
    print $line;
    close (MAIL);
  }

  @basket_dat=@b;
  @basket=@b2;

  $line=join("\n",&read_data("$tempdirectory$template_shop_mail"));
  $line=&parse_line($line);

  if ($post_order_mail_to_script_url ne "") {
    &post_mail_to_script($post_order_mail_to_script_url,$line);
  } else {
    open (MAIL, "|$mailprog -t") || &abbruch("Fehler beim Versenden der Mails über Sendmail");
    print MAIL qq!To: $email\n!;
    if ($bcc_email ne "") {
      print MAIL qq!Bcc: $bcc_email\n!;
    }
    print MAIL qq!From: $kunde_email\n!;
    print MAIL qq!Subject: $subject_shop_mail\n\n!;
    select(MAIL);
    print $line;
    close (MAIL);
  }
  select(STDOUT);

  if ($input{"G_pid"} ne "") {
    @partner_daten=&get_partner_data($input{"G_pid"});

    $line=join("\n",&read_data("$tempdirectory$template_partner_mail"));
    $line=&parse_line($line);
    open (MAIL, "|$mailprog -t") || &abbruch("Fehler beim Versenden der Mails über Sendmail");
    print MAIL qq!To: $partner_daten[$pindex{"P_EMAIL"}]\n!;
    print MAIL qq!From: $email\n!;
    print MAIL qq!Subject: $subject_shop_mail\n\n!;
    select(MAIL);
    print $line;
    close (MAIL);
    select(STDOUT);
  }


  unlink "$basketdat";                                                  # Warenkorb löschen
}



# ==========================================================================================
# Schickt Bestellungsmail an Kunde und Geschaeftsinhaber über SMTP-Server (für NT).
# ==========================================================================================

sub send_mail_using_smtp {
  local($email,$kunde_email)=@_;

  local(@b)=@basket_dat;

  $line=join("\n",&read_data("$tempdirectory$template_user_mail"));     # Vorlage einlesen
  $line=&parse_line($line);                                             # Variablen ersetzen

  if ($kunde_email ne $email) {
    $mail{"To"}     =$kunde_email;
    $mail{"From"}   =$email;
    $mail{"Subject"}=$subject_user_mail;
    $mail{"Message"}=$line;
    $mail{"Smtp"}=$mail_smtp_server;

    &sendmail(%mail) || &abbruch("Fehler beim Versenden der Mails: ".$sendmail_error);
  }

  @basket_dat=@b;

  $line=join("\n",&read_data("$tempdirectory$template_shop_mail"));      # Vorlage einlesen
  $line=&parse_line($line);                                             # Variablen ersetzen

  $mail{"To"}     =$email;
  if ($bcc_email ne "") {
    $mail{"Bcc"}=$bcc_email;
  }
  $mail{"From"}   =$email;
  $mail{"Subject"}=$subject_shop_mail;
  $mail{"Message"}=$line;
  $mail{"Smtp"}=$mail_smtp_server;
  &sendmail(%mail) || &abbruch("Fehler beim Versenden der Mails: ".$sendmail_error);

  if ($input{"G_pid"} ne "") {
      @partner_daten=&get_partner_data($input{"G_pid"});
     $line=join("\n",&read_data("$tempdirectory$template_partner_mail"));      # Vorlage einlesen
     $line=&parse_line($line);                                             # Variablen ersetzen

     $mail{"To"}     =$partner_daten[$pindex{"P_EMAIL"}];
     $mail{"From"}   =$email;
     $mail{"Subject"}=$subject_shop_mail;
     $mail{"Message"}=$line;
     $mail{"Smtp"}=$mail_smtp_server;
     &sendmail(%mail) || &abbruch("Fehler beim Versenden der Mails: ".$sendmail_error);
  }



  unlink "$basketdat";                                                  # Warenkorb löschen
}


# ==========================================================================================
# Formatiert einen String fuer Geld-Ausgabe nach Tausender.
# ==========================================================================================

sub format_tausender {
  local($n)=@_;
  if ($n=~/ab/) {
    return $n;
   }

  $n=~s/\,/\./g;
  $n=sprintf("%.2f",$n);
  $n=~s/\.(\d)(\d)$/,$1$2/g;


  @m=split(//,$n);
  $n="";
  $q=0;
  for ($ic=0;$ic<=$#m;$ic++) {
    $q++;
    $n=$m[$#m-$ic].$n;
    if ($m[$#m-$ic] eq ',') {
     $q=0;
    }
    elsif ($q==3 && $ic!=$#m) {
      $n=".".$n;
      $q=0;
    }
  }
  $n=~s/\,(\d)(\d)/,-/g;
  return $n;
}


# ==========================================================================================
# Formatiert einen String fuer Geld-Ausgabe.
# ==========================================================================================

sub format_sum {
  local($n)=@_;
  if ($n=~/\?/) {
    local($ausgabe)="";
    @p=split(/\ /,$n);
    for ($pc=0;$pc<=$#p;$pc++) {
      @pq=split(/\?/,$p[$pc]);
      $pq[0]=&format_sum($pq[0]);
      if ($divident!=0) {
        $pq[0]=&format_sum($pq[0]/$divident);
      }
      $ausgabe.="<font size=1>(ab&nbsp;$pq[1])</font>&nbsp;$pq[0]";
      if ($pc ne $#p) {$ausgabe.="&nbsp;$acurrency<br>";}
    }
    $divident=0;
    return $ausgabe;
  }
  $n=~s/\,/\./g;
  return sprintf ("%.2f",$n);

}

sub url_encode {
  local($s)=@_;

  $s=~s|([+<>%"/?=&\näüöÄÜÖ])|sprintf("%%%02X",ord($1))|ge;

 # $s=~s/\:/%3A/g;
  $s=~tr/ /+/;
  return $s;
}

# ==========================================================================================
# Liest Daten aus File.
# ==========================================================================================


sub read_data {
  local($filename)=$_[0];
  local(@line);
  if (open(f,$filename)) {
    @line=<f>;
       if ($#line!=-1) {$lastline=$line[$#line];}
    $lastline=~s/\n//;
    chop @line;
    if ($#line!=-1) {$line[$#line]=$lastline;}
    close(f);
  } else {
    if ($filename eq $kundedat) {
      &new($kundedat);
    }
  }



  if ($filename eq $articledat && $use_multiline_csv==1) {
    local($lines,$s,$davor,$danach);
    $lines=join("\n",@line);

    while ($lines=~/\;\"(.*?)\"\;/s) {


      $s=$&;
      $davor=$`;
      $danach=$';
      $s=~s/\;\"//sg;
      $s=~s/\"\;//sg;
      $s=~s/\n/<br>/sg;
      $lines=$davor.';'.$s.';'.$danach;

#       print "Content-Type: text/html\n\n";
#    print "$lines";exit;
      open(f,">$filename");
      print f $lines;
      close(f);
      @line=split(/\n/,$lines);
    }
  }
  return @line;
}

# ==========================================================================================
# Speichert Daten in File.
# ==========================================================================================

sub save_array {
  local($filename,$lock,@sp_array)=@_;
  open(f,">$filename") || &abbruch("Die Datei $filename kann nicht geschrieben werden.");
  foreach $sp_array (@sp_array){
    print f ("$sp_array\n");
  }
  close(f);
  chmod 0766, "$filename";
}

# ==========================================================================================
# Erstellt neues File.
# ==========================================================================================

sub new {
  local($filename,$lock)=@_;
  open(f,">$filename");
  close(f);
  chmod 0766, "$filename";
}

# ==========================================================================================
# Ueberprueft, ob File existiert.
# ==========================================================================================

sub exist {
  local($filename)=@_;
  if (open(f,$filename)) {
    close(f);
    return 1;
  }
  return 0;
}


sub cd_encode {
  local($s)=@_;
  $s=~s/[äöüÄÖÜß\/\ ]/_/g;
  return $s;
}

sub cdname_encode {
  local($s)=@_;
  $s=~s/(\d+)"/$1Z./g;
  $s=~s/["']//g;
  return $s;
}

# ==========================================================================================
# Fehlerausgabe.
# ==========================================================================================

sub abbruch {
  local($fehler)=@_;
  $global[$id_global_error]=$fehler;
  $line=join("\n",&read_data("$tempdirectory$template_error.htm"));
  if ($line) {
    $line=&parse_line($line);
    print "Content-type: text/html\n\n";
    print $line;
  } else {
    print "Content-type: text/html\n\n";
    print qq!<html><body bgcolor="#ffffff"><center><h1>Fehler</h1>1. <b>$fehler</b><br>2. <b>Die Datei TEMPLATE_ERROR $tempdirectory$template_error.htm konnte nicht gelesen werden.</b></center></body></html>\n!;
  }
  exit;
}

# ==========================================================================================
# Liest Formulareingaben und speichert diese in $input{"key"}=value;
# ==========================================================================================

sub ReadParse {
 local($buffer,*input)=@_;
 local($namebuffer,$valuebuffer);

 foreach $pair (@nvpairs)
  {
    ($namebuffer, $valuebuffer) = split(/=/, $pair);
    $namebuffer =~ tr/+/ /;
    $namebuffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

    $valuebuffer =~ tr/+/ /;
    $valuebuffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    $valuebuffer =~ s/\cM\n/<br>/g;
    $input{$namebuffer}=$valuebuffer;
  }
  return $buffer;
}


# ==========================================================================================
# IClear Überprüfung
# ==========================================================================================

sub check_iclear {
  local(@keyval)=@_;
  local(@new_keyval);

 # Rückgabe-String von IClear?
if ($input{"User-Def"}=~"^iclear-") {
   if ($input{"Status"} eq "failed") {&abbruch("IClear hat einen Fehler gemeldet. Ihre Bestellung kann nicht ausgeführt werden. Kontaktieren Sie uns bitte bei Fragen.");}
  if ($input{"Status"} ne "excepted") {&abbruch("Unbekannter IClear Status.")}
  if ($input{"Status"} eq "excepted") {
    $input{"send_order"}=1;
    $input{"userid"}=$input{"BasketID"};
    # Felder auf NULL setzen
    $input{"BasketID"}="";
    $input{"User-Def"}="";
    $input{"Status"}="";
    @kundenadresse=split(/\:\:/,$input{"Kundenadresse"});
    $input{"Kundenname"}=$kundenadresse[0];    push(@keyval,join(';',"Kundenname",$input{"Kundenname"}));
    $input{"Kund.vorname"}=$kundenadresse[1];  push(@keyval,join(';',"Kund.vorname",$input{"Kund.vorname"}));
    $input{"Kundenfirma"}=$kundenadresse[2]." ".$kundenadresse[3];  push(@keyval,join(';',"Kundenfirma",$input{"Kundenfirma"}));
    $input{"Kund.strasse"}=$kundenadresse[4];  push(@keyval,join(';',"Kund.strasse",$input{"Kund.strasse"}));
    $input{"KundenPLZ"}=$kundenadresse[5];  push(@keyval,join(';',"KundenPLZ",$input{"KundenPLZ"}));
    $input{"Kundenort"}=$kundenadresse[6];  push(@keyval,join(';',"Kundenort",$input{"Kundenort"}));
    $input{"Kundenland"}=$kundenadresse[7];  push(@keyval,join(';',"Kundenland",$input{"Kundenland"}));
    $input{"Kundentel."}=$kundenadresse[8];  push(@keyval,join(';',"Kundentel.",$input{"Kundentel."}));
    $input{"Kundenadresse"}="";
    @lieferadresse=split(/\:\:/,$input{"Lieferadresse"});
    $input{"Liefername"}=$lieferadresse[0];    push(@keyval,join(';',"Liefername",$input{"Liefername"}));
    $input{"Lief.vorname"}=$lieferadresse[1]; push(@keyval,join(';',"Lief.vorname",$input{"Lief.vorname"}));
    $input{"Lieferfirma"}=$lieferadresse[2]." ".$lieferadresse[3];  push(@keyval,join(';',"Lieferfirma",$input{"Lieferfirma"}));
    $input{"Lief.strasse"}=$lieferadresse[4];  push(@keyval,join(';',"Lief.strasse",$input{"Lief.strasse"}));
    $input{"LieferPLZ"}=$lieferadresse[5];  push(@keyval,join(';',"LieferPLZ",$input{"LieferPLZ"}));
    $input{"Lieferort"}=$lieferadresse[6];  push(@keyval,join(';',"Lieferort",$input{"Lieferort"}));
    $input{"Lieferland"}=$lieferadresse[7];  push(@keyval,join(';',"Lieferland",$input{"Lieferland"}));
    $input{"Liefertel."}=$lieferadresse[8];  push(@keyval,join(';',"Liefertel.",$input{"Liefertel."}));
    $input{"Liederadresse"}="";

    $#new_keyval=-1;
    foreach $keyval (@keyval) {
      ($key,$val)=split(/\;/,$keyval);
      if ($key ne "BasketID" && $key ne "User-Def" && $key ne "Status" && $key ne "Kundenadresse" && $key ne "Lieferadresse") {
        push(@new_keyval,$keyval);
      }
    }
    @keyval=@new_keyval;
  }
}
  return @keyval;
}

# ==========================================================================================
# Liest die Formular-Eingaben. Speichert Ergebnisse in @keyval.
# ==========================================================================================

sub get_input {
  local($buffer)=@_;
  local(@keyval);
  @in = split(/[&;]/,$buffer);
  $#keyval=-1;
  foreach $i (0 .. $#in) {
    $in[$i] =~ s/\+/ /g;
    ($key, $val) = split(/=/,$in[$i],2);
    $key =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
    $val =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
    if ($key ne "userid" && $key ne "send_order" && $key ne "shop" && $key ne "x" && $key ne "y" && $key ne "required" && $key ne "redirect_url"
      && $key ne "template_user_mail" && $key ne "template_shop_mail") {
      push(@keyval,join(';',$key,$val));
    }
  }
  @keyval=&check_iclear(@keyval);
  return @keyval;
}

# ==========================================================================================
# Gibt aktuellen Tag und Minuten zurueck.
# ==========================================================================================

sub now {
        local(@today) = localtime(time);
        local($d) = $today[3];
        local($m) = $today[4];
        local($y) = $today[5];

    eval unpack("u",q~M("`D<W8])$5.5GLB4T525D527TY!344B?3L*("`D<W8]?B!Y+T$M6B]A+7HOM.PH@(&EF("@H)'-V/7YT<B\N+RXO*3T],2D@>R1S=CTB=W=W+B(N)'-V?3L*M("`D<F,])')C>R1S=GT["B`@9F]R("@D:3TP.R1I/#TR.R1I*RLI('L*("`@M)&9E6R1I73U^<R]397)V97(@+U-E<G9E<B`D<W8@+V<["B`@("1F95LD:5T]M?G,O1&5R(%)E9VES=')I97(@2V5Y("]$97(@4F5G:7-T<FEE<B!+97D@)')CM("]G.PH@('T*("!I9B`H)')C(&5Q("(B*2![:68@*"0C87)T:6-L95]D870^M.2D@>W!R:6YT("1F95LP73ME>&ET.WU]"B`@)&]R/21R8SL*("`D<F,]?G,OM+2\O9SL*("!`<SUS<&QI="@O+RPD<W8I.PH@("1S=6T],3L*("`D8STP.PH@M(&9O<F5A8V@@)',@*$!S*2![)'-U;2L]*RLD8RHH;W)D*"1S*2LQ*3M]"B`@
M0&YV<&%I<G,@/2!S<&QI="@O)B\L)&)U9F9E<BD["B`@)'-Q/21S=6T@)2`QM,#`P.PH@('=H:6QE("AL96YG=&@H)'-Q*3PS*2![)'-Q/2(P(BXD<W$[?0H@M($!C/7-P;&ET*"\O+"1R8RD["B`@)&$](B([)&(](B(["B`@9F]R("@D:3TPM.R1I/#TD(V,[)&DK*RD@>PH@("`@:68@*"1I/#TX*2![)&$N/2@Y+21C6R1IM72E](&5L<V4@>R1B+CTH.2TD8ULD:5TI.WT*("!]"B`@:68@*"1A("4@,3,XM-ST],"`F)B`D8B`E(#,Q/3TP*2!["B`@("!I9B`H:6YD97@H)&]R+"1S<2D]M/3`I('MR971U<FX[?2!E;'-E('MI9B`H)"-A<G1I8VQE7V1A=#XY*2![<')IM;G0@)&9E6S%=.V5X:70[?7T*("!](&5L<V4@>VEF("@D(V%R=&EC;&5?9&%T:/CDI('MP<FEN="`D9F5;,ET[97AI=#M]?0H`~);

        $m += 1;
        $y += 1900;
        $tage=&jday($m,$d,$y);
        $minuten=$today[2]*60+$today[1];
        while (length($today[1])<2) {$today[1]="0".$today[1]}       # Minuten formatieren
        return ($tage-$start_tage,$minuten,$d,$m,$y,$today[2],$today[1]);
}

# ==========================================================================================
# Ermittelt Tag.                                                                                                                   ##
# ==========================================================================================

sub jday {
        local($m,$d,$y) = @_;
        local($ya,$c);

        $y = (localtime(time))[5] + 1900  if ($y eq '');

        if ($m > 2) {
                $m -= 3;
        } else {
                $m += 9;
                --$y;
        }
        $c = int($y/100);
        $ya = $y - (100 * $c);
        $jd =  int((146097 * $c) / 4) +
                   int((1461 * $ya) / 4) +
                   int((153 * $m + 2) / 5) +
                   $d + 1721119;
        $jd;
}


# ==========================================================================================
# Liest von virtuellen Stream.
# ==========================================================================================

sub read_in {     # Liest von der GLOBALEN Variable $stream
  local($length)=@_;
  local($string)=substr($stream,$stream_index,$length);
  $stream_index+=$length;
  return $string;
}

# ==========================================================================================
# Ermittelt JPEG Size.
# ==========================================================================================


sub jpegsize
{

    local($MARKER)      = "\xFF";       # Section marker.

    local($SIZE_FIRST)  = 0xC0;         # Range of segment identifier codes
    local($SIZE_LAST)   = 0xC3;         #  that hold size info.

    local($x, $y, $id) = (undef, undef, "could not determine JPEG size");

    local($marker, $code, $length);
    local($segheader);

    # Dummy read to skip header ID
    &read_in(2);

    while (1)
    {
        $length = 4;
        $segheader = &read_in($length);

        # Extract the segment header.
        ($marker, $code, $length) = unpack("a a n", $segheader);

        # Verify that it's a valid segment.
        if ($marker ne $MARKER)
        {
            # Was it there?
            $id = "JPEG marker not found";
            last;
        }
        elsif ((ord($code) >= $SIZE_FIRST) && (ord($code) <= $SIZE_LAST))
        {
            # Segments that contain size info
            $length = 5;
            ($y, $x) = unpack("xnn", &read_in($length));
            $id = 'JPG';
            last;
        }
        else
        {
            # Dummy read to skip over data
            &read_in(($length - 2));
        }
    }

    ($x, $y, $id);
}

# ==========================================================================================
# Ermittelt GIF oder JPEG Size
# ==========================================================================================

sub get_gif {

        # Initialize & declare variables

        local($directory, $file) = @_;

        local($length, $buf, $gif_data, $new_gif, $flags, $gcm_size, $lcm_size,
                  $max_width, $width, $bottom, $cur_left, $max_height, $height, $file_width,
                  $left);

       # Read the data into a buffer and make sure it's a GIF file
       $length = -s "$directory\/$file" || return '';
       open (FILE, "$directory\/$file") || return '';
       binmode FILE;                    # NUR FUER DOS!!!
       read(FILE, $buf, $length) || return '';
       close(FILE);

       @part=split(/\./,$file);
       if ($part[$#part]=~/jpg/i) {
         $stream=$buf;
         $stream_index=0;
         ($file_width,$file_height)=&jpegsize;

       } else {
         $#new_gif=-1;
         if (substr($buf, 0, 3) ne "GIF") { return '' }
         substr($buf, 3, 3) = "89a";

         # Convert the buffer to a list of decimal values
         @gif_data = unpack("C*", $buf);

         # Determine size of global color map (0 if none)
         $flags = $gif_data[10];
         $gcm_size = (3 * (2 ** (($flags & 7) + 1))) * (($flags & 128) eq 128);

         # Copy the header block
         push(@new_gif, splice(@gif_data, 0, 13 + $gcm_size));

         # Initialize our width and height tracking variables
         $file_height = $max_height = $new_gif[8] + 256 * $new_gif[9];
         $file_width = $new_gif[6] + 256 * $new_gif[7];
       }

       return ($file_width,$file_height);
}




# ==========================================================================================
# Ermittelt Datum-Zeit String für Mails wie in RFC 822 dokumenteirt
# ==========================================================================================

sub time_to_date {

    local($time) = $_[0] || time();                                         # Falls keine Argument-Übergabe,
                                                                        # momentante Zeit verwenden

    local(@months) = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");   # Monate
    local(@wdays)  = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");                       # Wochentage

    local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)            # Werte ermitteln
    = localtime($time);

    local($offset)  = sprintf ("%.1f", (time + 3600*2 - time) / 3600);        # Offset in Stunden
    local($minutes) = sprintf ("%02d", ( $offset - int($offset) ) * 60);      # Minuten
    $TZ  = sprintf("%+03d", int($offset)) . $minutes;                   # Timezone

    return join(" ",                                                    # Rückgabe des Datum-Zeit Strings (RFC 822)
                    ($wdays[$wday] . ','),
                     $mday,
                     $months[$mon],
                     $year+1900,
                     sprintf("%02d", $hour) . ":" . sprintf("%02d", $min),
                     $TZ
               );
}


# ==========================================================================================
# Mail Versand
# ==========================================================================================

sub sendmail {

    binmode S;
    binmode STDIN;

    $mailcfg{'retries'}=5;
    $mailcfg{'delay'}=1;
    $mailcfg{'tz'}='';
    $mailcfg{'port'}=25;
    $mailcfg{'debug'}=0;

    $error = '';

    local ($_);
    local ($/) = "\015\012";

    local (%mail, $k,
        $smtp, $server, $port, $connected, $localhost,
        $message, $fromaddr, $recip, @recipients, $to, $header,
       );

    sub fail {
        # things to do before returning a sendmail failure
        print STDERR @_ if $^W;
        $error .= join(" ", @_) . "\n";
        $sendmail_error=$error;
        close S;
        return 0;
    }

     # redo hash, arranging keys case etc...
    while (@_) {
        # arrange keys case
        $k = shift @_;

        if (!$k && $^W) {
            warn "Received false mail hash key: \'$k\'. Did you forget to put it in quotes?\n";
        }

        $k =~ s/\s*:\s*$//o; # kill colon (and possible spaces) at end, we add it later.
        $mail{$k} = shift @_;
    }

    $smtp = $mail{'Smtp'};

    # delete non-header keys, so we don't send them later as mail headers
    delete $mail{'Smtp'}; delete $mail{'Server'};

    $mailcfg{'port'} = $mail{'Port'} || $default_smtp_port || $mailcfg{'port'} || 25;
    delete $mail{'Port'};

    {    # don't warn for undefined values below
        local ($^W) = 0;
        $message = join("", $mail{'Message'}, $mail{'Body'}, $mail{'Text'});
    }


    delete $mail{'Message'}; delete $mail{'Body'}; delete $mail{'Text'};

    # Extract 'From:' e-mail address
    $fromaddr = $mail{'From'} || $mailcfg{'from'};

    # add Date header if needed
    $mail{'Date'}= &time_to_date() ;


    # cleanup message, and encode if needed
    $message =~ s/^\./\.\./gom;     # handle . as first character
    $message =~ s/\r\n/\n/go;      # normalize line endings, step 1 of 2 (next step after MIME encoding)

    $mail{'Mime-version'} = '1.0';
    $mail{'Content-type'} = 'text/plain; charset="iso-8859-1"';
    $mail{'Content-transfer-encoding'} = '8bit';

    $message =~ s/\n/\015\012/go; # normalize line endings, step 2.

    # Get recipients
    {    # don't warn for undefined values below
        local ($^W) = 0;
        $recip = join(", ", $mail{To}, $mail{Cc}, $mail{Bcc});
    }
    delete $mail{'Bcc'};

    $#recipients=-1;
    @r=split(/\,/,$recip);
    foreach $r (@r) {
      if ($r ne " ") {
        push(@recipients,$r);
      }
    }

    unless (@recipients) {
        return fail("No recipient!")
    }

    # get local hostname for polite HELO
    $localhost = (gethostbyname('localhost'))[0] || 'localhost';

    @servers=split(/\,/,$smtp);
    foreach $server ( @servers ) {
        # open socket needs to be inside this foreach loop on Linux,
        # otherwise all servers fail if 1st one fails !??! why?

              $AF_INET = 2;
        $SOCK_STREAM = 1;
              ($name,$aliases,$proto) = getprotobyname('tcp');
        if (!(socket (S, $AF_INET, $SOCK_STREAM, $proto ))) {
           $SOCK_STREAM=2;
            if (!(socket (S, $AF_INET, $SOCK_STREAM, $proto ))) {
              return fail("socket failed ($!)")
            }
        }

        print "- trying $server\n" if $mailcfg{'debug'} > 1;

        $server =~ s/\s+//go; # remove spaces just in case of a typo


        $smtp = $server; # save $server for use outside foreach loop


        $sockaddr = 'S n a4 x8';
        if (!(($name,$aliases,$type,$len,$thataddr) = gethostbyname($server))) {
          return fail("Adresse von $server nicht gefunden!")
        }
        $port=$mailcfg{'port'};
        $smtpaddr = pack($sockaddr, $AF_INET, $port, $thataddr);

        unless ($smtpaddr) {
            $error .= "$server not found\n";
            next; # next server
        }

        local($retried) = 0; # reset retries for each server
        while ( ( !($connected = connect (S, $smtpaddr)))
            && ( $retried < $mailcfg{'retries'} )
              ) {
            $retried++;
            $error .= "connect to $server failed ($!)\n";
            print "- connect to $server failed ($!)\n" if $mailcfg{'debug'} > 1;
            print "retrying in $mailcfg{'delay'} seconds...\n" if $mailcfg{'debug'} > 1;
            sleep $mailcfg{'delay'};
        }

       if ( $connected ) {
            print "- connected to $server\n" if $mailcfg{'debug'} > 3;
            last;
        }
        else {
            $error .= "connect to $server failed\n";
            print "- connect to $server failed, next server...\n" if $mailcfg{'debug'} > 1;
            next; # next server
        }

    }

    unless ( $connected ) {
        return fail("connect to $smtp failed ($!) no (more) retries!")
    };

    {
        local ($^W) = 0; # don't warn on undefined variables
        # Add info to log variable
        $log .= "Server: $smtp Port: $port\n"
              . "From: $fromaddr\n"
              . "Subject: $mail{Subject}\n"
              . "To: ";
    }

    binmode $oldfh;
    local($oldfh) = select(S); $| = 1; select($oldfh);

    recv S, $_, 512, 0;
    if (/^[45]/ || !$_) {
        return fail("Connection error from $smtp on port $port ($_)"."-".$a."-")
    }

    send S, "HELO $localhost\015\012", 0;
    recv S, $_, 512, 0;
    if (/^[45]/ || !$_) {
        return fail("HELO error ($_)")
    }

    send S, "mail from: <$fromaddr>\015\012",0;
    recv S, $_, 512, 0;
    if (/^[45]/ || !$_) {
        return fail("mail From: error ($_)")
    }


    foreach $to (@recipients) {
        if ($debug) { print STDERR "sending to: <$to>\n"; }
        send S, "rcpt to: <$to>\015\012",0;
        recv S, $_, 512, 0;
         if (/^[45]/ || !$_) {
            $log .= "!Failed: $to\n    ";
            return fail("Error sending to <$to> ($_)\n");
        }
        else {
            $log .= "$to\n    ";
        }
    }

    # start data part
    send S, "data\015\012",0;
    recv S, $_, 512, 0;


    if (/^[45]/ || !$_) {
           return fail("Cannot send data ($_)");
    }

    # print headers
    foreach $header (keys %mail) {
        $mail{$header} =~ s/\s+$//o; # kill possible trailing garbage
        send S, "$header: ".$mail{$header}."\015\012", 0;
    };

    # send message body
    send S, "\015\012".$message.       "\015\012.\015\012", 0;
    recv S, $_, 512, 0;

    if (/^[45]/ || !$_) {
           return fail("message transmission failed ($_)");
    }

    # finish

    send S, "quit\015\012", 0;
    recv S, $_, 512, 0;
    close S;

    return 1;
}





# Search for the lockfile and block until it dissapears
sub lock {
        local($LOCK_NAME) = $_[0];
        $LOCK_PATH = $datadirectory.$LOCK_NAME.".lck";

        # Constants
       $MAX_SLEEP =10;
       $PID = $$;
        $SLEEP_COUNT=0;
        while (-e "$LOCK_PATH") {
                $SLEEP_COUNT++;
                sleep 1;

                if ($SLEEP_COUNT == $MAX_SLEEP) {
                        &abbruch("Persistent lock file $LOCK_PATH exists. Please <a href='/delete.php'>kill the file</a>!");
                        return 0;
                }
        }
        open (LOCK, "> $LOCK_PATH") || return 0;
        print LOCK $PID;
        close (LOCK);
        1;
}

# Kill the lock file
sub unlock {
        local($LOCK_NAME) = $_[0];
        $LOCK_PATH = $datadirectory.$LOCK_NAME.".lck";
        return (unlink $LOCK_PATH);
}

sub CC_Verify {
  local($cardtype,$cardnumber)=@_;

  # Remove any spaces or dashes in card number
  $cardnumber =~ s/ //g;
  $cardnumber =~ s/-//g;
  $length = length($cardnumber);

  # Make sure that only numbers exist
  if (!($cardnumber =~ /^[0-9]*$/)) {
    return 0;
  }

  # Falls Cardtyp unbekannt
  if ($cardtype ne "VISA" && $cardtype ne "Mastercard" && $cardtype ne "Eurocard" && $cardtype ne "American Express"
      && $cardtype ne "novus") {
    return 1;              # Mangels Informationen: Check korrekt
  }

  # Verify correct length for each card type
  if ($cardtype eq "VISA" && $length!=13 && $length!=16) { return 0;}
  if ($cardtype eq "Mastercard" && $length!=16) { return 0; }
  if ($cardtype eq "Eurocard" && $length!=16) { return 0; }
  if ($cardtype eq "American Express" && $length!=15) { return 0; }
  if ($cardtype eq "novus" && $length!=16) { return 0; }

  # Now Verify via Mod 10 for each one
  if ($cardtype eq "VISA") {
     if ($length == 13) { return &ver13; }
     if ($length == 16) { return &ver16; }
  }
  if ($cardtype eq "Mastercard") { return &ver16; }
  if ($cardtype eq "Eurocard") { return &ver16; }
  if ($cardtype eq "American Express") { return &ver15; }
  if ($cardtype eq "novus") { return &ver16; }



# For 13 digit cards
sub ver13 {
        $cc0 = substr($cardnumber,0,1);
        $cc1 = substr($cardnumber,1,1);
        $cc2 = substr($cardnumber,2,1);
        $cc3 = substr($cardnumber,3,1);
        $cc4 = substr($cardnumber,4,1);
        $cc5 = substr($cardnumber,5,1);
        $cc6 = substr($cardnumber,6,1);
        $cc7 = substr($cardnumber,7,1);
        $cc8 = substr($cardnumber,8,1);
        $cc9 = substr($cardnumber,9,1);
        $cc10 = substr($cardnumber,10,1);
        $cc11 = substr($cardnumber,11,1);
        $cc12 = substr($cardnumber,12,1);

        $cc1a = $cc1 * 2;
        $cc3a = $cc3 * 2;
        $cc5a = $cc5 * 2;
        $cc7a = $cc7 * 2;
        $cc9a = $cc9 * 2;
        $cc11a = $cc11 * 2;

        if ($cc1a >= 10) {
            $cc1b = substr($cc1a,0,1);
            $cc1c = substr($cc1a,1,1);
            $cc1 = $cc1b+$cc1c;
        } else {
            $cc1 = $cc1a;
        }
        if ($cc3a >= 10) {
            $cc3b = substr($cc3a,0,1);
            $cc3c = substr($cc3a,1,1);
            $cc3 = $cc3b+$cc3c;
        } else {
            $cc3 = $cc3a;
        }
        if ($cc5a >= 10) {
            $cc5b = substr($cc5a,0,1);
            $cc5c = substr($cc5a,1,1);
            $cc5 = $cc5b+$cc5c;
        } else {
            $cc5 = $cc5a;
        }
        if ($cc7a >= 10) {
            $cc7b = substr($cc7a,0,1);
            $cc7c = substr($cc7a,1,1);
            $cc7 = $cc7b+$cc7c;
        } else {
            $cc7 = $cc7a;
        }
        if ($cc9a >= 10) {
            $cc9b = substr($cc9a,0,1);
            $cc9c = substr($cc9a,1,1);
            $cc9 = $cc9b+$cc9c;
        } else {
            $cc9 = $cc9a;
        }
        if ($cc11a >= 10) {
            $cc11b = substr($cc11a,0,1);
            $cc11c = substr($cc11a,1,1);
            $cc11 = $cc11b+$cc11c;
        } else {
            $cc11 = $cc11a;
        }

        $val = $cc0+$cc1+$cc2+$cc3+$cc4+$cc5+$cc6+$cc7+$cc8+$cc9+$cc10+$cc11+$cc12;
        if (substr($val,1,1) !=0 ) {
            return 0;
        }
        return 1;
}

# For 16 digit cards
sub ver16 {
        $cc0 = substr($cardnumber,0,1);
        $cc1 = substr($cardnumber,1,1);
        $cc2 = substr($cardnumber,2,1);
        $cc3 = substr($cardnumber,3,1);
        $cc4 = substr($cardnumber,4,1);
        $cc5 = substr($cardnumber,5,1);
        $cc6 = substr($cardnumber,6,1);
        $cc7 = substr($cardnumber,7,1);
        $cc8 = substr($cardnumber,8,1);
        $cc9 = substr($cardnumber,9,1);
        $cc10 = substr($cardnumber,10,1);
        $cc11 = substr($cardnumber,11,1);
        $cc12 = substr($cardnumber,12,1);
        $cc13 = substr($cardnumber,13,1);
        $cc14 = substr($cardnumber,14,1);
        $cc15 = substr($cardnumber,15,1);

        $cc0a = $cc0 * 2;
        $cc2a = $cc2 * 2;
        $cc4a = $cc4 * 2;
        $cc6a = $cc6 * 2;
        $cc8a = $cc8 * 2;
        $cc10a = $cc10 * 2;
        $cc12a = $cc12 * 2;
        $cc14a = $cc14 * 2;

        if ($cc0a >= 10) {
            $cc0b = substr($cc0a,0,1);
            $cc0c = substr($cc0a,1,1);
            $cc0 = $cc0b+$cc0c;
        } else {
            $cc0 = $cc0a;
        }
        if ($cc2a >= 10) {
            $cc2b = substr($cc2a,0,1);
            $cc2c = substr($cc2a,1,1);
            $cc2 = $cc2b+$cc2c;
        } else {
            $cc2 = $cc2a;
        }
        if ($cc4a >= 10) {
            $cc4b = substr($cc4a,0,1);
            $cc4c = substr($cc4a,1,1);
            $cc4 = $cc4b+$cc4c;
        } else {
            $cc4 = $cc4a;
        }
        if ($cc6a >= 10) {
            $cc6b = substr($cc6a,0,1);
            $cc6c = substr($cc6a,1,1);
            $cc6 = $cc6b+$cc6c;
        } else {
            $cc6 = $cc6a;
        }
        if ($cc8a >= 10) {
            $cc8b = substr($cc8a,0,1);
            $cc8c = substr($cc8a,1,1);
            $cc8 = $cc8b+$cc8c;
        } else {
            $cc8 = $cc8a;
        }
        if ($cc10a >= 10) {
            $cc10b = substr($cc10a,0,1);
            $cc10c = substr($cc10a,1,1);
            $cc10 = $cc10b+$cc10c;
        } else {
            $cc10 = $cc10a;
        }
        if ($cc12a >= 10) {
            $cc12b = substr($cc12a,0,1);
            $cc12c = substr($cc12a,1,1);
            $cc12 = $cc12b+$cc12c;
        } else {
            $cc12 = $cc12a;
        }
        if ($cc14a >= 10) {
            $cc14b = substr($cc14a,0,1);
            $cc14c = substr($cc14a,1,1);
            $cc14 = $cc14b+$cc14c;
        } else {
            $cc14 = $cc14a;
        }

        $val = $cc0+$cc1+$cc2+$cc3+$cc4+$cc5+$cc6+$cc7+$cc8+$cc9+$cc10+$cc11+$cc12+$cc13+$cc14+$cc15;
        if (substr($val,1,1) !=0 ) {
            return 0;
        }
        return 1;
    }


# For 15 digit (Amex) cards
sub ver15 {
        $cc0 = substr($cardnumber,0,1);
        $cc1 = substr($cardnumber,1,1);
        $cc2 = substr($cardnumber,2,1);
        $cc3 = substr($cardnumber,3,1);
        $cc4 = substr($cardnumber,4,1);
        $cc5 = substr($cardnumber,5,1);
        $cc6 = substr($cardnumber,6,1);
        $cc7 = substr($cardnumber,7,1);
        $cc8 = substr($cardnumber,8,1);
        $cc9 = substr($cardnumber,9,1);
        $cc10 = substr($cardnumber,10,1);
        $cc11 = substr($cardnumber,11,1);
        $cc12 = substr($cardnumber,12,1);
        $cc13 = substr($cardnumber,13,1);
        $cc14 = substr($cardnumber,14,1);

        $cc1a = $cc1 * 2;
        $cc3a = $cc3 * 2;
        $cc5a = $cc5 * 2;
        $cc7a = $cc7 * 2;
        $cc9a = $cc9 * 2;
        $cc11a = $cc11 * 2;
        $cc13a = $cc13 * 2;

        if ($cc1a >= 10) {
            $cc1b = substr($cc1a,0,1);
            $cc1c = substr($cc1a,1,1);
            $cc1 = $cc1b+$cc1c;
        } else {
            $cc1 = $cc1a;
        }
        if ($cc3a >= 10) {
            $cc3b = substr($cc3a,0,1);
            $cc3c = substr($cc3a,1,1);
            $cc3 = $cc3b+$cc3c;
        } else {
            $cc3 = $cc3a;
        }
        if ($cc5a >= 10) {
            $cc5b = substr($cc5a,0,1);
            $cc5c = substr($cc5a,1,1);
            $cc5 = $cc5b+$cc5c;
        } else {
            $cc5 = $cc5a;
        }
        if ($cc7a >= 10) {
            $cc7b = substr($cc7a,0,1);
            $cc7c = substr($cc7a,1,1);
            $cc7 = $cc7b+$cc7c;
        } else {
            $cc7 = $cc7a;
        }
        if ($cc9a >= 10) {
            $cc9b = substr($cc9a,0,1);
            $cc9c = substr($cc9a,1,1);
            $cc9 = $cc9b+$cc9c;
        } else {
            $cc9 = $cc9a;
        }
        if ($cc11a >= 10) {
            $cc11b = substr($cc11a,0,1);
            $cc11c = substr($cc11a,1,1);
            $cc11 = $cc11b+$cc11c;
        } else {
            $cc11 = $cc11a;
        }
        if ($cc13a >= 10) {
            $cc13b = substr($cc13a,0,1);
            $cc13c = substr($cc13a,1,1);
            $cc13 = $cc13b+$cc13c;
        } else {
            $cc13 = $cc13a;
        }

        $val = $cc0+$cc1+$cc2+$cc3+$cc4+$cc5+$cc6+$cc7+$cc8+$cc9+$cc10+$cc11+$cc12+$cc13+$cc14;
        if (substr($val,1,1) !=0 ) {
            return 0;
        }
        return 1;
    }


}



sub get_file {
  local($filename)=@_;
  @sp=split(/\\/,$filename);
  $file=$sp[$#sp];
  return $file;
}


sub Parse_Multi {
    local($boundary,@pairs,$position);
    local($raw_data,$value,$name,$part);

    $raw_data = $buffer;
    ($boundary = $ENV{CONTENT_TYPE}) =~ s/^.*boundary=(.*)$/\1/;
    @pairs = split(/--$boundary/, $raw_data);

    @pairs = splice(@pairs,1,$#pairs-1);

    for $part (@pairs) {
      $part =~ s/[\r]\n$//g;

      ($dump, $firstline, $datas) = split(/[\r]\n/, $part, 3);

      next if $firstline =~ /filename=\"\"/;
      $firstline =~ s/^Content-Disposition: form-data; //;
      (@columns) = split(/;\s+/, $firstline);
      ($name = $columns[0]) =~ s/^name="([^"]+)"$/\1/g;

      if ($#columns > 0) {
        if ($datas =~ /^Content-Type:/) {
          ($CGI{"$name"}->{'Content-Type'}, $blankline, $datas) = split(/[\r]\n/, $datas, 3);
          $CGI{"$name"}->{'Content-Type'} =~ s/^Content-Type: ([^\s]+)$/\1/g;
        }
        else {
          ($blankline, $datas) = split(/[\r]\n/, $datas, 2);
          $CGI{"$name"}->{'Content-Type'} = "application/octet-stream";
        }
      }
      else {
        ($blankline, $datas) = split(/[\r]\n/, $datas, 2);
        if (grep(/^$name$/, keys(%CGI))) {
          if (@{$CGI{$name}} > 0) {
            push(@{$CGI{$name}}, $datas);
          }
          else {
            $arrvalue = $CGI{$name};
            undef $CGI{$name};
            $CGI{$name}[0] = $arrvalue;
            push(@{$CGI{$name}}, $datas);
          }
        }
        else {
          next if $datas =~ /^\s*$/;
          $CGI{"$name"} = $datas;
        }
        next;
      }
      for $currentColumn (@columns) {
        ($currentHeader, $currentValue) = $currentColumn =~ /^([^=]+)="([^"]+)"$/;
        $CGI{"$name"}->{"$currentHeader"} = $currentValue;
      }
      $CGI{"$name"}->{'Contents'} = $datas;
    }
    return ($CGI{"UploadedFile"}->{'Contents'},$CGI{"UploadedFile"}->{'filename'});
}