Project

General

Profile

1
<?php
2

    
3
// $Id: template.inc 2 2017-07-02 15:14:29Z Manuela $
4

    
5
/*
6
 * Session Management for PHP3
7
 *
8
 * (C) Copyright 1999-2000 NetUSE GmbH
9
 *                    Kristian Koehntopp
10
 *
11
 * $Id: template.inc 2 2017-07-02 15:14:29Z Manuela $
12
 *
13
 */
14

    
15
/*
16
 * Change log since version 7.2c
17
 *
18
 * Bug fixes to version 7.2c compiled by Richard Archer <rha@juggernaut.com.au>:
19
 * (credits given to first person to post a diff to phplib mailing list)
20
 *
21
 * Normalised all comments and whitespace (rha)
22
 * replaced "$handle" with "$varname" and "$h" with "$v" throughout (from phplib-devel)
23
 * added braces around all one-line if statements in: get_undefined, loadfile and halt (rha)
24
 * set_var was missing two sets of braces (rha)
25
 * added a couple of "return true" statements (rha)
26
 * set_unknowns had "keep" as default instead of "remove" (from phplib-devel)
27
 * set_file failed to check for empty strings if passed an array of filenames (phplib-devel)
28
 * remove @ from call to preg_replace in subst -- report errors if there are any (NickM)
29
 * set_block unnecessarily required a newline in the template file (Marc Tardif)
30
 * pparse now calls this->finish to replace undefined vars (Layne Weathers)
31
 * get_var now checks for unset varnames (NickM & rha)
32
 * get_var when passed an array used the array key instead of the value (rha)
33
 * get_vars now uses a call to get_var rather than this->varvals to prevent undefined var warning (rha)
34
 * in finish, the replacement string referenced an unset variable (rha)
35
 * loadfile would try to load a file if the varval had been set to "" (rha)
36
 * in get_undefined, only match non-whitespace in variable tags as in finish (Layne Weathers & rha)
37
 * more elegant fix to the problem of subst stripping '$n', '\n' and '\\' strings (rha)
38
 * parse uses get_var to obtain return value (Jordi via SF)
39
 * set_block reports an error if the block could not be extracted (rha)
40
 * filename is now windows-pathname aware (krabu @ SF)
41
 *
42
 *
43
 * Changes in functionality which go beyond bug fixes:
44
 *
45
 * added ability for filename comments to be output (from phplib-users layne)
46
 * changed debug handling so set, get and internals can be tracked separately (rha)
47
 * added debug statements throughout to track most function calls (rha)
48
 * debug output contained raw HTML -- is now escaped with htmlentities (rha)
49
 * Alter regex in set_block to remove more whitespace around BEGIN/END tags to improve HTML layout (rha)
50
 * Add "append" option to set_var, works just like append in parse (dale at linuxwebpro.com, rha)
51
 * Altered parse so that append is honored if passed an array (Brian)
52
 * Converted comments and documentation to phpdoc style (rha)
53
 * Added clear_var to set the value of variables to "" (rha)
54
 * Added unset_var to usset variables (rha)
55
 *
56
 */
57

    
58
/**
59
 * The template class allows you to keep your HTML code in some external files
60
 * which are completely free of PHP code, but contain replacement fields.
61
 * The class provides you with functions which can fill in the replacement fields
62
 * with arbitrary strings. These strings can become very large, e.g. entire tables.
63
 *
64
 * Note: If you think that this is like FastTemplates, read carefully. It isn't.
65
 *
66
 * Fixes
67
 * Ticket #812 depricated Fix 2009/11/25
68
 */
69

    
70
class Template
71
{
72
 /**
73
  * Serialization helper, the name of this class.
74
  *
75
 * @var       string
76
 * @access    public
77
  */
78
  public $classname = "Template";
79

    
80
 /**
81
  * Determines how much debugging output Template will produce.
82
  * This is a bitwise mask of available debug levels:
83
  * 0 = no debugging
84
  * 1 = debug variable assignments
85
  * 2 = debug calls to get variable
86
  * 4 = debug internals (outputs all function calls with parameters).
87
  *
88
  * Note: setting $this->debug = true will enable debugging of variable
89
  * assignments only which is the same behaviour as versions up to release 7.2d.
90
  *
91
 * @var       int
92
 * @access    public
93
  */
94
  public $debug    = false;
95

    
96
 /**
97
  * Determines whether Template outputs filename comments.
98
  * false = no filename outputs
99
  * true = HTML comments (e.g. <!-- START FILE $filename -->) placed in output
100
  *
101
 * @var       int
102
 * @access    public
103
  */
104
  public $filename_comments = false;
105

    
106
 /**
107
  * Determines the regular expression used to find unknown variable tags.
108
  * "loose"  = traditional match all curly braces with no whitespace between
109
  * "strict" = adopts PHP's variable naming rules
110
  *              ("loose" has a nasty habit of deleting JavaScript RegEx components)
111
  *              (should future major version releases of PHPLib default this "strict"?)
112
  *
113
 * @var       string
114
 * @access    public
115
  */
116
  public $unknown_regexp = "loose";
117

    
118
 /**
119
  * The base directory from which template files are loaded.
120
  *
121
 * @var       string
122
 * @access    private
123
 * @see       set_root
124
  */
125
  public $root     = ".";
126

    
127
 /**
128
  * A hash of strings forming a translation table which translates variable names
129
  * into names of files containing the variable content.
130
  * $file[varname] = "filename";
131
  *
132
 * @var       array
133
 * @access    private
134
 * @see       set_file
135
  */
136
  public $file     = array();
137

    
138
 /**
139
  * A hash of strings forming a translation table which translates variable names
140
  * into regular expressions for themselves.
141
  * $varkeys[varname] = "/varname/"
142
  *
143
 * @var       array
144
 * @access    private
145
 * @see       set_var
146
  */
147
  public $varkeys  = array();
148

    
149
 /**
150
  * A hash of strings forming a translation table which translates variable names
151
  * into values for their respective varkeys.
152
  * $varvals[varname] = "value"
153
  *
154
 * @var       array
155
 * @access    private
156
 * @see       set_var
157
  */
158
  public $varvals  = array();
159

    
160
 /**
161
  * Determines how to output variable tags with no assigned value in templates.
162
  *
163
 * @var       string
164
 * @access    private
165
 * @see       set_unknowns
166
  */
167
  public $unknowns = "remove";
168

    
169
 /**
170
  * Determines how Template handles error conditions.
171
  * "yes"      = the error is reported, then execution is halted
172
  * "report"   = the error is reported, then execution continues by returning "false"
173
  * "no"       = errors are silently ignored, and execution resumes reporting "false"
174
  *
175
 * @var       string
176
 * @access    public
177
 * @see       halt
178
  */
179
  public $halt_on_error  = "yes";
180

    
181
 /**
182
  * The last error message is retained in this variable.
183
  *
184
 * @var       string
185
 * @access    public
186
 * @see       halt
187
  */
188
  public $last_error     = "";
189

    
190
 /******************************************************************************
191
  * Class constructor. May be called with two optional parameters.
192
  * The first parameter sets the template directory the second parameter
193
  * sets the policy regarding handling of unknown variables.
194
  *
195
  * usage: Template([string $root = "."], [string $unknowns = "remove"])
196
  *
197
 * @param     $root        path to template directory
198
 * @param     $string      what to do with undefined variables
199
 * @see       set_root
200
 * @see       set_unknowns
201
 * @access    public
202
 * @return    void
203
  */
204
  public function __construct($root = ".", $unknowns = "remove") {
205
    if ($this->debug & 4) {
206
      echo "<p><b>Template:</b> root = $root, unknowns = $unknowns</p>\n";
207
    }
208
    $this->set_root($root);
209
    $this->set_unknowns($unknowns);
210
  }
211

    
212

    
213
 /******************************************************************************
214
  * Checks that $root is a valid directory and if so sets this directory as the
215
  * base directory from which templates are loaded by storing the value in
216
  * $this->root. Relative filenames are prepended with the path in $this->root.
217
  *
218
  * Returns true on success, false on error.
219
  *
220
  * usage: set_root(string $root)
221
  *
222
 * @param     $root         string containing new template directory
223
 * @see       root
224
 * @access    public
225
 * @return    boolean
226
  */
227
  public function set_root($root) {
228
    if(preg_match ('/\/$/', $root)) {
229
      $root = substr($root, 0, -1);
230
    }
231
    if ($this->debug & 4) {
232
      echo "<p><b>set_root:</b> root = $root</p>\n";
233
    }
234
    if (!is_dir($root)) {
235
      $this->halt("set_root: $root is not a directory.");
236
      return false;
237
    }
238

    
239
    $this->root = $root;
240
    return true;
241
  }
242

    
243

    
244
 /******************************************************************************
245
  * Sets the policy for dealing with unresolved variable names.
246
  *
247
  * unknowns defines what to do with undefined template variables
248
  * "remove"   = remove undefined variables
249
  * "comment"  = replace undefined variables with comments
250
  * "keep"     = keep undefined variables
251
  *
252
  * Note: "comment" can cause unexpected results when the variable tag is embedded
253
  * inside an HTML tag, for example a tag which is expected to be replaced with a URL.
254
  *
255
  * usage: set_unknowns(string $unknowns)
256
  *
257
 * @param     $unknowns         new value for unknowns
258
 * @see       unknowns
259
 * @access    public
260
 * @return    void
261
  */
262
  public function set_unknowns($unknowns = "remove") {
263
    if ($this->debug & 4) {
264
      echo "<p><b>unknowns:</b> unknowns = $unknowns</p>\n";
265
    }
266
    $this->unknowns = $unknowns;
267
  }
268

    
269

    
270
 /******************************************************************************
271
  * Defines a filename for the initial value of a variable.
272
  *
273
  * It may be passed either a varname and a file name as two strings or
274
  * a hash of strings with the key being the varname and the value
275
  * being the file name.
276
  *
277
  * The new mappings are stored in the array $this->file.
278
  * The files are not loaded yet, but only when needed.
279
  *
280
  * Returns true on success, false on error.
281
  *
282
  * usage: set_file(array $filelist = (string $varname => string $filename))
283
  * or
284
  * usage: set_file(string $varname, string $filename)
285
  *
286
 * @param     $varname      either a string containing a varname or a hash of varname/file name pairs.
287
 * @param     $filename     if varname is a string this is the filename otherwise filename is not required
288
 * @access    public
289
 * @return    boolean
290
  */
291
  public function set_file($varname, $filename = "") {
292
    if (!is_array($varname)) {
293
      if ($this->debug & 4) {
294
        echo "<p><b>set_file:</b> (with scalar) varname = $varname, filename = $filename</p>\n";
295
      }
296
      if ($filename == "") {
297
        $this->halt("set_file: For varname $varname filename is empty.");
298
        return false;
299
      }
300
      $this->file[$varname] = $this->filename($filename);
301
    } else {
302
      reset($varname);
303
      while (list($v, $f) = each($varname)) {
304
        if ($this->debug & 4) {
305
          echo "<p><b>set_file:</b> (with array) varname = $v, filename = $f</p>\n";
306
        }
307
        if ($f == "") {
308
          $this->halt("set_file: For varname $v filename is empty.");
309
          return false;
310
        }
311
        $this->file[$v] = $this->filename($f);
312
      }
313
    }
314
    return true;
315
  }
316

    
317

    
318
 /******************************************************************************
319
  * A variable $parent may contain a variable block defined by:
320
  * &lt;!-- BEGIN $varname --&gt; content &lt;!-- END $varname --&gt;. This function removes
321
  * that block from $parent and replaces it with a variable reference named $name.
322
  * The block is inserted into the varkeys and varvals hashes. If $name is
323
  * omitted, it is assumed to be the same as $varname.
324
  *
325
  * Blocks may be nested but care must be taken to extract the blocks in order
326
  * from the innermost block to the outermost block.
327
  *
328
  * Returns true on success, false on error.
329
  *
330
  * usage: set_block(string $parent, string $varname, [string $name = ""])
331
  *
332
 * @param     $parent       a string containing the name of the parent variable
333
 * @param     $varname      a string containing the name of the block to be extracted
334
 * @param     $name         the name of the variable in which to store the block
335
 * @access    public
336
 * @return    boolean
337
  */
338
  public function set_block($parent, $varname, $name = "") {
339
    if ($this->debug & 4) {
340
      echo "<p><b>set_block:</b> parent = $parent, varname = $varname, name = $name</p>\n";
341
    }
342
    if (!$this->loadfile($parent)) {
343
      $this->halt("set_block: unable to load $parent.");
344
      return false;
345
    }
346
    if ($name == "") {
347
      $name = $varname;
348
    }
349

    
350
    $str = $this->get_var($parent);
351
    $reg = '/[ \t]*<!--\s+BEGIN '.$varname.'\s+-->\s*?\n?(\s*.*?\n?)\s*<!--\s+END '.$varname.'\s+-->\s*?\n?/sm';
352
    preg_match_all($reg, $str, $m);
353
/* workaround to avoid problems with some WB files/modules (e.g. massmail)
354
    if (!isset($m[1][0])) {
355
      $this->halt("set_block: unable to set block $varname.");
356
      return false;
357
    }
358
*/
359
    $str = preg_replace($reg, "{" . $name . "}", $str);
360
    @$this->set_var($varname, (isset($m[1][0])?$m[1][0]:''));
361
    $this->set_var($parent, $str);
362
    return true;
363
  }
364

    
365

    
366
 /******************************************************************************
367
  * This functions sets the value of a variable.
368
  *
369
  * It may be called with either a varname and a value as two strings or an
370
  * an associative array with the key being the varname and the value being
371
  * the new variable value.
372
  *
373
  * The function inserts the new value of the variable into the $varkeys and
374
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
375
  * before calling this function.
376
  *
377
  * An optional third parameter allows the value for each varname to be appended
378
  * to the existing variable instead of replacing it. The default is to replace.
379
  * This feature was introduced after the 7.2d release.
380
  *
381
  *
382
  * usage: set_var(string $varname, [string $value = ""], [boolean $append = false])
383
  * or
384
  * usage: set_var(array $varname = (string $varname => string $value), [mixed $dummy_var], [boolean $append = false])
385
  *
386
 * @param     $varname      either a string containing a varname or a hash of varname/value pairs.
387
 * @param     $value        if $varname is a string this contains the new value for the variable otherwise this parameter is ignored
388
 * @param     $append       if true, the value is appended to the variable's existing value
389
 * @access    public
390
 * @return    void
391
  */
392
  public function set_var($varname, $value = "", $append = false) {
393
    if (!is_array($varname)) {
394
      if (!empty($varname)) {
395
        if ($this->debug & 1) {
396
          printf("<b>set_var:</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($value));
397
        }
398
        $this->varkeys[$varname] = "/".$this->varname($varname)."/";
399
        if ($append && isset($this->varvals[$varname])) {
400
          $this->varvals[$varname] .= $value;
401
        } else {
402
          $this->varvals[$varname] = $value;
403
        }
404
      }
405
    } else {
406
      reset($varname);
407
      while (list($k, $v) = each($varname)) {
408
        if (!empty($k)) {
409
          if ($this->debug & 1) {
410
            printf("<b>set_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $k, htmlentities($v));
411
          }
412
          $this->varkeys[$k] = "/".$this->varname($k)."/";
413
          if ($append && isset($this->varvals[$k])) {
414
            $this->varvals[$k] .= $v;
415
          } else {
416
            $this->varvals[$k] = $v;
417
          }
418
        }
419
      }
420
    }
421
  }
422

    
423

    
424
 /******************************************************************************
425
  * This functions clears the value of a variable.
426
  *
427
  * It may be called with either a varname as a string or an array with the
428
  * values being the varnames to be cleared.
429
  *
430
  * The function sets the value of the variable in the $varkeys and $varvals
431
  * hashes to "". It is not necessary for a variable to exist in these hashes
432
  * before calling this function.
433
  *
434
  *
435
  * usage: clear_var(string $varname)
436
  * or
437
  * usage: clear_var(array $varname = (string $varname))
438
  *
439
 * @param     $varname      either a string containing a varname or an array of varnames.
440
 * @access    public
441
 * @return    void
442
  */
443
  public function clear_var($varname) {
444
    if (!is_array($varname)) {
445
      if (!empty($varname)) {
446
        if ($this->debug & 1) {
447
          printf("<b>clear_var:</b> (with scalar) <b>%s</b><br>\n", $varname);
448
        }
449
        $this->set_var($varname, "");
450
      }
451
    } else {
452
      reset($varname);
453
      while (list($k, $v) = each($varname)) {
454
        if (!empty($v)) {
455
          if ($this->debug & 1) {
456
            printf("<b>clear_var:</b> (with array) <b>%s</b><br>\n", $v);
457
          }
458
          $this->set_var($v, "");
459
        }
460
      }
461
    }
462
  }
463

    
464

    
465
 /******************************************************************************
466
  * This functions unsets a variable completely.
467

    
468
  * It may be called with either a varname as a string or an array with the
469
  * values being the varnames to be cleared.
470
  *
471
  * The function removes the variable from the $varkeys and $varvals hashes.
472
  * It is not necessary for a variable to exist in these hashes before calling
473
  * this function.
474
  *
475
  *
476
  * usage: unset_var(string $varname)
477
  * or
478
  * usage: unset_var(array $varname = (string $varname))
479
  *
480
 * @param     $varname      either a string containing a varname or an array of varnames.
481
 * @access    public
482
 * @return    void
483
  */
484
  public function unset_var($varname) {
485
    if (!is_array($varname)) {
486
      if (!empty($varname)) {
487
        if ($this->debug & 1) {
488
          printf("<b>unset_var:</b> (with scalar) <b>%s</b><br>\n", $varname);
489
        }
490
        unset($this->varkeys[$varname]);
491
        unset($this->varvals[$varname]);
492
      }
493
    } else {
494
      reset($varname);
495
      while (list($k, $v) = each($varname)) {
496
        if (!empty($v)) {
497
          if ($this->debug & 1) {
498
            printf("<b>unset_var:</b> (with array) <b>%s</b><br>\n", $v);
499
          }
500
          unset($this->varkeys[$v]);
501
          unset($this->varvals[$v]);
502
        }
503
      }
504
    }
505
  }
506

    
507

    
508
 /******************************************************************************
509
  * This function fills in all the variables contained within the variable named
510
  * $varname. The resulting value is returned as the function result and the
511
  * original value of the variable varname is not changed. The resulting string
512
  * is not "finished", that is, the unresolved variable name policy has not been
513
  * applied yet.
514
  *
515
  * Returns: the value of the variable $varname with all variables substituted.
516
  *
517
  * usage: subst(string $varname)
518
  *
519
 * @param     $varname      the name of the variable within which variables are to be substituted
520
 * @access    public
521
 * @return    string
522
  */
523
    protected function subst($varname) {
524
    $varvals_quoted = array();
525
    if ($this->debug & 4) {
526
      echo "<p><b>subst:</b> varname = $varname</p>\n";
527
    }
528
    if (!$this->loadfile($varname)) {
529
      $this->halt("subst: unable to load $varname.");
530
      return false;
531
    }
532

    
533
    // quote the replacement strings to prevent bogus stripping of special chars
534
    reset($this->varvals);
535
    while (list($k, $v) = each($this->varvals)) {
536
      $varvals_quoted[$k] = preg_replace(array('/\\\\/', '/\$/'), array('\\\\\\\\', '\\\\$'), $v);
537
    }
538
    $str = $this->get_var($varname);
539
    $str = @preg_replace($this->varkeys, $varvals_quoted, $str);
540
    if (class_exists('ParseError')) {
541
        $bRetval = true;
542
        try{
543
            $str = @preg_replace($this->varkeys, $varvals_quoted, $str);
544
        } catch(ParseError $e) {
545
            echo "<p><b>subst:</b> varname = $varname</p>\n";
546
        }
547
    } else {
548
        $str = @preg_replace($this->varkeys, $varvals_quoted, $str);
549
    }
550
    return $str;
551
  }
552

    
553

    
554
 /******************************************************************************
555
  * This is shorthand for print $this->subst($varname). See subst for further
556
  * details.
557
  *
558
  * Returns: always returns false.
559
  *
560
  * usage: psubst(string $varname)
561
  *
562
 * @param     $varname      the name of the variable within which variables are to be substituted
563
 * @access    public
564
 * @return    false
565
 * @see       subst
566
  */
567
  public function psubst($varname) {
568
    if ($this->debug & 4) {
569
      echo "<p><b>psubst:</b> varname = $varname</p>\n";
570
    }
571
    print $this->subst($varname);
572

    
573
    return false;
574
  }
575

    
576

    
577
 /******************************************************************************
578
  * The function substitutes the values of all defined variables in the variable
579
  * named $varname and stores or appends the result in the variable named $target.
580
  *
581
  * It may be called with either a target and a varname as two strings or a
582
  * target as a string and an array of variable names in varname.
583
  *
584
  * The function inserts the new value of the variable into the $varkeys and
585
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
586
  * before calling this function.
587
  *
588
  * An optional third parameter allows the value for each varname to be appended
589
  * to the existing target variable instead of replacing it. The default is to
590
  * replace.
591
  *
592
  * If $target and $varname are both strings, the substituted value of the
593
  * variable $varname is inserted into or appended to $target.
594
  *
595
  * If $handle is an array of variable names the variables named by $handle are
596
  * sequentially substituted and the result of each substitution step is
597
  * inserted into or appended to in $target. The resulting substitution is
598
  * available in the variable named by $target, as is each intermediate step
599
  * for the next $varname in sequence. Note that while it is possible, it
600
  * is only rarely desirable to call this function with an array of varnames
601
  * and with $append = true. This append feature was introduced after the 7.2d
602
  * release.
603
  *
604
  * Returns: the last value assigned to $target.
605
  *
606
  * usage: parse(string $target, string $varname, [boolean $append])
607
  * or
608
  * usage: parse(string $target, array $varname = (string $varname), [boolean $append])
609
  *
610
 * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
611
 * @param     $varname     if a string, the name the name of the variable to substitute or if an array a list of variables to be substituted
612
 * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
613
 * @access    public
614
 * @return    string
615
 * @see       subst
616
  */
617
  public function parse($target, $varname, $append = false) {
618
    if (!is_array($varname)) {
619
      if ($this->debug & 4) {
620
        echo "<p><b>parse:</b> (with scalar) target = $target, varname = $varname, append = $append</p>\n";
621
      }
622
      $str = $this->subst($varname);
623
      if ($append) {
624
        $this->set_var($target, $this->get_var($target) . $str);
625
      } else {
626
        $this->set_var($target, $str);
627
      }
628
    } else {
629
      reset($varname);
630
      while (list($i, $v) = each($varname)) {
631
        if ($this->debug & 4) {
632
          echo "<p><b>parse:</b> (with array) target = $target, i = $i, varname = $v, append = $append</p>\n";
633
        }
634
        $str = $this->subst($v);
635
        if ($append) {
636
          $this->set_var($target, $this->get_var($target) . $str);
637
        } else {
638
          $this->set_var($target, $str);
639
        }
640
      }
641
    }
642

    
643
    if ($this->debug & 4) {
644
      echo "<p><b>parse:</b> completed</p>\n";
645
    }
646
    return $this->get_var($target);
647
  }
648

    
649

    
650
 /******************************************************************************
651
  * This is shorthand for print $this->parse(...) and is functionally identical.
652
  * See parse for further details.
653
  *
654
  * Returns: always returns false.
655
  *
656
  * usage: pparse(string $target, string $varname, [boolean $append])
657
  * or
658
  * usage: pparse(string $target, array $varname = (string $varname), [boolean $append])
659
  *
660
 * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
661
 * @param     $varname     if a string, the name the name of the variable to substitute or if an array a list of variables to be substituted
662
 * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
663
 * @access    public
664
 * @return    false
665
 * @see       parse
666
  */
667
  public function pparse($target, $varname, $append = false, $clear = true) { // added $clear: whether to delete undefined vars or not (needed for wb-module code) - thorn
668
    if ($this->debug & 4) {
669
      echo "<p><b>pparse:</b> passing parameters to parse...</p>\n";
670
    }
671
        if(!$clear) {
672
            $unknowns = $this->unknowns;
673
            $this->set_unknowns('keep');
674
            print $this->finish($this->parse($target, $varname, $append));
675
            $this->set_unknowns($unknowns);
676
        } else {
677
            print $this->finish($this->parse($target, $varname, $append));
678
        }
679
        return false;
680
  }
681

    
682

    
683
 /******************************************************************************
684
  * This function returns an associative array of all defined variables with the
685
  * name as the key and the value of the variable as the value.
686
  *
687
  * This is mostly useful for debugging. Also note that $this->debug can be used
688
  * to echo all variable assignments as they occur and to trace execution.
689
  *
690
  * Returns: a hash of all defined variable values keyed by their names.
691
  *
692
  * usage: get_vars()
693
  *
694
 * @access    public
695
 * @return    array
696
 * @see       $debug
697
  */
698
  public function get_vars() {
699
    if ($this->debug & 4) {
700
      echo "<p><b>get_vars:</b> constructing array of vars...</p>\n";
701
    }
702
    reset($this->varkeys);
703
    while (list($k, $v) = each($this->varkeys)) {
704
      $result[$k] = $this->get_var($k);
705
    }
706
    return $result;
707
  }
708

    
709

    
710
 /******************************************************************************
711
  * This function returns the value of the variable named by $varname.
712
  * If $varname references a file and that file has not been loaded yet, the
713
  * variable will be reported as empty.
714
  *
715
  * When called with an array of variable names this function will return a a
716
  * hash of variable values keyed by their names.
717
  *
718
  * Returns: a string or an array containing the value of $varname.
719
  *
720
  * usage: get_var(string $varname)
721
  * or
722
  * usage: get_var(array $varname)
723
  *
724
 * @param     $varname     if a string, the name the name of the variable to get the value of, or if an array a list of variables to return the value of
725
 * @access    public
726
 * @return    string or array
727
  */
728
  public function get_var($varname) {
729
    if (!is_array($varname)) {
730
      if (isset($this->varvals[$varname])) {
731
        $str = $this->varvals[$varname];
732
      } else {
733
        $str = "";
734
      }
735
      if ($this->debug & 2) {
736
        printf ("<b>get_var</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($str));
737
      }
738
      return $str;
739
    } else {
740
      reset($varname);
741
      while (list($k, $v) = each($varname)) {
742
        if (isset($this->varvals[$v])) {
743
          $str = $this->varvals[$v];
744
        } else {
745
          $str = "";
746
        }
747
        if ($this->debug & 2) {
748
          printf ("<b>get_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $v, htmlentities($str));
749
        }
750
        $result[$v] = $str;
751
      }
752
      return $result;
753
    }
754
  }
755

    
756

    
757
 /******************************************************************************
758
  * This function returns a hash of unresolved variable names in $varname, keyed
759
  * by their names (that is, the hash has the form $a[$name] = $name).
760
  *
761
  * Returns: a hash of varname/varname pairs or false on error.
762
  *
763
  * usage: get_undefined(string $varname)
764
  *
765
 * @param     $varname     a string containing the name the name of the variable to scan for unresolved variables
766
 * @access    public
767
 * @return    array
768
  */
769
  public function get_undefined($varname) {
770
    if ($this->debug & 4) {
771
      echo "<p><b>get_undefined:</b> varname = $varname</p>\n";
772
    }
773
    if (!$this->loadfile($varname)) {
774
      $this->halt("get_undefined: unable to load $varname.");
775
      return false;
776
    }
777

    
778
    preg_match_all(
779
        (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
780
        $this->get_var($varname),
781
        $m);
782
    $m = $m[1];
783
    if (!is_array($m)) {
784
      return false;
785
    }
786

    
787
    reset($m);
788
    while (list($k, $v) = each($m)) {
789
      if (!isset($this->varkeys[$v])) {
790
        if ($this->debug & 4) {
791
         echo "<p><b>get_undefined:</b> undefined: $v</p>\n";
792
        }
793
        $result[$v] = $v;
794
      }
795
    }
796

    
797
    if (count($result)) {
798
      return $result;
799
    } else {
800
      return false;
801
    }
802
  }
803

    
804

    
805
 /******************************************************************************
806
  * This function returns the finished version of $str. That is, the policy
807
  * regarding unresolved variable names will be applied to $str.
808
  *
809
  * Returns: a finished string derived from $str and $this->unknowns.
810
  *
811
  * usage: finish(string $str)
812
  *
813
 * @param     $str         a string to which to apply the unresolved variable policy
814
 * @access    public
815
 * @return    string
816
 * @see       set_unknowns
817
  */
818
  public function finish($str) {
819
    switch ($this->unknowns) {
820
      case "keep":
821
      break;
822

    
823
      case "remove":
824
        $str = preg_replace(
825
            (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
826
            "",
827
            $str);
828
      break;
829

    
830
      case "comment":
831
        $str = preg_replace(
832
             (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
833
            "<!-- Template variable \\1 undefined -->",
834
            $str);
835
      break;
836
    }
837

    
838
    return $str;
839
  }
840

    
841

    
842
 /******************************************************************************
843
  * This function prints the finished version of the value of the variable named
844
  * by $varname. That is, the policy regarding unresolved variable names will be
845
  * applied to the variable $varname then it will be printed.
846
  *
847
  * usage: p(string $varname)
848
  *
849
 * @param     $varname     a string containing the name of the variable to finish and print
850
 * @access    public
851
 * @return    void
852
 * @see       set_unknowns
853
 * @see       finish
854
  */
855
  public function p($varname) {
856
    print $this->finish($this->get_var($varname));
857
  }
858

    
859

    
860
 /******************************************************************************
861
  * This function returns the finished version of the value of the variable named
862
  * by $varname. That is, the policy regarding unresolved variable names will be
863
  * applied to the variable $varname and the result returned.
864
  *
865
  * Returns: a finished string derived from the variable $varname.
866
  *
867
  * usage: get(string $varname)
868
  *
869
 * @param     $varname     a string containing the name of the variable to finish
870
 * @access    public
871
 * @return    void
872
 * @see       set_unknowns
873
 * @see       finish
874
  */
875
  public function get($varname) {
876
    return $this->finish($this->get_var($varname));
877
  }
878

    
879

    
880
 /******************************************************************************
881
  * When called with a relative pathname, this function will return the pathname
882
  * with $this->root prepended. Absolute pathnames are returned unchanged.
883
  *
884
  * Returns: a string containing an absolute pathname.
885
  *
886
  * usage: filename(string $filename)
887
  *
888
 * @param     $filename    a string containing a filename
889
 * @access    private
890
 * @return    string
891
 * @see       set_root
892
  */
893
  public function filename($filename) {
894
    if ($this->debug & 4) {
895
      echo "<p><b>filename:</b> filename = $filename</p>\n";
896
    }
897
    if (substr($filename, 0, 1) != "/"
898
       && substr($filename, 0, 1) != "\\"
899
       && substr($filename, 1, 2) != ":\\"
900
       && substr($filename, 1, 2) != ":/"
901
    ) {
902
      $filename = $this->root."/".$filename;
903
    }
904

    
905
    if (!file_exists($filename)) {
906
      $this->halt("filename: file $filename does not exist.");
907
    }
908
    return $filename;
909
  }
910

    
911

    
912
 /******************************************************************************
913
  * This function will construct a regexp for a given variable name with any
914
  * special chars quoted.
915
  *
916
  * Returns: a string containing an escaped variable name.
917
  *
918
  * usage: varname(string $varname)
919
  *
920
 * @param     $varname    a string containing a variable name
921
 * @access    private
922
 * @return    string
923
  */
924
  public function varname($varname) {
925
    return preg_quote("{" . $varname . "}");
926
  }
927

    
928

    
929
 /******************************************************************************
930
  * If a variable's value is undefined and the variable has a filename stored in
931
  * $this->file[$varname] then the backing file will be loaded and the file's
932
  * contents will be assigned as the variable's value.
933
  *
934
  * Note that the behaviour of this function changed slightly after the 7.2d
935
  * release. Where previously a variable was reloaded from file if the value
936
  * was empty, now this is not done. This allows a variable to be loaded then
937
  * set to "", and also prevents attempts to load empty variables. Files are
938
  * now only loaded if $this->varvals[$varname] is unset.
939
  *
940
  * Returns: true on success, false on error.
941
  *
942
  * usage: loadfile(string $varname)
943
  *
944
 * @param     $varname    a string containing the name of a variable to load
945
 * @access    private
946
 * @return    boolean
947
 * @see       set_file
948
  */
949
  public function loadfile($varname) {
950
    if ($this->debug & 4) {
951
      echo "<p><b>loadfile:</b> varname = $varname</p>\n";
952
    }
953

    
954
    if (!isset($this->file[$varname])) {
955
      // $varname does not reference a file so return
956
      if ($this->debug & 4) {
957
        echo "<p><b>loadfile:</b> varname $varname does not reference a file</p>\n";
958
      }
959
      return true;
960
    }
961

    
962
    if (isset($this->varvals[$varname])) {
963
      // will only be unset if varname was created with set_file and has never been loaded
964
      // $varname has already been loaded so return
965
      if ($this->debug & 4) {
966
        echo "<p><b>loadfile:</b> varname $varname is already loaded</p>\n";
967
      }
968
      return true;
969
    }
970
    $filename = $this->file[$varname];
971

    
972
    /* use @file here to avoid leaking filesystem information if there is an error */
973
    $str = implode("", @file($filename));
974
    if (empty($str)) {
975
      $this->halt("loadfile: While loading $varname, $filename does not exist or is empty.");
976
      return false;
977
    }
978

    
979
    if ($this->filename_comments) {
980
      $str = "<!-- START FILE $filename -->\n$str<!-- END FILE $filename -->\n";
981
    }
982
    if ($this->debug & 4) {
983
      printf("<b>loadfile:</b> loaded $filename into $varname<br>\n");
984
    }
985
    $this->set_var($varname, $str);
986

    
987
    return true;
988
  }
989

    
990

    
991
 /******************************************************************************
992
  * This function is called whenever an error occurs and will handle the error
993
  * according to the policy defined in $this->halt_on_error. Additionally the
994
  * error message will be saved in $this->last_error.
995
  *
996
  * Returns: always returns false.
997
  *
998
  * usage: halt(string $msg)
999
  *
1000
 * @param     $msg         a string containing an error message
1001
 * @access    private
1002
 * @return    void
1003
 * @see       $halt_on_error
1004
  */
1005
  public function halt($msg) {
1006
    $this->last_error = $msg;
1007

    
1008
    if ($this->halt_on_error != "no") {
1009
      $this->haltmsg($msg);
1010
    }
1011

    
1012
    if ($this->halt_on_error == "yes") {
1013
      die("<b>Halted.</b>");
1014
    }
1015

    
1016
    return false;
1017
  }
1018

    
1019

    
1020
 /******************************************************************************
1021
  * This function prints an error message.
1022
  * It can be overridden by your subclass of Template. It will be called with an
1023
  * error message to display.
1024
  *
1025
  * usage: haltmsg(string $msg)
1026
  *
1027
 * @param     $msg         a string containing the error message to display
1028
 * @access    public
1029
 * @return    void
1030
 * @see       halt
1031
  */
1032
  public function haltmsg($msg) {
1033
    printf("<b>Template Error:</b> %s<br>\n", $msg);
1034
  }
1035

    
1036
}
(2-2/2)