[ Index ] |
|
Code source de PHP PEAR 1.4.5 |
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 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 14:08:00 2007 | par Balluche grâce à PHPXref 0.7 |