Project

General

Profile

1
<?php
2

    
3
// $Id: template.inc 28 2017-11-11 16:48:31Z Manuela $
4

    
5
/*
6
 * Session Management for PHP3
7
 *
8
 * (C) Copyright 1999-2000 NetUSE GmbH
9
 *                    Kristian Koehntopp
10
 *
11
 * $Id: template.inc 28 2017-11-11 16:48:31Z 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
if (is_readable(__DIR__.'/FtanTrait.php') and !trait_exists('\FtanTrait', false)) {
71
    include __DIR__.'/FtanTrait.php';
72
}
73

    
74
class Template
75
{
76
    use \FtanTrait;
77
 /**
78
  * Serialization helper, the name of this class.
79
  *
80
 * @var       string
81
 * @access    public
82
  */
83
  public $classname = "Template";
84

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

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

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

    
123
 /**
124
  * The base directory from which template files are loaded.
125
  *
126
 * @var       string
127
 * @access    private
128
 * @see       set_root
129
  */
130
  public $root     = ".";
131

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

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

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

    
165
 /**
166
  * Determines how to output variable tags with no assigned value in templates.
167
  *
168
 * @var       string
169
 * @access    private
170
 * @see       set_unknowns
171
  */
172
  public $unknowns = "remove";
173

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

    
186
 /**
187
  * The last error message is retained in this variable.
188
  *
189
 * @var       string
190
 * @access    public
191
 * @see       halt
192
  */
193
  public $last_error     = "";
194

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

    
217

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

    
244
    $this->root = $root;
245
    return true;
246
  }
247

    
248

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

    
274

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

    
322

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

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

    
370

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

    
428

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

    
469

    
470
 /******************************************************************************
471
  * This functions unsets a variable completely.
472

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

    
512

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

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

    
558

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

    
578
    return false;
579
  }
580

    
581

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

    
648
    if ($this->debug & 4) {
649
      echo "<p><b>parse:</b> completed</p>\n";
650
    }
651
    return $this->get_var($target);
652
  }
653

    
654

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

    
687

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

    
714

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

    
761

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

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

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

    
802
    if (count($result)) {
803
      return $result;
804
    } else {
805
      return false;
806
    }
807
  }
808

    
809

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

    
828
      case "remove":
829
        $str = preg_replace(
830
            (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
831
            "",
832
            $str);
833
      break;
834

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

    
843
    return $str;
844
  }
845

    
846

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

    
864

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

    
884

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

    
910
    if (!file_exists($filename)) {
911
      $this->halt("filename: file $filename does not exist.");
912
    }
913
    return $filename;
914
  }
915

    
916

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

    
933

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

    
959
    if (!isset($this->file[$varname])) {
960
      // $varname does not reference a file so return
961
      if ($this->debug & 4) {
962
        echo "<p><b>loadfile:</b> varname $varname does not reference a file</p>\n";
963
      }
964
      return true;
965
    }
966

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

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

    
984
    if ($this->filename_comments) {
985
      $str = "<!-- START FILE $filename -->\n$str<!-- END FILE $filename -->\n";
986
    }
987
    if ($this->debug & 4) {
988
      printf("<b>loadfile:</b> loaded $filename into $varname<br>\n");
989
    }
990
    $this->set_var($varname, $str);
991

    
992
    return true;
993
  }
994

    
995

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

    
1013
    if ($this->halt_on_error != "no") {
1014
      $this->haltmsg($msg);
1015
    }
1016

    
1017
    if ($this->halt_on_error == "yes") {
1018
      die("<b>Halted.</b>");
1019
    }
1020

    
1021
    return false;
1022
  }
1023

    
1024

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

    
1041
}
(3-3/3)