]> git.p6c8.net - devedit.git/blobdiff - modules/Template.pm
- Fixed a security problem:
[devedit.git] / modules / Template.pm
index 04893d1f08a19538d0a43ba275c241f7a9d54aae..ea2a9cc7f0d4b8762223fe87f4b799dd504989b9 100644 (file)
@@ -1,12 +1,12 @@
 package Template;
 
 #
-# Template (Version 1.3)
+# Template (Version 1.5)
 #
 # Klasse zum Parsen von Templates
 #
-# Autor:            Patrick Canterino <patshaping@gmx.net>
-# Letzte Aenderung: 11.4.2004
+# Autor:            Patrick Canterino <patrick@patshaping.de>
+# Letzte Aenderung: 4.5.2005
 #
 
 use strict;
@@ -24,7 +24,7 @@ use Carp qw(croak);
 sub new
 {
  my $class = shift;
- my $self  = {template => ''};
+ my $self  = {file => '', template => ''};
  return bless($self,$class);
 }
 
@@ -85,12 +85,14 @@ sub add_text($)
 
 sub read_file($;$)
 {
- my ($self,$tfile,$not_include) = @_;
+ my ($self,$file,$not_include) = @_;
  local *FILE;
 
- open(FILE,"<$tfile") or croak "Open $tfile: $!";
- read(FILE, my $content, -s $tfile);
- close(FILE) or croak "Closing $tfile: $!";
+ $self->{'file'} = $file;
+
+ open(FILE,'<'.$file) or croak "Open $file: $!";
+ read(FILE, my $content, -s $file);
+ close(FILE) or croak "Closing $file: $!";
 
  $self->add_text($content);
  $self->parse_includes unless($not_include);
@@ -110,7 +112,7 @@ sub fillin($$)
  my ($self,$var,$text) = @_;
 
  $var  = quotemeta($var);
- $text = "" unless defined $text; # Um Fehler zu vermeiden
+ $text = '' unless defined $text; # Um Fehler zu vermeiden
 
  my $template = $self->get_template;
  $template    =~ s/\{$var\}/$text/g;
@@ -125,14 +127,14 @@ sub fillin($$)
 # Parameter: 1. Variable zum Ersetzen
 #            2. Array-Referenz, durch die die Variable ersetzt werden soll
 #            3. Zeichenkette, mit der das Array verbunden werden soll
-#               (Standard: "")
+#               (Standard: '')
 #
 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
 
 sub fillin_array($$;$)
 {
  my ($self,$var,$array,$glue) = @_;
- $glue = "" unless defined $glue;
+ $glue = '' unless defined $glue;
 
  $self->fillin($var,join($glue,@$array));
 }
@@ -158,33 +160,53 @@ sub to_file($)
 # Parameter: 1. Name des IF-Blocks (das, was nach dem IF steht)
 #            2. Status-Code (true  => Inhalt anzeigen
 #                            false => Inhalt nicht anzeigen
+#            3. true  => Verneinten Block nicht parsen
+#               false => Verneinten Block parsen (Standard)
 #
 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
 
-sub parse_if_block($$)
+sub parse_if_block($$;$)
 {
- my ($self,$name,$state) = @_;
- my $template            = $self->get_template;
+ my ($self,$name,$state,$no_negate) = @_;
+ my $template                       = $self->get_template;
+
+ my $count = 0;
 
- while(index($template,"{IF ".$name."}") >= 0)
+ while(index($template,'{IF '.$name.'}') >= 0)
  {
   # Das alles hier ist nicht wirklich elegant geloest...
   # ... aber solange es funktioniert... ;-)
 
-  my $start    = index($template,"{IF ".$name."}");
+  $count++;
+
+  my $start    = index($template,'{IF '.$name.'}');
   my $tpl_tmp  = substr($template,$start);
   my @splitted = split(/\{ENDIF\}/,$tpl_tmp);
 
-  my $block = ""; # Kompletter bedingter Block
+  # Wenn sich am Ende der Zeichenkette {ENDIF} befinden, werden diese
+  # von split() ignoriert, was zu einem Verschachtelungsfehler fuehrt
+  # Die fehlenden leeren Zeichenketten muessen von Hand eingefuegt werden
+
+  my $x = 1;
+
+  while(substr($tpl_tmp,-7*$x,7) eq '{ENDIF}')
+  {
+   push(@splitted,'');
+   $x++;
+  }
+
+  my $block = ''; # Kompletter bedingter Block
   my $ifs   = 0;  # IF-Zaehler (wird fuer jedes IF erhoeht und fuer jedes ENDIF erniedrigt)
 
   # {IF}
 
   for(my $x=0;$x<@splitted;$x++)
   {
-   $ifs += substr_count($splitted[$x],"{IF"); # Zum Zaehler jedes Vorkommen von IF hinzuzaehlen
-   $ifs--;                                    # Zaehler um 1 erniedrigen
-   $block .= $splitted[$x]."{ENDIF}";         # Daten zum Block hinzufuegen
+   croak 'Nesting error found while parsing IF block "'.$name.'" nr. '.$count.' in template file "'.$self->{'file'}.'"' if($x == $#splitted);
+
+   $ifs += substr_count($splitted[$x],'{IF '); # Zum Zaehler jedes Vorkommen von IF hinzuzaehlen
+   $ifs--;                                     # Zaehler um 1 erniedrigen
+   $block .= $splitted[$x].'{ENDIF}';          # Daten zum Block hinzufuegen
 
    if($ifs == 0)
    {
@@ -198,15 +220,15 @@ sub parse_if_block($$)
 
   # {ELSE}
 
-  my $else_block = ""; # Alles ab {ELSE}
+  my $else_block = ''; # Alles ab {ELSE}
      $ifs        = 0;  # IF-Zaehler
 
   @splitted = split(/\{ELSE\}/,$if_block);
 
   for(my $x=0;$x<@splitted;$x++)
   {
-   $ifs += substr_count($splitted[$x],"{IF");     # Zum Zaehler jedes Vorkommen von IF hinzuzaehlen
-   $ifs -= substr_count($splitted[$x],"{ENDIF}"); # Vom Zaehler jedes Vorkommen von ENDIF abziehen
+   $ifs += substr_count($splitted[$x],'{IF ');    # Zum Zaehler jedes Vorkommen von IF hinzuzaehlen
+   $ifs -= substr_count($splitted[$x],'{ENDIF}'); # Vom Zaehler jedes Vorkommen von ENDIF abziehen
 
    if($ifs == 0)
    {
@@ -216,13 +238,13 @@ sub parse_if_block($$)
 
     for(my $y=$x+1;$y<@splitted;$y++)
     {
-     $else_block .= "{ELSE}".$splitted[$y];
+     $else_block .= '{ELSE}'.$splitted[$y];
     }
 
     if($else_block)
     {
      $if_block   = substr($if_block,0,length($if_block)-length($else_block));
-     $else_block = (length($else_block) > 6) ? substr($else_block,6) : "";    # Ansonsten gibt es Fehler
+     $else_block = (length($else_block) > 6) ? substr($else_block,6) : '';    # Ansonsten gibt es Fehler
     }
 
     last;
@@ -237,6 +259,13 @@ sub parse_if_block($$)
  }
 
  $self->set_template($template);
+
+ # Evtl. verneinte Form parsen
+
+ unless($no_negate)
+ {
+  $self->parse_if_block('!'.$name,not($state),1);
+ }
 }
 
 # parse_condtag()
@@ -255,18 +284,18 @@ sub parse_condtag($$)
 
  my $template = $self->get_template;
 
- while(index($template,"<$condtag>") >= 0)
+ while(index($template,'<'.$condtag.'>') >= 0)
  {
-  my $start = index($template,"<$condtag>");                                # Beginn des Blocks
-  my $end   = index($template,"</$condtag>")+length($condtag)+3;            # Ende des Blocks
+  my $start = index($template,'<'.$condtag.'>');                                # Beginn des Blocks
+  my $end   = index($template,'</'.$condtag.'>')+length($condtag)+3;            # Ende des Blocks
 
-  my $extract = substr($template,$start,$end-$start);                       # Kompletten Bedingungsblock extrahieren...
+  my $extract = substr($template,$start,$end-$start);                           # Kompletten Bedingungsblock extrahieren...
 
-  my $replacement = ($state) ? substr($extract,length($condtag)+2,0-length($condtag)-3) : "";
+  my $replacement = ($state) ? substr($extract,length($condtag)+2,0-length($condtag)-3) : '';
 
   $extract = quotemeta($extract);
 
-  $template =~ s/$extract/$replacement/g;                                   # Block durch neue Daten ersetzen
+  $template =~ s/$extract/$replacement/g;                                       # Block durch neue Daten ersetzen
  }
  $self->set_template($template);
 }
@@ -284,22 +313,18 @@ sub parse_includes
  my $self     = shift;
  my $template = $self->get_template;
 
- while($template =~ /(\{INCLUDE (\S+?)\})/)
+ while($template =~ /(\{INCLUDE (\S+?)\})/g)
  {
   my ($directive,$file) = ($1,$2);
   my $qm_directive      = quotemeta($directive);
-  my $replacement       = "";
 
   if(-f $file)
   {
-   local *FILE;
+   my $inc = new Template;
+   $inc->read_file($file);
 
-   open(FILE,"<$file") or croak "Open $file: $!";
-   read(FILE, $replacement, -s $file);
-   close(FILE) or croak "Closing $file: $!";
+   $template =~ s/$qm_directive/$inc->get_template/eg;
   }
-
-  $template =~ s/$qm_directive/$replacement/g;
  }
 
  $self->set_template($template);
@@ -335,25 +360,10 @@ sub substr_count($$)
 #  Alias-Funktionen
 # ==================
 
-sub addtext($)
-{
- shift->add_text(shift);
-}
-
-sub as_string
-{
- return shift->get_template;
-}
-
-sub condtag($$)
-{
- shift->parse_condtag(@_);
-}
-
-sub readin($)
-{
- shift->read_file(shift);
-}
+*addtext   = \&add_text;
+*as_string = \&get_template;
+*condtag   = \&parse_condtag;
+*readin    = \&read_file;
 
 # it's true, baby ;-)
 

patrick-canterino.de