Project

General

Profile

1 1289 kweitzel
<?php
2
3
// $Id$
4
5
/*
6
 * Session Management for PHP3
7
 *
8
 * (C) Copyright 1999-2000 NetUSE GmbH
9
 *                    Kristian Koehntopp
10
 *
11
 * $Id$
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
  var $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
  var $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
  var $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
  var $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
  var $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
  var $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
  var $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
  var $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
  var $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
  var $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
  var $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
  function Template($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
  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
  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
  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
  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, $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
  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
  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
  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
  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
539
    $str = $this->get_var($varname);
540
    $str = preg_replace($this->varkeys, $varvals_quoted, $str);
541
    return $str;
542
  }
543
544
545
 /******************************************************************************
546
  * This is shorthand for print $this->subst($varname). See subst for further
547
  * details.
548
  *
549
  * Returns: always returns false.
550
  *
551
  * usage: psubst(string $varname)
552
  *
553
  * @param     $varname      the name of the variable within which variables are to be substituted
554
  * @access    public
555
  * @return    false
556
  * @see       subst
557
  */
558
  function psubst($varname) {
559
    if ($this->debug & 4) {
560
      echo "<p><b>psubst:</b> varname = $varname</p>\n";
561
    }
562
    print $this->subst($varname);
563
564
    return false;
565
  }
566
567
568
 /******************************************************************************
569
  * The function substitutes the values of all defined variables in the variable
570
  * named $varname and stores or appends the result in the variable named $target.
571
  *
572
  * It may be called with either a target and a varname as two strings or a
573
  * target as a string and an array of variable names in varname.
574
  *
575
  * The function inserts the new value of the variable into the $varkeys and
576
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
577
  * before calling this function.
578
  *
579
  * An optional third parameter allows the value for each varname to be appended
580
  * to the existing target variable instead of replacing it. The default is to
581
  * replace.
582
  *
583
  * If $target and $varname are both strings, the substituted value of the
584
  * variable $varname is inserted into or appended to $target.
585
  *
586
  * If $handle is an array of variable names the variables named by $handle are
587
  * sequentially substituted and the result of each substitution step is
588
  * inserted into or appended to in $target. The resulting substitution is
589
  * available in the variable named by $target, as is each intermediate step
590
  * for the next $varname in sequence. Note that while it is possible, it
591
  * is only rarely desirable to call this function with an array of varnames
592
  * and with $append = true. This append feature was introduced after the 7.2d
593
  * release.
594
  *
595
  * Returns: the last value assigned to $target.
596
  *
597
  * usage: parse(string $target, string $varname, [boolean $append])
598
  * or
599
  * usage: parse(string $target, array $varname = (string $varname), [boolean $append])
600
  *
601
  * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
602
  * @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
603
  * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
604
  * @access    public
605
  * @return    string
606
  * @see       subst
607
  */
608
  function parse($target, $varname, $append = false) {
609
    if (!is_array($varname)) {
610
      if ($this->debug & 4) {
611
        echo "<p><b>parse:</b> (with scalar) target = $target, varname = $varname, append = $append</p>\n";
612
      }
613
      $str = $this->subst($varname);
614
      if ($append) {
615
        $this->set_var($target, $this->get_var($target) . $str);
616
      } else {
617
        $this->set_var($target, $str);
618
      }
619
    } else {
620
      reset($varname);
621
      while (list($i, $v) = each($varname)) {
622
        if ($this->debug & 4) {
623
          echo "<p><b>parse:</b> (with array) target = $target, i = $i, varname = $v, append = $append</p>\n";
624
        }
625
        $str = $this->subst($v);
626
        if ($append) {
627
          $this->set_var($target, $this->get_var($target) . $str);
628
        } else {
629
          $this->set_var($target, $str);
630
        }
631
      }
632
    }
633
634
    if ($this->debug & 4) {
635
      echo "<p><b>parse:</b> completed</p>\n";
636
    }
637
    return $this->get_var($target);
638
  }
639
640
641
 /******************************************************************************
642
  * This is shorthand for print $this->parse(...) and is functionally identical.
643
  * See parse for further details.
644
  *
645
  * Returns: always returns false.
646
  *
647
  * usage: pparse(string $target, string $varname, [boolean $append])
648
  * or
649
  * usage: pparse(string $target, array $varname = (string $varname), [boolean $append])
650
  *
651
  * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
652
  * @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
653
  * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
654
  * @access    public
655
  * @return    false
656
  * @see       parse
657
  */
658
  function pparse($target, $varname, $append = false, $clear = true) { // added $clear: whether to delete undefined vars or not (needed for wb-module code) - thorn
659
    if ($this->debug & 4) {
660
      echo "<p><b>pparse:</b> passing parameters to parse...</p>\n";
661
    }
662
		if(!$clear) {
663
			$unknowns = $this->unknowns;
664
			$this->set_unknowns('keep');
665
			print $this->finish($this->parse($target, $varname, $append));
666
			$this->set_unknowns($unknowns);
667
		} else {
668
			print $this->finish($this->parse($target, $varname, $append));
669
		}
670
		return false;
671
  }
672
673
674
 /******************************************************************************
675
  * This function returns an associative array of all defined variables with the
676
  * name as the key and the value of the variable as the value.
677
  *
678
  * This is mostly useful for debugging. Also note that $this->debug can be used
679
  * to echo all variable assignments as they occur and to trace execution.
680
  *
681
  * Returns: a hash of all defined variable values keyed by their names.
682
  *
683
  * usage: get_vars()
684
  *
685
  * @access    public
686
  * @return    array
687
  * @see       $debug
688
  */
689
  function get_vars() {
690
    if ($this->debug & 4) {
691
      echo "<p><b>get_vars:</b> constructing array of vars...</p>\n";
692
    }
693
    reset($this->varkeys);
694
    while (list($k, $v) = each($this->varkeys)) {
695
      $result[$k] = $this->get_var($k);
696
    }
697
    return $result;
698
  }
699
700
701
 /******************************************************************************
702
  * This function returns the value of the variable named by $varname.
703
  * If $varname references a file and that file has not been loaded yet, the
704
  * variable will be reported as empty.
705
  *
706
  * When called with an array of variable names this function will return a a
707
  * hash of variable values keyed by their names.
708
  *
709
  * Returns: a string or an array containing the value of $varname.
710
  *
711
  * usage: get_var(string $varname)
712
  * or
713
  * usage: get_var(array $varname)
714
  *
715
  * @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
716
  * @access    public
717
  * @return    string or array
718
  */
719
  function get_var($varname) {
720
    if (!is_array($varname)) {
721
      if (isset($this->varvals[$varname])) {
722
        $str = $this->varvals[$varname];
723
      } else {
724
        $str = "";
725
      }
726
      if ($this->debug & 2) {
727
        printf ("<b>get_var</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($str));
728
      }
729
      return $str;
730
    } else {
731
      reset($varname);
732
      while (list($k, $v) = each($varname)) {
733
        if (isset($this->varvals[$v])) {
734
          $str = $this->varvals[$v];
735
        } else {
736
          $str = "";
737
        }
738
        if ($this->debug & 2) {
739
          printf ("<b>get_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $v, htmlentities($str));
740
        }
741
        $result[$v] = $str;
742
      }
743
      return $result;
744
    }
745
  }
746
747
748
 /******************************************************************************
749
  * This function returns a hash of unresolved variable names in $varname, keyed
750
  * by their names (that is, the hash has the form $a[$name] = $name).
751
  *
752
  * Returns: a hash of varname/varname pairs or false on error.
753
  *
754
  * usage: get_undefined(string $varname)
755
  *
756
  * @param     $varname     a string containing the name the name of the variable to scan for unresolved variables
757
  * @access    public
758
  * @return    array
759
  */
760
  function get_undefined($varname) {
761
    if ($this->debug & 4) {
762
      echo "<p><b>get_undefined:</b> varname = $varname</p>\n";
763
    }
764
    if (!$this->loadfile($varname)) {
765
      $this->halt("get_undefined: unable to load $varname.");
766
      return false;
767
    }
768
769
    preg_match_all(
770
        (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
771
        $this->get_var($varname),
772
        $m);
773
    $m = $m[1];
774
    if (!is_array($m)) {
775
      return false;
776
    }
777
778
    reset($m);
779
    while (list($k, $v) = each($m)) {
780
      if (!isset($this->varkeys[$v])) {
781
        if ($this->debug & 4) {
782
         echo "<p><b>get_undefined:</b> undefined: $v</p>\n";
783
        }
784
        $result[$v] = $v;
785
      }
786
    }
787
788
    if (count($result)) {
789
      return $result;
790
    } else {
791
      return false;
792
    }
793
  }
794
795
796
 /******************************************************************************
797
  * This function returns the finished version of $str. That is, the policy
798
  * regarding unresolved variable names will be applied to $str.
799
  *
800
  * Returns: a finished string derived from $str and $this->unknowns.
801
  *
802
  * usage: finish(string $str)
803
  *
804
  * @param     $str         a string to which to apply the unresolved variable policy
805
  * @access    public
806
  * @return    string
807
  * @see       set_unknowns
808
  */
809
  function finish($str) {
810
    switch ($this->unknowns) {
811
      case "keep":
812
      break;
813
814
      case "remove":
815
        $str = preg_replace(
816
            (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
817
            "",
818
            $str);
819
      break;
820
821
      case "comment":
822
        $str = preg_replace(
823
             (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
824
            "<!-- Template variable \\1 undefined -->",
825
            $str);
826
      break;
827
    }
828
829
    return $str;
830
  }
831
832
833
 /******************************************************************************
834
  * This function prints the finished version of the value of the variable named
835
  * by $varname. That is, the policy regarding unresolved variable names will be
836
  * applied to the variable $varname then it will be printed.
837
  *
838
  * usage: p(string $varname)
839
  *
840
  * @param     $varname     a string containing the name of the variable to finish and print
841
  * @access    public
842
  * @return    void
843
  * @see       set_unknowns
844
  * @see       finish
845
  */
846
  function p($varname) {
847
    print $this->finish($this->get_var($varname));
848
  }
849
850
851
 /******************************************************************************
852
  * This function returns the finished version of the value of the variable named
853
  * by $varname. That is, the policy regarding unresolved variable names will be
854
  * applied to the variable $varname and the result returned.
855
  *
856
  * Returns: a finished string derived from the variable $varname.
857
  *
858
  * usage: get(string $varname)
859
  *
860
  * @param     $varname     a string containing the name of the variable to finish
861
  * @access    public
862
  * @return    void
863
  * @see       set_unknowns
864
  * @see       finish
865
  */
866
  function get($varname) {
867
    return $this->finish($this->get_var($varname));
868
  }
869
870
871
 /******************************************************************************
872
  * When called with a relative pathname, this function will return the pathname
873
  * with $this->root prepended. Absolute pathnames are returned unchanged.
874
  *
875
  * Returns: a string containing an absolute pathname.
876
  *
877
  * usage: filename(string $filename)
878
  *
879
  * @param     $filename    a string containing a filename
880
  * @access    private
881
  * @return    string
882
  * @see       set_root
883
  */
884
  function filename($filename) {
885
    if ($this->debug & 4) {
886
      echo "<p><b>filename:</b> filename = $filename</p>\n";
887
    }
888
    if (substr($filename, 0, 1) != "/"
889
       && substr($filename, 0, 1) != "\\"
890
       && substr($filename, 1, 2) != ":\\"
891
       && substr($filename, 1, 2) != ":/"
892
    ) {
893
      $filename = $this->root."/".$filename;
894
    }
895
896
    if (!file_exists($filename)) {
897
      $this->halt("filename: file $filename does not exist.");
898
    }
899
    return $filename;
900
  }
901
902
903
 /******************************************************************************
904
  * This function will construct a regexp for a given variable name with any
905
  * special chars quoted.
906
  *
907
  * Returns: a string containing an escaped variable name.
908
  *
909
  * usage: varname(string $varname)
910
  *
911
  * @param     $varname    a string containing a variable name
912
  * @access    private
913
  * @return    string
914
  */
915
  function varname($varname) {
916
    return preg_quote("{" . $varname . "}");
917
  }
918
919
920
 /******************************************************************************
921
  * If a variable's value is undefined and the variable has a filename stored in
922
  * $this->file[$varname] then the backing file will be loaded and the file's
923
  * contents will be assigned as the variable's value.
924
  *
925
  * Note that the behaviour of this function changed slightly after the 7.2d
926
  * release. Where previously a variable was reloaded from file if the value
927
  * was empty, now this is not done. This allows a variable to be loaded then
928
  * set to "", and also prevents attempts to load empty variables. Files are
929
  * now only loaded if $this->varvals[$varname] is unset.
930
  *
931
  * Returns: true on success, false on error.
932
  *
933
  * usage: loadfile(string $varname)
934
  *
935
  * @param     $varname    a string containing the name of a variable to load
936
  * @access    private
937
  * @return    boolean
938
  * @see       set_file
939
  */
940
  function loadfile($varname) {
941
    if ($this->debug & 4) {
942
      echo "<p><b>loadfile:</b> varname = $varname</p>\n";
943
    }
944
945
    if (!isset($this->file[$varname])) {
946
      // $varname does not reference a file so return
947
      if ($this->debug & 4) {
948
        echo "<p><b>loadfile:</b> varname $varname does not reference a file</p>\n";
949
      }
950
      return true;
951
    }
952
953
    if (isset($this->varvals[$varname])) {
954
      // will only be unset if varname was created with set_file and has never been loaded
955
      // $varname has already been loaded so return
956
      if ($this->debug & 4) {
957
        echo "<p><b>loadfile:</b> varname $varname is already loaded</p>\n";
958
      }
959
      return true;
960
    }
961
    $filename = $this->file[$varname];
962
963
    /* use @file here to avoid leaking filesystem information if there is an error */
964
    $str = implode("", @file($filename));
965
    if (empty($str)) {
966
      $this->halt("loadfile: While loading $varname, $filename does not exist or is empty.");
967
      return false;
968
    }
969
970
    if ($this->filename_comments) {
971
      $str = "<!-- START FILE $filename -->\n$str<!-- END FILE $filename -->\n";
972
    }
973
    if ($this->debug & 4) {
974
      printf("<b>loadfile:</b> loaded $filename into $varname<br>\n");
975
    }
976
    $this->set_var($varname, $str);
977
978
    return true;
979
  }
980
981
982
 /******************************************************************************
983
  * This function is called whenever an error occurs and will handle the error
984
  * according to the policy defined in $this->halt_on_error. Additionally the
985
  * error message will be saved in $this->last_error.
986
  *
987
  * Returns: always returns false.
988
  *
989
  * usage: halt(string $msg)
990
  *
991
  * @param     $msg         a string containing an error message
992
  * @access    private
993
  * @return    void
994
  * @see       $halt_on_error
995
  */
996
  function halt($msg) {
997
    $this->last_error = $msg;
998
999
    if ($this->halt_on_error != "no") {
1000
      $this->haltmsg($msg);
1001
    }
1002
1003
    if ($this->halt_on_error == "yes") {
1004
      die("<b>Halted.</b>");
1005
    }
1006
1007
    return false;
1008
  }
1009
1010
1011
 /******************************************************************************
1012
  * This function prints an error message.
1013
  * It can be overridden by your subclass of Template. It will be called with an
1014
  * error message to display.
1015
  *
1016
  * usage: haltmsg(string $msg)
1017
  *
1018
  * @param     $msg         a string containing the error message to display
1019
  * @access    public
1020
  * @return    void
1021
  * @see       halt
1022
  */
1023
  function haltmsg($msg) {
1024
    printf("<b>Template Error:</b> %s<br>\n", $msg);
1025
  }
1026
1027
}
1028
?>