[ Index ]
 

Code source de eGroupWare 1.2.106-2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/phpgwapi/inc/savant2/Savant2/ -> Savant2_Compiler_basic.php (source)

   1  <?php
   2  
   3  /**
   4  * 
   5  * Basic compiler for Savant2.
   6  * 
   7  * This is a simple compiler provided as an example.  It probably won't
   8  * work with streams, but it does limit the template syntax in a
   9  * relatively strict way.  It's not perfect, but it's OK for many
  10  * purposes.  Basically, the compiler converts specialized instances of
  11  * curly braces into PHP commands or Savant2 method calls.  It will
  12  * probably mess up embedded JavaScript unless you change the prefix
  13  * and suffix to something else (e.g., '<!-- ' and ' -->', but then it 
  14  * will mess up your HTML comments ;-).
  15  * 
  16  * When in "restrict" mode, ise of PHP commands not in the whitelists
  17  * will cause the compiler to * fail.  Use of various constructs and
  18  * superglobals, likewise.
  19  * 
  20  * Use {$var} or {$this->var} to print a variable.
  21  * 
  22  * Use {: function-list} to print the results of function calls.
  23  * 
  24  * Use {['pluginName', 'arg1', $arg2, $this->arg3]} to call plugins.
  25  * 
  26  * Use these for looping:
  27  *     {foreach ():} ... {endforeach}
  28  *     {for ():} ... {endfor}
  29  *     {while ():} ... {endwhile}
  30  * 
  31  * Use these for conditionals (normal PHP can go in the parens):
  32  *     {if (...):}
  33  *     {elseif (...):}
  34  *     {else:}
  35  *     {endif}
  36  *   {switch (...):}
  37  *   {case ...:}
  38  *   {default:}
  39  *   {endswitch}
  40  * 
  41  * {break} and {continue} are supported as well.
  42  * 
  43  * Use this to include a template:
  44  *     {tpl 'template.tpl.php'}
  45  *     {tpl $tplname}
  46  *     {tpl $this->tplname}
  47  * 
  48  * $Id: Savant2_Compiler_basic.php 18360 2005-05-26 19:38:09Z mipmip $
  49  * 
  50  * @author Paul M. Jones <pmjones@ciaweb.net>
  51  * 
  52  * @package Savant2
  53  * 
  54  * @license http://www.gnu.org/copyleft/lesser.html LGPL
  55  * 
  56  * This program is free software; you can redistribute it and/or modify
  57  * it under the terms of the GNU Lesser General Public License as
  58  * published by the Free Software Foundation; either version 2.1 of the
  59  * License, or (at your option) any later version.
  60  *
  61  * This program is distributed in the hope that it will be useful, but
  62  * WITHOUT ANY WARRANTY; without even the implied warranty of
  63  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  64  * Lesser General Public License for more details.
  65  *
  66  */
  67  
  68  require_once 'Savant2/Compiler.php';
  69  require_once 'Savant2/Error.php';
  70  require_once 'Savant2/PHPCodeAnalyzer.php';
  71  
  72  class Savant2_Compiler_basic extends Savant2_Compiler {
  73      
  74          
  75      /**
  76      * 
  77      * The template directive prefix.
  78      * 
  79      * @access public
  80      * 
  81      * @var array
  82      * 
  83      */
  84      
  85      var $prefix = '{';
  86      
  87          
  88      /**
  89      * 
  90      * The template directive suffix.
  91      * 
  92      * @access public
  93      * 
  94      * @var array
  95      * 
  96      */
  97      
  98      var $suffix = '}';
  99      
 100      
 101      /**
 102      * 
 103      * The conversion regular expressions.
 104      * 
 105      * @access public
 106      * 
 107      * @var array
 108      * 
 109      */
 110      
 111      var $convert = array(
 112      
 113          // branching
 114          '(if\s*(.+):)'        => '$1',
 115          '(elseif\s*(.+):)'    => '$1',
 116          '(else\s*(.+):)'      => '$1',
 117          '(endif)'             => '$1',
 118          '(switch\s*(.+):)'    => '$1',
 119          '(case\s*(.+):)'      => '$1',
 120          '(default:)'          => '$1',
 121          '(endswitch)'         => '$1',
 122          '(break)'             => '$1',
 123          
 124          // looping
 125          '(foreach\s*(.+):)'   => '$1',
 126          '(endforeach)'        => '$1',
 127          '(for\s*(.+):)'       => '$1',
 128          '(endfor)'            => '$1',
 129          '(while\s*(.+):)'     => '$1',
 130          '(endwhile)'          => '$1',
 131          '(continue)'          => '$1',
 132          
 133          // simple variable printing
 134          '(\$(.+))'            => 'print $1',
 135          
 136          // extended printing
 137          '(\:(.+))'            => 'print ($2)',
 138          
 139          // comments
 140          '\*(.*)?\*'           => '/**$1*/',
 141          
 142          // template includes
 143          'tpl (.*)'            => 'include $this->findTemplate($1)',
 144          
 145          // plugins
 146          '\[\s*(.+)?\s*\]'     => '$this->plugin($1)',
 147      );
 148      
 149      
 150      /**
 151      * 
 152      * The list of allowed functions when in restricted mode.
 153      * 
 154      * @access public
 155      * 
 156      * @var array
 157      * 
 158      */
 159      
 160      var $allowedFunctions = array();
 161      
 162      
 163      /**
 164      * 
 165      * The list of allowed static methods when in restricted mode.
 166      * 
 167      * @access public
 168      * 
 169      * @var array
 170      * 
 171      */
 172      
 173      var $allowedStatic = array();
 174      
 175      
 176      /**
 177      * 
 178      * The directory where compiled templates are saved.
 179      * 
 180      * @access public
 181      * 
 182      * @var string
 183      * 
 184      */
 185      
 186      var $compileDir = null;
 187      
 188      
 189      /**
 190      * 
 191      * Whether or not to force every template to be compiled every time.
 192      * 
 193      * @access public
 194      * 
 195      * @var bool
 196      * 
 197      */
 198      
 199      var $forceCompile = false;
 200      
 201      
 202      
 203      /**
 204      * 
 205      * Whether or not to strict-check the compiled template.
 206      * 
 207      * Strict-checks are off by default until all problems with
 208      * PhpCodeAnalyzer have been resolved.
 209      * 
 210      * @access public
 211      * 
 212      * @var bool
 213      * 
 214      */
 215      
 216      var $strict = false;
 217      
 218      
 219      /**
 220      * 
 221      * Constructor.
 222      * 
 223      */
 224      
 225  	function Savant2_Compiler_basic($conf = array())
 226      {
 227          parent::Savant2_Compiler($conf);
 228          $this->ca =& new PHPCodeAnalyzer();
 229          $this->allowedFunctions = $this->allowedFunctions();
 230          $this->allowedStatic = $this->allowedStatic();
 231      }
 232      
 233      
 234      /**
 235      * 
 236      * Has the source template changed since it was last compiled?
 237      * 
 238      * @access public
 239      * 
 240      * @var string $tpl The source template file.
 241      * 
 242      */
 243      
 244  	function changed($tpl)
 245      {
 246          // the path for the compiled file
 247          $file = $this->getPath($tpl);
 248          
 249          // if the copmiled file does not exist, or if the mod-time of
 250          // the source is later than that of the existing compiled file,
 251          // then the source template file has changed.
 252          if (! file_exists($file) ||
 253              filemtime($tpl) > filemtime($file)) {
 254              return true;
 255          } else {
 256              return false;
 257          }
 258      }
 259      
 260      
 261      /**
 262      * 
 263      * Saves the PHP compiled from template source.
 264      * 
 265      * @access public
 266      * 
 267      * @var string $tpl The source template file.
 268      * 
 269      */
 270      
 271  	function saveCompiled($tpl, $php)
 272      {
 273          $fp = fopen($this->getPath($tpl), 'w');
 274          if (! $fp) {
 275              return false;
 276          } else {
 277              $result = fwrite($fp, $php);
 278              fclose($fp);
 279              return $result;
 280          }
 281      }
 282      
 283      
 284      /**
 285      * 
 286      * Gets the path to the compiled PHP for a template source.
 287      * 
 288      * @access public
 289      * 
 290      * @var string $tpl The source template file.
 291      * 
 292      */
 293      
 294  	function getPath($tpl)
 295      {
 296          $dir = $this->compileDir;
 297          if (substr($dir, -1) != DIRECTORY_SEPARATOR) {
 298              $dir .= DIRECTORY_SEPARATOR;
 299          }
 300          return $dir . 'Savant2_' . md5($tpl);
 301      }
 302      
 303      
 304      /**
 305      * 
 306      * Compiles a template source into PHP code for Savant.
 307      * 
 308      * @access public
 309      * 
 310      * @var string $tpl The source template file.
 311      * 
 312      */
 313      
 314  	function compile($tpl)
 315      {
 316          // create a end-tag so that text editors don't
 317          // stop colorizing text
 318          $end = '?' . '>';
 319          
 320          // recompile only if we are forcing compiled, or
 321          // if the template source has changed.
 322          if ($this->forceCompile || $this->changed($tpl)) {
 323              
 324              // get the template source text
 325              $php = file_get_contents($tpl);
 326              
 327              /**
 328              * @todo Do we really care about PHP tags?  The code analyzer
 329              * will disallow any offending PHP regardless.
 330              */
 331              
 332              // disallow PHP long tags
 333              $php = str_replace('<?php', '&lt;?php', $php);
 334              
 335              // disallow PHP short tags (if turned on)
 336              if (ini_get('short_open_tag')) {
 337                  $php = str_replace('<?', '&lt;?', $php);
 338                  $php = str_replace('<?=', '&lt;?=', $php);
 339              }
 340              
 341              // disallow closing tags
 342              $php = str_replace($end, '?&gt;', $php);
 343              
 344              // convert each template command
 345              foreach ($this->convert as $find => $replace) {
 346              
 347                  // allow whitespace around the command
 348                  $find = preg_quote($this->prefix) . '\s*' . $find .
 349                      '\s*' . preg_quote($this->suffix);
 350                      
 351                  // actually do the find-and-replace
 352                  $php = preg_replace(
 353                      "/$find/U",
 354                      "<?php $replace $end",
 355                      $php
 356                  );
 357                  
 358              }
 359              
 360              // +++ DEBUG
 361              // $this->saveCompiled($tpl, $php);
 362              // --- DEBUG
 363              
 364              // are we doing strict checking?
 365              if ($this->strict) {
 366                  // analyze the code for restriction violations.
 367                  $report = $this->analyze($php);
 368                  if (count($report) > 0) {
 369                      // there were violations, report them as a generic
 370                      // Savant error and return.  Savant will wrap this
 371                      // generic rror with another error that will report
 372                      // properly to the customized error handler (if any).
 373                      return new Savant2_Error(
 374                          array(
 375                              'code' => SAVANT2_ERROR_COMPILE_FAIL,
 376                              'text' => $GLOBALS['_SAVANT2']['error'][SAVANT2_ERROR_COMPILE_FAIL],
 377                              'info' => $report
 378                          )
 379                      );
 380                  }
 381              }
 382              
 383              // otherwise, save the compiled template
 384              $this->saveCompiled($tpl, $php);
 385          }
 386          
 387          // return the path to the compiled PHP script
 388          return $this->getPath($tpl);
 389      }
 390      
 391      
 392      /**
 393      * 
 394      * Analyze a compiled template for restriction violations.
 395      * 
 396      * @access public
 397      * 
 398      * @var string $php The compiled PHP code from a template source.
 399      * 
 400      * @return array An array of restriction violations; if empty, then
 401      * there were no violations discovered by analysis.
 402      * 
 403      */
 404      
 405  	function analyze(&$php)
 406      {
 407          // analyze the compiled code
 408          $ca =& $this->ca;
 409          $ca->source =& $php;
 410          $ca->analyze();
 411          
 412          // array of captured restriction violations
 413          $report = array();
 414          
 415          // -------------------------------------------------------------
 416          //
 417          // go through the list of called functions and make sure each
 418          // one is allowed via the whitelist.  if not, record each non-
 419          // allowed function.  this also restricts variable-functions
 420          // such as $var().
 421          //
 422          
 423          foreach ($ca->calledFunctions as $func => $lines) {
 424              if (! in_array($func, $this->allowedFunctions)) {
 425                  $report[$func] = $lines;
 426              }
 427          }
 428          
 429          // -------------------------------------------------------------
 430          //
 431          // disallow use of various constructs (include is allowed, we
 432          // need it for {tpl}).
 433          //
 434          
 435          $tmp = array(
 436              'eval',
 437              'global',
 438              'include_once',
 439              'require',
 440              'require_once',
 441              'parent',
 442              'self'
 443          );
 444          
 445          foreach ($tmp as $val) {
 446              if (isset($ca->calledConstructs[$val])) {
 447                  $report[$val] = $ca->calledConstructs[$val];
 448              }
 449          }
 450          
 451          // -------------------------------------------------------------
 452          //
 453          // disallow instantiation of new classes
 454          //
 455          
 456          foreach ($ca->classesInstantiated as $key => $val) {
 457              $report['new ' . $key] = $val;
 458          }
 459          
 460          // -------------------------------------------------------------
 461          //
 462          // disallow access to the various superglobals
 463          // so that templates cannot manipulate them.
 464          //
 465          
 466          $tmp = array(
 467              '$_COOKIE',
 468              '$_ENV',
 469              '$_FILES',
 470              '$_GET',
 471              '$_POST',
 472              '$_REQUEST',
 473              '$_SERVER',
 474              '$_SESSION',
 475              '$GLOBALS',
 476              '$HTTP_COOKIE_VARS',
 477              '$HTTP_ENV_VARS',
 478              '$HTTP_GET_VARS',
 479              '$HTTP_POST_FILES',
 480              '$HTTP_POST_VARS',
 481              '$HTTP_SERVER_VARS',
 482              '$HTTP_SESSION_VARS'
 483          );
 484          
 485          foreach ($ca->usedVariables as $var => $lines) {
 486              if (in_array(strtoupper($var), $tmp)) {
 487                  $report[$var] = $lines;
 488              }
 489          }
 490          
 491          // -------------------------------------------------------------
 492          //
 493          // allow only certain $this methods
 494          //
 495          
 496          $tmp = array('plugin', 'splugin', 'findTemplate');
 497          if (isset($ca->calledMethods['$this'])) {
 498              foreach ($ca->calledMethods['$this'] as $method => $lines) {
 499                  if (! in_array($method, $tmp)) {
 500                      $report['$this->' . $method] = $lines;
 501                  }
 502              }
 503          }
 504          
 505          // -------------------------------------------------------------
 506          //
 507          // disallow private and variable-variable $this properties
 508          // 
 509          
 510          if (isset($ca->usedMemberVariables['$this'])) {
 511              foreach ($ca->usedMemberVariables['$this'] as $prop => $lines) {
 512                  $char = substr($prop, 0, 1);
 513                  if ($char == '_' || $char == '$') {
 514                      $report['$this->' . $prop] = $lines;
 515                  }
 516              }
 517          }
 518          
 519          // -------------------------------------------------------------
 520          //
 521          // allow only certain static method calls
 522          //
 523          
 524          foreach ($ca->calledStaticMethods as $class => $methods) {
 525              foreach ($methods as $method => $lines) {
 526                  if (! array_key_exists($class, $this->allowedStatic)) {
 527                  
 528                      // the class itself is not allowed
 529                      $report["$class::$method"] = $lines;
 530                      
 531                  } elseif (! in_array('*', $this->allowedStatic[$class]) &&
 532                      ! in_array($method, $this->allowedStatic[$class])){
 533                      
 534                      // the specific method is not allowed,
 535                      // and there is no wildcard for the class methods.
 536                      $report["$class::$method"] = $lines;
 537                      
 538                  }
 539              }
 540          }
 541          
 542          // -------------------------------------------------------------
 543          //
 544          // only allow includes via $this->findTemplate(*)
 545          //
 546          
 547          foreach ($ca->filesIncluded as $text => $lines) {
 548              
 549              // in each include statment, look for $this->findTemplate.
 550              preg_match(
 551                  '/(.*)?\$this->findTemplate\((.*)?\)(.*)/i',
 552                  $text,
 553                  $matches
 554              );
 555              
 556              if (! empty($matches[1]) || ! empty($matches[3]) ||
 557                  empty($matches[2])) {
 558                  
 559                  // there is something before or after the findTemplate call,
 560                  // or it's a direct include (which is not allowed)
 561                  $report["include $text"] = $lines;
 562                  
 563              }
 564          }
 565          
 566          // -------------------------------------------------------------
 567          //
 568          // do not allow the use of "$this" by itself;
 569          // it must be always be followed by "->" or another
 570          // valid variable-name character (a-z, 0-9, or _).
 571          //
 572          
 573          $regex = '/(.*)?\$this(?!(\-\>)|([a-z0-9_]))(.*)?/i';
 574          preg_match_all($regex, $php, $matches, PREG_SET_ORDER);
 575          foreach ($matches as $val) {
 576              $report['\'$this\' without \'->\''][] = $val[0];
 577          }
 578          
 579          /** @todo disallow standalone variable-variables, $$var */
 580          
 581          /** @todo disallow vars from static classes? class::$var */
 582          
 583          
 584          // -------------------------------------------------------------
 585          //
 586          // done!
 587          //
 588          
 589          // +++ DEBUG
 590          //echo "<pre>";
 591          //print_r($ca);
 592          //echo "</pre>";
 593          // --- DEBUG
 594          
 595          return $report;
 596      }
 597      
 598      
 599      /**
 600      * 
 601      * A list of allowed static method calls for templates.
 602      * 
 603      * The format is ...
 604      * 
 605      * array(
 606      *     'Class1' => array('method1', 'method2'),
 607      *     'Class2' => array('methodA', 'methodB'),
 608      *     'Class3' => '*'
 609      * );
 610      * 
 611      * If you want to allow all methods from the static class to be allowed,
 612      * use a '*' in the method name list.
 613      * 
 614      */
 615  
 616  	function allowedStatic()
 617      {
 618          return array();
 619      }
 620      
 621      
 622      /**
 623      * 
 624      * A list of allowed functions for templates.
 625      * 
 626      */
 627      
 628  	function allowedFunctions()
 629      {
 630          return array(
 631              
 632              // arrays
 633              'array_count_values',
 634              'array_key_exists',
 635              'array_keys',
 636              'array_sum',
 637              'array_values',
 638              'compact',
 639              'count',
 640              'current',
 641              'each',
 642              'end',
 643              'extract',
 644              'in_array',
 645              'key',
 646              'list',
 647              'next',
 648              'pos',
 649              'prev',
 650              'reset',
 651              'sizeof',
 652              
 653              // calendar
 654              'cal_days_in_month',
 655              'cal_from_jd',
 656              'cal_to_jd',
 657              'easter_date',
 658              'easter_days',
 659              'FrenchToJD',
 660              'GregorianToJD',
 661              'JDDayOfWeek',
 662              'JDMonthName',
 663              'JDToFrench',
 664              'JDToGregorian',
 665              'jdtojewish',
 666              'JDToJulian',
 667              'jdtounix',
 668              'JewishToJD',
 669              'JulianToJD',
 670              'unixtojd',
 671              
 672              // date
 673              'checkdate',
 674              'date_sunrise',
 675              'date_sunset',
 676              'date',
 677              'getdate',
 678              'gettimeofday',
 679              'gmdate',
 680              'gmmktime',
 681              'gmstrftime',
 682              'idate',
 683              'localtime',
 684              'microtime',
 685              'mktime',
 686              'strftime',
 687              'strptime',
 688              'strtotime',
 689              'time',
 690          
 691              // gettext
 692              '_',
 693              'gettext',
 694              'ngettext',
 695              
 696              // math
 697              'abs',
 698              'acos',
 699              'acosh',
 700              'asin',
 701              'asinh',
 702              'atan2',
 703              'atan',
 704              'atanh',
 705              'base_convert',
 706              'bindec',
 707              'ceil',
 708              'cos',
 709              'cosh',
 710              'decbin',
 711              'dechex',
 712              'decoct',
 713              'deg2rad',
 714              'exp',
 715              'expm1',
 716              'floor',
 717              'fmod',
 718              'getrandmax',
 719              'hexdec',
 720              'hypot',
 721              'is_finite',
 722              'is_infinite',
 723              'is_nan',
 724              'lcg_value',
 725              'log10',
 726              'log1p',
 727              'log',
 728              'max',
 729              'min',
 730              'mt_getrandmax',
 731              'mt_rand',
 732              'mt_srand',
 733              'octdec',
 734              'pi',
 735              'pow',
 736              'rad2deg',
 737              'rand',
 738              'round',
 739              'sin',
 740              'sinh',
 741              'sqrt',
 742              'srand',
 743              'tan',
 744              'tanh',
 745          
 746              // strings
 747              'chop',
 748              'count_chars',
 749              'echo',
 750              'explode',
 751              'hebrev',
 752              'hebrevc',
 753              'html_entity_decode',
 754              'htmlentities',
 755              'htmlspecialchars',
 756              'implode',
 757              'join',
 758              'localeconv',
 759              'ltrim',
 760              'money_format',
 761              'nl_langinfo',
 762              'nl2br',
 763              'number_format',
 764              'ord',
 765              'print',
 766              'printf',
 767              'quoted_printable_decode',
 768              'rtrim',
 769              'sprintf',
 770              'sscanf',
 771              'str_pad',
 772              'str_repeat',
 773              'str_replace',
 774              'str_rot13',
 775              'str_shuffle',
 776              'str_word_count',
 777              'strcasecmp',
 778              'strchr',
 779              'strcmp',
 780              'strcoll',
 781              'strcspn',
 782              'strip_tags',
 783              'stripcslashes',
 784              'stripos',
 785              'stripslashes',
 786              'stristr',
 787              'strlen',
 788              'strnatcasecmp',
 789              'strnatcmp',
 790              'strncasecmp',
 791              'strncmp',
 792              'strpbrk',
 793              'strpos',
 794              'strrchr',
 795              'strrev',
 796              'strripos',
 797              'strrpos',
 798              'strspn',
 799              'strstr',
 800              'strtok',
 801              'strtolower',
 802              'strtoupper',
 803              'strtr',
 804              'substr_compare',
 805              'substr_count',
 806              'substr_replace',
 807              'substr',
 808              'trim',
 809              'ucfirst',
 810              'ucwords',
 811              'wordwrap',
 812          
 813              // url
 814              'base64_decode',
 815              'base64_encode',
 816              'rawurldecode',
 817              'rawurlencode',
 818              'urldecode',
 819              'urlencode',
 820          
 821              // variables
 822              'empty',
 823              'is_array',
 824              'is_bool',
 825              'is_double',
 826              'is_float',
 827              'is_int',
 828              'is_integer',
 829              'is_long',
 830              'is_null',
 831              'is_numeric',
 832              'is_object',
 833              'is_real',
 834              'is_resource',
 835              'is_scalar',
 836              'is_string',
 837              'isset',
 838              'print_r',
 839              'unset',
 840              'var_dump',
 841          );
 842      }
 843  }
 844  
 845  
 846      
 847  ?>


Généré le : Sun Feb 25 17:20:01 2007 par Balluche grâce à PHPXref 0.7