#!/usr/bin/perl -w
###########################################
# CGI Address Book
# 1999, mschilli@perlmeister.com
###########################################

use CGI qw/:standard :html3/;
use CGI::Carp qw/fatalsToBrowser/;
use DBI;

my $DB_DIR      = "./addressbook";
my $DB_DSN      = "DBI:CSV:f_dir=$DB_DIR";
my $DB_USER     = "";
my $DB_PASSWD   = "";

my @dbfields = qw/fname lname phone email
                   addr notes/;
my $dbflist  = join(', ', @dbfields);

my $dbh = DBI->connect($DB_DSN, $DB_USER,
   $DB_PASSWD) or die "Cannot connect to DB";

print header(), start_html(-BGCOLOR => 'white'),
      h1("Adreßbuch");

if(param('insert')) {
    # Insert/Update record according to form
    insert_rec($dbh, map { $dbh->quote(param($_)) } @dbfields);
    page_header();

} elsif(param('delete')) {
    # Delete a record according to ID field
    my $id = $dbh->quote(param('id'));
    $dbh->do(<<EOT) or die "Cannot delete data";
        DELETE FROM addressbook
        WHERE id = $id
EOT
    page_header();

} elsif(param('edit')) {
    # Display fields for inserting/updating
    if(param('id')) {
        $id = $dbh->quote(param('id'));
        # ID exists. Preset fields
        my $sql = qq[SELECT id, $dbflist
                     FROM addressbook
                     WHERE id = $id];
        my $cursor = $dbh->prepare($sql) or
                die "Cannot select ($sql)";
        $cursor->execute() or die "SQL failed";

        while(defined($row = $cursor->fetch)) {
            my $i = 1;
            foreach $field (@dbfields) {
                param($field, $row->[$i++]);
            }
        }
    }

    print start_form(),
      hidden(-name => 'id'),
      table({"border" => 1},
      TR(td("Vorname:"),
         td(textfield(-name => 'fname'))),
      TR(td("Nachname:"),
         td(textfield(-name => 'lname'))),
      TR(td("Telefon:"),
         td(textfield(-name => 'phone'))),
      TR(td("E-Mail:"),
         td(textfield(-name => 'email'))),
      TR(td("Adresse:"),
         td(textarea(-name => 'addr', -rows => 3))),
      TR(td("Notizen:"),
         td(textarea(-name => 'notes', -rows => 3))),
      );

    print submit(-name  => 'insert',
                 -value => 'Speichern'),
          submit(-name  => 'delete',
                 -value => 'Eintrag löschen'),
          end_form();

} elsif(defined param('search')) {
    page_header();
    keyword_search($dbh, param('search'));

} elsif(param('init')) {
    page_header();
    init_db($dbh);

} else {
    page_header();
}

print end_html();

$dbh->disconnect();  # Verbindung lösen.

###########################################
sub page_header {
###########################################
    print start_form();
    foreach $letter ('A'..'Z') {
        print a({href => url() .
          "?search=$letter"}, "$letter ");
    }
    print a({href => url() .  "?search="},
            "&nbsp;Alle Einträge"),
          p("Suchbegriff:",
            textfield(-name => 'search'),
            submit(-name => 'Search',
                   -value => 'Suche starten'),
            submit(-name => 'edit',
                   -value => 'Neuer Eintrag'));
    print end_form();
}

###########################################
sub keyword_search {
###########################################
    my ($dbh, $keyword) = @_;
    my $cursor;
    my $where_clause = "";

    if($keyword ne "") {
        $keyword = $dbh->quote("$keyword%");
        $where_clause = qq[
            WHERE fname CLIKE $keyword OR
                  lname CLIKE $keyword];
    }

    my $sql = qq[ SELECT id, $dbflist
                  FROM addressbook
                  $where_clause
                  ORDER BY lname];

    $cursor = $dbh->prepare($sql) or
              die "Select failed: $sql";

    $cursor->execute() or
        die "Can't execute ($sql): ", $cursor->errstr;

    print "<TABLE BORDER=1>\n";
    print TR(map { th($_) }
   qw/Name Telefon E-Mail Adresse Notizen/);

    while(defined(my $row = $cursor->fetch)) {
        print TR(td(
        a({href => url() . "?id=$row->[0]&edit=1"},
          "$row->[2], $row->[1]"),
        td("$row->[3]"),
        td("$row->[4]"), td("$row->[5]"),
        td("$row->[6]"),
        )), "\n";
    }
    print "</TABLE>\n";
}

###########################################
sub insert_rec {
###########################################
    my($dbh, $fname, $lname, $phone,
       $email, $addr, $notes) = @_;

    if(param('id')) {
        # ID there, it's an update!
        my $id = $dbh->quote(param('id'));

        my $sql = qq[
          UPDATE addressbook
          SET id=$id, fname=$fname,
              lname=$lname, phone=$phone,
              email=$email, notes=$notes
          WHERE id = $id];

        $dbh->do($sql) or die "Update failed ($sql)";

    } else {
        # ID not there, it's a new record!
        my $id = time . $$;  # Generate ID
        $id = $dbh->quote($id);

        my $sql = qq[
          INSERT INTO addressbook
          (id, $dbflist)
          VALUES ($id, $fname, $lname, $phone,
                  $email, $addr, $notes)];
        $dbh->do($sql) or die "Insert failed ($sql)";
    }
}

###########################################
sub init_db {
 ###########################################
    my $dbh = shift;

    if(! -d $DB_DIR) {
        mkdir($DB_DIR, 0755) ||
            die "Cannot create dir $DB_DIR";
    }

    $dbh->do(<<'EOT') or die "Cannot create table";
     CREATE TABLE addressbook (
      id     char(20),
      fname  char(40),  lname char(40),
      phone  char(20),  email char(40),
      addr   char(100), notes char(100)
     )
EOT
}