Thread Gästebuch funktioniert nicht (13 answers)
Opened by leonie_sonia at 2012-10-15 18:03

topeg
 2012-10-16 01:05
#162651 #162651
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Code (perl): (dl )
print("Content-type: text/html");

das und alles andere sollte nicht HTML-Encoded sein!
Das sollte so aussehen
Code (perl): (dl )
print("Content-type: text/html");

Das ist aber auch nicht ganz korrkt da eine Header mit zwei \r\n also \x0D\x0A abgeschlossen wird.

Zudem ist der gesamte Code ohne Sinn und verstand zusammen gehauen.
Weist du grundsätzlich wie ein Webserver funktioniert? weist du wie ein Perl Script auf einem Webserver abläuft. Weißt du was "CGI" bedeutet?

Damit du nicht ganz auf dem Trockenen sitzt. Ein Lauffähiges Script
more (72.0kb):
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
#!/usr/bin/perl

# ausführliche Fehlermeldungen
# und besseres Perl
use strict;
use warnings;

# einfacher Zugriff auf Übertragene Daten
use CGI;

# Fehler an den Browser senden
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);

# mit Cookies arbeiten
use CGI::Cookie;

# zum Verschlüsseln von Passworten
use Digest::MD5 qw(md5_hex);

# konstante zum Exklusiven Lock einer Datei importieren
use Fcntl qw(LOCK_EX);

# Script ist UTF-8
use utf8;

# Ausgabe ist UTF-8
binmode( STDOUT, ':encoding(UTF-8)' );

########################################################################
# Alle wichtigen Einstellungen

# das Verzeichnis in dem sich die die "Session Datenbank" und die "User Datenbank befinden"
# dieses Verzeichnis sollte nicht im Browser aufrufbar sein!
# Wenn jeder weiß welche Sessions aktiv sind und welche Nutzer sich einloggen dürfen,
# dann kann man das auch gleich weg lassen
my $basis_verzeichnis    = '/kunden/homepages/30/d11176583/htdocs/werftler/gaestebuch';

# das Verzeichnis in dem sich die Gästebuchdatei befindet
my $template_verzeichnis = '/kunden/homepages/30/d11176583/htdocs/werftler/gaestebuch';

# der "web-pfad" zum Ordner mit dem Gästebuch.
# das ist der Pfad der vom Browser aus sichtbar ist
my $web_werzeichnis      = '/werftler/gaestebuch/';

# die Datei in dem die Sessions gespeichert werden
my $session_database     = 'session.db';

# die Datei in dem die Login Daten gespeichert sind
my $nutzer_database      = 'user.db';

# die Datei in der das Template eingefügt wird
# das ist das Gästebuch
my $website              = 'gaestebuch.html';

# der Name dieses Scripts
my $script_name          = $ENV{SCRIPT_NAME};

# wie lange ist eine Session gültig
my $session_timeout      = 3600; # sekunden;


########################################################################
# HTML Blöcke zusammengefasst,
# das macht den restlichen Code übersichtlicher.

# Teile die später ersetzt werden sind mit %--name--% gekennzeichnet
# die Funktion replace_template ersetzt die Werte.

# Das Login
my $login_page = << 'END_OF_HTML';
<html>
  <head>
    <title>BVB-FAN!</title>
    <link rel="favico icon"type="image/x-icon"href="/favicon.ico">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <style type="text/css">
  <!--
.Gelb {colour:#FF00F0}
p.fett{font.weoght:bold;}
  //-->
  </style>
  <body>
    <h1 align="center">Login</h1>
    <form action="%--script_name--%" method=POST>
      Benuzername: <input type="text" name="name" size="30"><br>
      Passwort: <input type="password" name="passwort" size="30" /><br>
      <input type="submit" value="Login">
      <input type="RESET" value="Löschen">
    </form>
    <br>
    <br>
  </body>
</html>
END_OF_HTML

# Die Gästebucheingabe
my $input_page = << 'END_OF_HTML';
<html>
  <head>
    <title>BVB-FAN!</title>
    <link rel="favico icon"type="image/x-icon"href="/favicon.ico">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <h1 align="center">Eintrag schreiben</h1>
    <p style="font-color:red;">%--error_msg--%</p>
    <form action="%--script_name--%" method=POST>
      <input type="hidden" name="session_id" value="%--session_id--%">
      Author: <input type="text" name="author" value="%--author--%" size="30"><br>
      Email: <input type="text" name="email"  value="%--email--%"size="30" /><br>
      Homepage: <input type="text" name="homepage" value="%--homepage--%" size="30" /><br>
      Text:<textarea name="text" cols="50" rows="10">%--text--%</textarea><br>
      <input type="submit" value="Absenden">
      <input type="RESET" value="Löschen">
    </form>
    <br>
    <br>
  </body>
</html>
END_OF_HTML

# Die Danke Seite mit der Weiterleitung
my $danke_page = << 'END_OF_HTML';
<html>
  <head>
    <title>BVB-FAN!</title>
    <link rel="favico icon"type="image/x-icon"href="/favicon.ico">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <h1 align="center">Danke für Ihren Eintrag</h1>
    <a href="%--website--%">zurück</a>
  </body>
</html>
END_OF_HTML

# das Template, welches in das Gästebuch eingefügt wird
my $entry_template = << 'END_OF_HTML';
    <table border="1">
      <tbody>
        <tr>
          <td>Text:</td>
          <td width="590">%--text--%</td>
        </tr>
        <tr>
          <td>Author:</td>
          <td>%--author--%</td>
        </tr>
        <tr>
          <td>Email:</td>
          <td>%--email--%</td>
        </tr>
        <tr>
          <td>Homepage:</td>
          <td>%--homepage--%</td>
        </tr>
      </tbody>
    </table>
    <br>
    <br>
    <hr>
    <hr>
    <br>
    <br>
END_OF_HTML

########################################################################
# Das eigentliche Script

# eine CGI Instanz erzeugen
# das ist viel einfacher und sicherer als es von Hand zu machen
my $cgi=CGI->new();

# Session id holen. Daran wird festgestellt,
# ob ein Login schon erfolgt ist
my $session_id=$cgi->param('session_id');

# Ist die Session ID in einem Cookie?
unless($session_id)
{
  my %cookies = CGI::Cookie->fetch;
  if($cookies{'session_id'})
  {
    $session_id = $cookies{'session_id'}->value;
  }
}

# alle Sessions laden
my %sessions=load_sessions("$basis_verzeichnis/$session_database");

my $session_data={};

# ist eine Session ID vorhanden?
if($session_id and exists($sessions{$session_id}))
{
  $session_data=$sessions{$session_id};
}
# eine neue Session erzeugen
else
{
  ($session_id,$session_data)=make_new_session(%sessions);
  $sessions{$session_id}=$session_data;
}

# ein neues Cookie mit der SessionID erzeugen
my $cookie=CGI::Cookie->new(-name=>'session_id' , -value=>$session_id);

# http Header ausgeben
# Ausgabe ist UTF-8 und Cookie setzen
print $cgi->header(-charset => 'utf-8', -cookie=>[$cookie] );

# Perl Warungen im Browser ausgeben (sind Kommentare im erzeugten HTML)
warningsToBrowser();

# überprüfen ob sich jemand einloggen will
my $user_name=$cgi->param('name');
my $user_pass=$cgi->param('passwort');
if($user_name and $user_pass)
{
  # Alle Nutzerdaten laden
  my %user=load_user("$basis_verzeichnis/$nutzer_database");

  # ist der Nutzer vorhanden?
  if(exists($user{$user_name}))
  {
    # alle Passworte sind gesalzen,
    # das macht es schwehrer diese zu entschlüsseln
    my $salt=$user{$user_name}->{salt};

    # den Passwort-hash erzeugen
    my $passwort=md5_hex("$salt$user_pass");

    # den Passwort-hasch mit dem Gespeicherten vergleichen
    if($passwort eq $user{$user_name}->{passwort})
    {
      # login erfolgreich
      $session_data->{login_ok}=1;
    }
  }
}


# ist der Benutzer noch nicht eingeloggt?
if(!$session_data->{login_ok})
{
  # login Page zeigen:
  print replace_template( $login_page,
      script_name => $script_name
    );
}
# login ist erfolgt
else
{
  # timeout der Session zurück setzen
  $session_data->{timeout}=time()+$session_timeout;

  my $author   = $cgi->param('author')   // '';
  my $email    = $cgi->param('email')    // '';
  my $homepage = $cgi->param('homepage') // '';
  my $text     = $cgi->param('text')     // '';

  # sind die Texte OK? kein HTML erlaubt!
  my $text_ok=1;
  $text_ok=0 if( $author   =~ s/<[^>]*>//gs );
  $text_ok=0 if( $email    =~ s/<[^>]*>//gs );
  $text_ok=0 if( $homepage =~ s/<[^>]*>//gs );
  $text_ok=0 if( $text     =~ s/<[^>]*>//gs );

  # wenn Eingaben Fehlen oder Fehlerhaft sind
  if( !($author and $email and $text and $text_ok) )
  {

    # schon was Eingegeben aber nicht vollständig
    my $error_message='';
    if( !($author and $email and $text) )
    {
      $error_message.=" Daten nicht vollständig! Bitte geben sie Autor und Email und einen Text ein! ";
    }

    # der Text enthielt unerlaubte zeichen (HTML ist nicht erlaubt!)
    if(!$text_ok)
    {
      $error_message.=" HTML ist nicht erlaubt!";
    }

    # und die Eingabeseite anzeigen
    print replace_template( $input_page,
        script_name => $script_name,
        session_id  => $session_id,
        author      => $author,
        email       => $email,
        homepage    => $homepage,
        text        => $text,
        error_msg   => $error_message,
      );
  }
  # jemand hat einen Text geschrieben
  else
  {
    # Daten in das Template eintragen
    my $data = replace_template( $entry_template,
        author      => $author,
        email       => $email,
        homepage    => $homepage,
        text        => $text,
      );

    # Seite öffnen Datei ist UTF-8 kodiert
    open(my $fh, '+<:encoding(UTF-8)', "$template_verzeichnis/$website") or die "Can't open website - $!\n";

    # exklusiven Zugriff,
    # nur immer ein laufende Script Instanz darf darauf zugreifen
    flock($fh, LOCK_EX) or die "Can't lock website - $!\n";

    # alles auf einmal einlesen
    local $/=undef;
    my $site=<$fh>;

    # Inhalt ergänzen
    $site=~s/\Q<!--daten-->\E/<!--daten-->$data/;

    # zum Anfang der Datei
    seek($fh,0,0);

    # neuen Inhalt schreiben
    print $fh $site;

    # Datei schließen und damit Lock aufheben
    close($fh);

    # Danke Seite Ausgeben
    print replace_template( $danke_page,
        website => "$web_werzeichnis/$website",
      );
  }
}

# Sessiondaten speichern
save_session("$basis_verzeichnis/$session_database",%sessions);

########################################################################
# Funktionen:

# angebene werte in den Templates ersetzen
sub replace_template
{
  my $template = shift;
  my %values = @_;

  # suche nach %--name--% im Template und ersetze es
  $template =~ s!%--(\w+)--%! $_ = $values{$1} // '' !egsi;

  return $template;
}

# Benutzerdatenbank laden
sub load_user
{
  my $file=shift;
  my %users;

  if(open(my $fh, '<:encoding(UTF-8)', $file))
  {
    while(my $line = <$fh>)
    {
      chomp($line);
      next unless($line=~m!^([^;]+?);([^;]+?);([^;]+?)$!);
      $users{$1}={ name=>$1, salt=>$2, passwort=>$3 };
    }
  }
  else
  { warn("Can't open userdb ($!)"); }

  return %users;
}

# alle Sessions aus einer Datei lesen
sub load_sessions
{
  my $file=shift;
  my %sessions;

  return %sessions unless(-f $file);

  if(open(my $fh, '<:encoding(UTF-8)', $file))
  {
    while(my $line = <$fh>)
    {
      chomp($line);
      next unless($line=~m!^\s*([^;]+?)\s*;\s*([^;]+?)\s*;\s*([^;]+?)\s*$!);
      next if($3<time());
      $sessions{$1}={ id=>$1, login_ok=>$2, timeout => $3};
    }
    close($fh);
  }
  else
  { warn("Can't open sessiondb ($!)"); }

  return %sessions;
}

# alles Sessions in eine Datei schreiben
sub save_session
{
  my $file=shift;
  my %sessions=@_;

  if(open(my $fh, '>:encoding(UTF-8)', $file))
  {
    for my $val ( values %sessions )
    {
      next unless( $val->{id} );
      next unless( $val->{timeout} );
      $val->{login_ok}=$val->{login_ok}?1:0;
      print $fh "$val->{id};$val->{login_ok};$val->{timeout}\n";
    }
  }
  else
  { warn("Can't write sessiondb ($!)"); }
}

# eine neue SessionID erzeugen
sub make_new_session
{
  my %sessions=@_;

  my $id='';
  while(!$id or exists($sessions{$id}))
  { $id.=int(rand(10)); }

  return $id,{id=>$id, login_ok=>0, timeout=>time };
}


Schau dir an was der Code macht und versuche es zu verstehen. Ich habe es kommentiert.

Im Anhang findest du auch ein Beispiel für eine user.db und ein script mit dem du Benutzer zur user.db hinzufügen kannst.
Anhänge
text/plain
1 lines
user.db
text/plain
37 lines
gaestebuch_user_add.pl

View full thread Gästebuch funktioniert nicht