[ Index ]
 

Code source de PHP PEAR 1.4.5

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

title

Body

[fermer]

/MDB/ -> Parser.php (source)

   1  <?php
   2  // +----------------------------------------------------------------------+
   3  // | PHP Version 4                                                        |
   4  // +----------------------------------------------------------------------+
   5  // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
   6  // | Stig. S. Bakken, Lukas Smith                                         |
   7  // | All rights reserved.                                                 |
   8  // +----------------------------------------------------------------------+
   9  // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  10  // | API as well as database abstraction for PHP applications.            |
  11  // | This LICENSE is in the BSD license style.                            |
  12  // |                                                                      |
  13  // | Redistribution and use in source and binary forms, with or without   |
  14  // | modification, are permitted provided that the following conditions   |
  15  // | are met:                                                             |
  16  // |                                                                      |
  17  // | Redistributions of source code must retain the above copyright       |
  18  // | notice, this list of conditions and the following disclaimer.        |
  19  // |                                                                      |
  20  // | Redistributions in binary form must reproduce the above copyright    |
  21  // | notice, this list of conditions and the following disclaimer in the  |
  22  // | documentation and/or other materials provided with the distribution. |
  23  // |                                                                      |
  24  // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25  // | Lukas Smith nor the names of his contributors may be used to endorse |
  26  // | or promote products derived from this software without specific prior|
  27  // | written permission.                                                  |
  28  // |                                                                      |
  29  // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30  // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31  // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32  // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33  // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34  // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35  // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36  // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37  // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38  // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39  // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40  // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41  // +----------------------------------------------------------------------+
  42  // | Author: Christian Dickmann <dickmann@php.net>                        |
  43  // +----------------------------------------------------------------------+
  44  //
  45  // $Id: Parser.php,v 1.30.4.1 2004/01/08 13:43:02 lsmith Exp $
  46  //
  47  
  48  require_once ('XML/Parser.php');
  49  
  50  /**
  51   * Parses an XML schema file
  52   *
  53   * @package MDB
  54   * @category Database
  55   * @access private
  56   * @author  Christian Dickmann <dickmann@php.net>
  57   */
  58  class MDB_Parser extends XML_Parser
  59  {
  60      var $database_definition = array();
  61      var $elements = array();
  62      var $element = '';
  63      var $count = 0;
  64      var $table = array();
  65      var $table_name = '';
  66      var $field = array();
  67      var $field_name = '';
  68      var $init = array();
  69      var $init_name = '';
  70      var $init_value = '';
  71      var $index = array();
  72      var $index_name = '';
  73      var $var_mode = FALSE;
  74      var $variables = array();
  75      var $seq = array();
  76      var $seq_name = '';
  77      var $error = NULL;
  78  
  79      var $invalid_names = array(
  80          'user' => array(),
  81          'is' => array(),
  82          'file' => array(
  83              'oci' => array(),
  84              'oracle' => array()
  85          ),
  86          'notify' => array(
  87              'pgsql' => array()
  88          ),
  89          'restrict' => array(
  90              'mysql' => array()
  91          ),
  92          'password' => array(
  93              'ibase' => array()
  94          )
  95      );
  96      var $fail_on_invalid_names = 1;
  97  
  98      function MDB_Parser($variables, $fail_on_invalid_names = 1) 
  99      {
 100          $this->XML_Parser();
 101          $this->variables = $variables;
 102          $this->fail_on_invalid_names = $fail_on_invalid_names;
 103      }
 104  
 105      function startHandler($xp, $element, $attribs) 
 106      {   
 107          if (strtolower($element) == 'variable') {
 108              $this->var_mode = TRUE;
 109              return;
 110          };
 111          
 112          $this->elements[$this->count++] = strtolower($element);
 113          $this->element = implode('-', $this->elements);
 114          
 115          switch($this->element) {
 116          case 'database-table-initialization-insert':
 117              $this->init = array('type' => 'insert');
 118              break;
 119          case 'database-table-initialization-insert-field':
 120              $this->init_name = '';
 121              $this->init_value = '';
 122              break;
 123          case 'database-table':
 124              $this->table_name = '';
 125              $this->table = array();
 126              break;
 127          case 'database-table-declaration-field':
 128              $this->field_name = '';
 129              $this->field = array();
 130              break;
 131          case 'database-table-declaration-field-default':
 132              $this->field['default'] = '';
 133              break;
 134          case 'database-table-declaration-index':
 135              $this->index_name = '';
 136              $this->index = array();
 137              break;
 138          case 'database-sequence':
 139              $this->seq_name = '';
 140              $this->seq = array();
 141              break;
 142          case 'database-table-declaration-index-field':
 143              $this->field_name = '';
 144              $this->field = array();
 145              break;
 146          };
 147      }
 148  
 149      function endHandler($xp, $element)
 150      {
 151          if (strtolower($element) == 'variable') {
 152              $this->var_mode = FALSE;
 153              return;
 154          };
 155          
 156          switch($this->element) {
 157          /* Initialization */
 158          case 'database-table-initialization-insert-field':
 159              if (!$this->init_name) {
 160                  $this->raiseError('field-name has to be specified', $xp);
 161              };
 162              if (isset($this->init['FIELDS'][$this->init_name])) {
 163                  $this->raiseError('field "'.$this->init_name.'" already filled', $xp);
 164              };
 165              if (!isset($this->table['FIELDS'][$this->init_name])) {
 166                  $this->raiseError('unkown field "'.$this->init_name.'"', $xp);
 167              };
 168              if ($this->init_value !== '' 
 169                  && !$this->validateFieldValue($this->init_name, $this->init_value, $xp)) 
 170              {
 171                  $this->raiseError('field "'.$this->init_name.'" has wrong value', $xp);
 172              };
 173              $this->init['FIELDS'][$this->init_name] = $this->init_value;
 174              break;
 175          case 'database-table-initialization-insert':
 176              $this->table['initialization'][] = $this->init;
 177              break;
 178              
 179          /* Table definition */
 180          case 'database-table':
 181              if (!isset($this->table['was'])) {
 182                  $this->table['was'] = $this->table_name;
 183              };
 184              if (!$this->table_name) {
 185                  $this->raiseError('tables need names', $xp);
 186              };
 187              if (isset($this->database_definition['TABLES'][$this->table_name])) {
 188                  $this->raiseError('table "'.$this->table_name.'" already exists', $xp);
 189              };
 190              if (!isset($this->table['FIELDS'])) {
 191                  $this->raiseError('tables need one or more fields', $xp);
 192              };
 193              if (isset($this->table['INDEXES'])) {
 194                  foreach($this->table['INDEXES'] as $index_name => $index) {
 195                      foreach($index['FIELDS'] as $field_name => $field) {
 196                          if (!isset($this->table['FIELDS'][$field_name])) {
 197                              $this->raiseError('index field "'.$field_name.'" does not exist', $xp);
 198                          }
 199                          if (!(isset($this->table['FIELDS'][$field_name]['notnull'])
 200                              && $this->table['FIELDS'][$field_name]['notnull'] == 1)) 
 201                          {
 202                              $this->raiseError('index field "'.$field_name.'" has to be "notnull"', $xp);
 203                          }
 204                      }
 205                  }
 206              };
 207              $this->database_definition['TABLES'][$this->table_name] = $this->table;
 208              break;
 209              
 210          /* Field declaration */
 211          case 'database-table-declaration-field':
 212              if (!$this->field_name || !isset($this->field['type'])) {
 213                  $this->raiseError('field "'.$this->field_name.'" was not properly specified', $xp);
 214              };
 215              if (isset($this->table['FIELDS'][$this->field_name])) {
 216                  $this->raiseError('field "'.$this->field_name.'" already exists', $xp);
 217              };
 218              /* Invalidname check */
 219              if ($this->fail_on_invalid_names && isset($this->invalid_names[$this->field_name])) {
 220                  $this->raiseError('fieldname "'.$this->field_name.'" not allowed', $xp);
 221              };
 222              /* Type check */
 223              switch($this->field['type']) {
 224              case 'integer':
 225                  if (isset($this->field['unsigned']) 
 226                      && $this->field['unsigned'] !== '1' && $this->field['unsigned'] !== '0') 
 227                  {
 228                      $this->raiseError('unsigned has to be 1 or 0', $xp);
 229                  };
 230                  break;
 231              case 'text':
 232              case 'clob':
 233              case 'blob':
 234                  if (isset($this->field['length']) && ((int)$this->field['length']) <= 0) {
 235                      $this->raiseError('length has to be an integer greater 0', $xp);
 236                  };
 237                  break;
 238              case 'boolean':
 239              case 'date':
 240              case 'timestamp':
 241              case 'time':
 242              case 'float':
 243              case 'decimal':
 244                  break;
 245              default: 
 246                  $this->raiseError('no valid field type ("'.$this->field['type'].'") specified', $xp);
 247              };
 248              if (!isset($this->field['was'])) {
 249                  $this->field['was'] = $this->field_name;
 250              };
 251              if (isset($this->field['notnull']) && !$this->is_boolean($this->field['notnull'])) {
 252                  $this->raiseError('field  "notnull" has to be 1 or 0', $xp);
 253              };
 254              if (isset($this->field['notnull']) && !isset($this->field['default'])) {
 255                  $this->raiseError('if field is "notnull", it needs a default value', $xp);
 256              };
 257              if (isset($this->field['unsigned']) && !$this->is_boolean($this->field['unsigned'])) {
 258                  $this->raiseError('field  "notnull" has to be 1 or 0', $xp);
 259              };
 260              $this->table['FIELDS'][$this->field_name] = $this->field;
 261              if (isset($this->field['default'])) {
 262                  if ($this->field['type'] == 'clob' || $this->field['type'] == 'blob') {
 263                      $this->raiseError('"'.$this->field['type'].'"-fields are not allowed to have a default value', $xp);
 264                  };
 265                  if ($this->field['default'] !== '' 
 266                      && !$this->validateFieldValue($this->field_name, $this->field['default'], $xp))
 267                  {
 268                      $this->raiseError('default value of "'.$this->field_name.'" is of wrong type', $xp);
 269                  };
 270              };
 271              break;
 272              
 273          /* Index declaration */
 274          case 'database-table-declaration-index':
 275              if (!$this->index_name) {
 276                  $this->raiseError('an index needs a name', $xp);
 277              };
 278              if (isset($this->table['INDEXES'][$this->index_name])) {
 279                  $this->raiseError('index "'.$this->index_name.'" already exists', $xp);
 280              };
 281              if (isset($this->index['unique']) && !$this->is_boolean($this->index['unique'])) {
 282                  $this->raiseError('field  "unique" has to be 1 or 0', $xp);
 283              };
 284              if (!isset($this->index['was'])) {
 285                  $this->index['was'] = $this->index_name;
 286              };
 287              $this->table['INDEXES'][$this->index_name] = $this->index;
 288              break;
 289          case 'database-table-declaration-index-field':
 290              if (!$this->field_name) {
 291                  $this->raiseError('the index-field-name is required', $xp);
 292              };
 293              if (isset($this->field['sorting']) 
 294                  && $this->field['sorting'] !== 'ascending' && $this->field['sorting'] !== 'descending') {
 295                  $this->raiseError('sorting type unknown', $xp);
 296              };
 297              $this->index['FIELDS'][$this->field_name] = $this->field;
 298              break;
 299              
 300          /* Sequence declaration */
 301          case 'database-sequence':
 302              if (!$this->seq_name) {
 303                  $this->raiseError('a sequence has to have a name', $xp);
 304              };
 305              if (isset($this->database_definition['SEQUENCES'][$this->seq_name])) {
 306                  $this->raiseError('sequence "'.$this->seq_name.'" already exists', $xp);
 307              };
 308              if (!isset($this->seq['was'])) {
 309                  $this->seq['was'] = $this->seq_name;
 310              };
 311              if (isset($this->seq['on'])) {
 312                  if ((!isset($this->seq['on']['table']) || !$this->seq['on']['table'])
 313                      || (!isset($this->seq['on']['field']) || !$this->seq['on']['field'])) 
 314                  {
 315                      $this->raiseError('sequence "'.$this->seq_name.'" was not properly defined', $xp);
 316                  };
 317              };
 318              $this->database_definition['SEQUENCES'][$this->seq_name] = $this->seq;
 319              break;
 320              
 321          /* End of File */
 322          case 'database':
 323              if (isset($this->database_definition['create']) 
 324                  && !$this->is_boolean($this->database_definition['create']))
 325              {
 326                  $this->raiseError('field "create" has to be 1 or 0', $xp);
 327              };
 328              if (isset($this->database_definition['overwrite']) 
 329                  && !$this->is_boolean($this->database_definition['overwrite']))
 330              {
 331                  $this->raiseError('field "overwrite" has to be 1 or 0', $xp);
 332              };
 333              if (!isset($this->database_definition['name']) || !$this->database_definition['name']) {
 334                  $this->raiseError('database needs a name', $xp);
 335              };
 336              if (isset($this->database_definition['SEQUENCES'])) {
 337                  foreach($this->database_definition['SEQUENCES'] as $seq_name => $seq) {
 338                      if (isset($seq['on']) 
 339                          && !isset($this->database_definition['TABLES'][$seq['on']['table']]['FIELDS'][$seq['on']['field']]))
 340                      {
 341                          $this->raiseError('sequence "'.$seq_name.'" was assigned on unexisting field/table', $xp);
 342                      };
 343                  };
 344              };
 345              if (MDB::isError($this->error)) {
 346                  $this->database_definition = $this->error;
 347              };
 348              break;
 349          }
 350          
 351          unset($this->elements[--$this->count]);
 352          $this->element = implode('-', $this->elements);
 353      }
 354  
 355      function validateFieldValue($field_name, &$field_value, &$xp)
 356      {
 357          if (!isset($this->table['FIELDS'][$field_name])) {
 358              return;
 359          };
 360          $field_def = $this->table['FIELDS'][$field_name];
 361          switch($field_def['type']) {
 362          case 'text':
 363          case 'clob':
 364              if (isset($field_def['length']) && strlen($field_value) > $field_def['length']) {
 365                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 366              };
 367              break;
 368          case 'blob':
 369              /*
 370              if (!preg_match('/^([0-9a-f]{2})*$/i', $field_value)) {
 371                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 372              }
 373              */
 374              $field_value = pack('H*', $field_value);
 375              if (isset($field_def['length']) && strlen($field_value) > $field_def['length']) {
 376                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 377              };
 378              break;
 379          case 'integer':
 380              if ($field_value != ((int)$field_value)) {
 381                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 382              };
 383              $field_value = (int) $field_value;
 384              if (isset($field_def['unsigned']) && $field_def['unsigned'] && $field_value < 0) {
 385                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 386              };
 387              break;
 388          case 'boolean':
 389              if (!$this->is_boolean($field_value)) {
 390                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 391              }
 392              break;
 393          case 'date':
 394              if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/', $field_value)) {
 395                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 396              }
 397              break;
 398          case 'timestamp':
 399              if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/', $field_value)) {
 400                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 401              }
 402              break;
 403          case 'time':
 404              if (!preg_match("/([0-9]{2}):([0-9]{2}):([0-9]{2})/", $field_value)) {
 405                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 406              }
 407              break;
 408          case 'float':
 409          case 'double':
 410              if ($field_value != (double) $field_value) {
 411                  return($this->raiseError('"'.$field_value.'" is not of type "'.$field_def['type'].'"', $xp));
 412              };
 413              $field_value = (double) $field_value;
 414              break;
 415          }
 416          return(TRUE);
 417      }
 418  
 419      function raiseError($msg, $xp = NULL)
 420      {
 421          if ($this->error === NULL) {
 422              if(is_resource($msg)) {
 423                  $error = "Parser error: ";
 424                  $xp = $msg;
 425              } else {
 426                  $error = "Parser error: \"".$msg."\"\n";
 427              }
 428              if($xp != NULL) {
 429                  $byte = @xml_get_current_byte_index($xp);
 430                  $line = @xml_get_current_line_number($xp);
 431                  $column = @xml_get_current_column_number($xp);
 432                  $error .= "Byte: $byte; Line: $line; Col: $column\n";
 433              }
 434              $this->error = PEAR::raiseError(NULL, MDB_ERROR_MANAGER_PARSE, NULL, NULL,
 435                  $error, 'MDB_Error', TRUE);
 436          };
 437          return(FALSE);
 438      }
 439  
 440      function is_boolean(&$value)
 441      {
 442          if (is_int($value) && ($value == 0 || $value == 1)) {
 443              return(TRUE);
 444          };
 445          if ($value === '1' || $value === '0') {
 446              $value = (int) $value;
 447              return(TRUE);
 448          };
 449          switch($value)
 450          {
 451          case 'N':
 452          case 'n':
 453          case 'no':
 454          case 'FALSE':
 455              $value = 0;
 456              break;
 457          case 'Y':
 458          case 'y':
 459          case 'yes':
 460          case 'TRUE':
 461              $value = 1;
 462              break;
 463          default:
 464              return(FALSE);
 465          };
 466          return(TRUE);
 467      }
 468  
 469      function cdataHandler($xp, $data)
 470      {
 471          if ($this->var_mode == TRUE) {
 472              if (!isset($this->variables[$data])) {
 473                  $this->raiseError('variable "'.$data.'" not found', $xp);
 474                  return;
 475              };
 476              $data = $this->variables[$data];
 477          };
 478          
 479          switch($this->element) {
 480          /* Initialization */
 481          case 'database-table-initialization-insert-field-name':
 482              @$this->init_name .= $data;
 483              break;
 484          case 'database-table-initialization-insert-field-value':
 485              @$this->init_value .= $data;
 486              break;
 487              
 488          /* Database */
 489          case 'database-name': 
 490              @$this->database_definition['name'] .= $data;
 491              break;
 492          case 'database-create':
 493              @$this->database_definition['create'] .= $data;
 494              break;
 495          case 'database-overwrite':
 496              @$this->database_definition['overwrite'] .= $data;
 497              break;
 498          case 'database-table-name':
 499              @$this->table_name .= $data;
 500              break;
 501          case 'database-table-was':
 502              @$this->table['was'] .= $data;
 503              break;
 504              
 505          /* Field declaration */
 506          case 'database-table-declaration-field-name':
 507              @$this->field_name .= $data;
 508              break;
 509          case 'database-table-declaration-field-type':
 510              @$this->field['type'] .= $data;
 511              break;
 512          case 'database-table-declaration-field-was':
 513              @$this->field['was'] .= $data;
 514              break;
 515          case 'database-table-declaration-field-notnull':
 516              @$this->field['notnull'] .= $data;
 517              break;
 518          case 'database-table-declaration-field-unsigned':
 519              @$this->field['unsigned'] .= $data;
 520              break;
 521          case 'database-table-declaration-field-default':
 522              @$this->field['default'] .= $data;
 523              break;
 524          case 'database-table-declaration-field-length':
 525              @$this->field['length'] .= $data;
 526              break;
 527              
 528          /* Index declaration */
 529          case 'database-table-declaration-index-name':
 530              @$this->index_name .= $data;
 531              break;
 532          case 'database-table-declaration-index-unique':
 533              @$this->index['unique'] .= $data;
 534              break;
 535          case 'database-table-declaration-index-was':
 536              @$this->index['was'] .= $data;
 537              break;
 538          case 'database-table-declaration-index-field-name':
 539              @$this->field_name .= $data;
 540              break;
 541          case 'database-table-declaration-index-field-sorting':
 542              @$this->field['sorting'] .= $data;
 543              break;
 544              
 545          /* Sequence declaration */
 546          case 'database-sequence-name':
 547              @$this->seq_name .= $data;
 548              break;
 549          case 'database-sequence-was':
 550              @$this->seq['was'] .= $data;
 551              break;
 552          case 'database-sequence-start':
 553              @$this->seq['start'] .= $data;
 554              break;
 555          case 'database-sequence-on-table':
 556              @$this->seq['on']['table'] .= $data;
 557              break;
 558          case 'database-sequence-on-field':
 559              @$this->seq['on']['field'] .= $data;
 560              break;
 561          };
 562      }
 563  };
 564  
 565  ?>


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7