Exponential 6.0.13 Exponential Enterprise Open Source CMS - PHP Class Reference

ezsimplifiedxmlinputparser.php
Go to the documentation of this file.
1 <?php
11 // if ( !class_exists( 'eZXMLInputParser' ) )
12 class eZSimplifiedXMLInputParser extends eZXMLInputParser
13 {
17 public $isInputValid;
18 public $InputTags = array(
19 'b' => array( 'name' => 'strong' ),
20 'bold' => array( 'name' => 'strong' ),
21 'i' => array( 'name' => 'emphasize' ),
22 'em' => array( 'name' => 'emphasize' ),
23 'h' => array( 'name' => 'header' ),
24 'p' => array( 'name' => 'paragraph' ),
25 'para' => array( 'name' => 'paragraph' ),
26 'br' => array( 'name' => 'br',
27 'noChildren' => true ),
28 'a' => array( 'name' => 'link' ),
29 'h1' => array( 'nameHandler' => 'tagNameHeader' ),
30 'h2' => array( 'nameHandler' => 'tagNameHeader' ),
31 'h3' => array( 'nameHandler' => 'tagNameHeader' ),
32 'h4' => array( 'nameHandler' => 'tagNameHeader' ),
33 'h5' => array( 'nameHandler' => 'tagNameHeader' ),
34 'h6' => array( 'nameHandler' => 'tagNameHeader' ),
35 );
36
37 public $OutputTags = array(
38 'section' => array(),
39
40 'embed' => array( //'parsingHandler' => 'breakInlineFlow',
41 'structHandler' => 'appendLineParagraph',
42 'publishHandler' => 'publishHandlerEmbed',
43 'attributes' => array( 'id' => 'xhtml:id' ),
44 'requiredInputAttributes' => array( 'href' ) ),
45
46 'embed-inline' => array( //'parsingHandler' => 'breakInlineFlow',
47 'structHandler' => 'appendLineParagraph',
48 'publishHandler' => 'publishHandlerEmbed',
49 'attributes' => array( 'id' => 'xhtml:id' ),
50 'requiredInputAttributes' => array( 'href' ) ),
51
52 'object' => array( //'parsingHandler' => 'breakInlineFlow',
53 'structHandler' => 'appendLineParagraph',
54 'publishHandler' => 'publishHandlerObject',
55 'attributes' => array( 'href' => 'image:ezurl_href',
56 'target' => 'image:ezurl_target',
57 'ezurl_href' => 'image:ezurl_href',
58 'ezurl_id' => 'image:ezurl_id',
59 'ezurl_target' => 'image:ezurl_target' ),
60 'requiredInputAttributes' => array( 'id' ) ),
61
62 'table' => array( 'structHandler' => 'appendParagraph' ),
63
64 'tr' => array(),
65
66 'td' => array( 'attributes' => array( 'width' => 'xhtml:width',
67 'colspan' => 'xhtml:colspan',
68 'rowspan' => 'xhtml:rowspan' ) ),
69
70 'th' => array( 'attributes' => array( 'width' => 'xhtml:width',
71 'colspan' => 'xhtml:colspan',
72 'rowspan' => 'xhtml:rowspan' ) ),
73
74 'ol' => array( 'structHandler' => 'structHandlerLists' ),
75
76 'ul' => array( 'structHandler' => 'structHandlerLists' ),
77
78 'li' => array( 'autoCloseOn' => array( 'li' ) ),
79
80 'header' => array( 'autoCloseOn' => array( 'paragraph' ),
81 'structHandler' => 'structHandlerHeader' ),
82
83 'paragraph' => array( 'autoCloseOn' => array( 'paragraph' ),
84 'publishHandler' => 'publishHandlerParagraph' ),
85
86 'line' => array(),
87
88 'br' => array( 'parsingHandler' => 'breakInlineFlow',
89 'structHandler' => 'structHandlerBr',
90 'attributes' => false ),
91
92 'literal' => array( 'parsingHandler' => 'parsingHandlerLiteral',
93 'structHandler' => 'appendParagraph' ),
94
95 'strong' => array( 'structHandler' => 'appendLineParagraph' ),
96
97 'emphasize' => array( 'structHandler' => 'appendLineParagraph' ),
98
99 'link' => array( 'structHandler' => 'appendLineParagraph',
100 'publishHandler' => 'publishHandlerLink',
101 'attributes' => array( 'title' => 'xhtml:title',
102 'id' => 'xhtml:id' ),
103 'requiredInputAttributes' => array( 'href' ) ),
104
105 'anchor' => array( 'structHandler' => 'appendLineParagraph' ),
106
107 'custom' => array( 'structHandler' => 'structHandlerCustom',
108 'publishHandler' => 'publishHandlerCustom',
109 'requiredInputAttributes' => array( 'name' ) ),
110
111 '#text' => array( 'structHandler' => 'structHandlerText' )
112 );
113
114 public function __construct( $contentObjectID, $validateErrorLevel = eZXMLInputParser::ERROR_ALL, $detectErrorLevel = eZXMLInputParser::ERROR_ALL,
115 $parseLineBreaks = false, $removeDefaultAttrs = false )
116 {
117 $this->contentObjectID = $contentObjectID;
118 parent::__construct( $validateErrorLevel, $detectErrorLevel, $parseLineBreaks, $removeDefaultAttrs );
119 }
120
121 /*
122 Tag Name handlers (init handlers)
123 */
124 function tagNameHeader( $tagName, &$attributes )
125 {
126 switch ( $tagName )
127 {
128 case 'h1':
129 {
130 $attributes['level'] = '1';
131 } break;
132 case 'h2':
133 {
134 $attributes['level'] = '2';
135 } break;
136 case 'h3':
137 {
138 $attributes['level'] = '3';
139 } break;
140 case 'h4':
141 {
142 $attributes['level'] = '4';
143 } break;
144 case 'h5':
145 {
146 $attributes['level'] = '5';
147 } break;
148 case 'h6':
149 {
150 $attributes['level'] = '6';
151 } break;
152 default :
153 {
154 return '';
155 } break;
156 }
157 return 'header';
158 }
159
160 /*
161 Parsing Handlers (called at pass 1)
162 */
163 function parsingHandlerLiteral( $element, &$param )
164 {
165 $ret = null;
166 $data = $param[0];
167 $pos =& $param[1];
168
169 $tablePos = strpos( $data, '</literal>', $pos );
170 if ( $tablePos === false )
171 {
172 $tablePos = strpos( $data, '</LITERAL>', $pos );
173 }
174
175 if ( $tablePos === false )
176 {
177 return $ret;
178 }
179
180 $text = substr( $data, $pos, $tablePos - $pos );
181
182 $textNode = $this->Document->createTextNode( $text );
183 $element->appendChild( $textNode );
184
185 $pos = $tablePos + strlen( '</literal>' );
186 $ret = false;
187
188 return $ret;
189 }
190
191 function breakInlineFlow( $element, $param )
192 {
193 // Breaks the flow of inline tags. Used for non-inline tags caught within inline.
194 // Works for tags with no children only.
195 $ret = null;
196 $data =& $param[0];
197 $pos =& $param[1];
198 $tagBeginPos = $param[2];
199 $parent = $element->parentNode;
200
201 $wholeTagString = substr( $data, $tagBeginPos, $pos - $tagBeginPos );
202
203 if ( $parent &&
204 $this->XMLSchema->isInline( $parent ) )
205 {
206 $insertData = '';
207 $currentParent = $parent;
208 // Close all parent tags
209 end( $this->ParentStack );
210 do
211 {
212 $stackData = current( $this->ParentStack );
213 $currentParentName = $stackData[0];
214 $insertData .= "</$currentParentName>";
215 $currentParent->setAttributeNS( 'http://ez.no/namespaces/ezpublish3/temporary/', 'tmp:new-element', 'true' );
216 $currentParent = $currentParent->parentNode;
217 prev( $this->ParentStack );
218 }
219 while( $this->XMLSchema->isInline( $currentParent ) );
220
221 $insertData .= $wholeTagString;
222
223 $currentParent = $parent;
224 end( $this->ParentStack );
225 $appendData = '';
226 do
227 {
228 $stackData = current( $this->ParentStack );
229 $currentParentName = $stackData[0];
230 $currentParentAttrString = '';
231 if ( $stackData[2] )
232 {
233 $currentParentAttrString = ' ' . $stackData[2];
234 }
235 $currentParentAttrString .= " tmp:new-element='true'";
236 $appendData = "<$currentParentName$currentParentAttrString>" . $appendData;
237 $currentParent = $currentParent->parentNode;
238 prev( $this->ParentStack );
239 }
240 while( $this->XMLSchema->isInline( $currentParent ) );
241
242 $insertData .= $appendData;
243
244 $data = $insertData . substr( $data, $pos );
245 $pos = 0;
246 $element = $parent->removeChild( $element );
247 $ret = false;
248 }
249
250 return $ret;
251 }
252
253
254 /*
255 Structure handlers. (called at pass 2)
256 */
257 // Structure handler for inline nodes.
258 function appendLineParagraph( $element, $newParent )
259 {
260 eZDebugSetting::writeDebug( 'kernel-datatype-ezxmltext', $newParent, 'eZSimplifiedXMLInputParser::appendLineParagraph new parent' );
261 $ret = array();
262 $parent = $element->parentNode;
263 if ( !$parent instanceof DOMElement )
264 {
265 return $ret;
266 }
267
268 $parentName = $parent->nodeName;
269 $newParentName = $newParent != null ? $newParent->nodeName : '';
270
271 // Correct structure by adding <line> and <paragraph> tags.
272 if ( $parentName == 'line' || $this->XMLSchema->isInline( $parent ) )
273 {
274 return $ret;
275 }
276
277 if ( $newParentName == 'line' )
278 {
279 $element = $parent->removeChild( $element );
280 $newParent->appendChild( $element );
281 $newLine = $newParent;
282 $ret['result'] = $newParent;
283 }
284 else if (
285 $parentName === 'header'
286 && (
287 $parent->getElementsByTagName( 'line' )->length
288 || $parent->getElementsByTagName( 'br' )->length
289 )
290 )
291 {
292 // by default the header element does not need a line element
293 // unless it contains a <br> or a previously created <line>
294 $newLine = $this->createAndPublishElement( 'line', $ret );
295 $element = $parent->replaceChild( $newLine, $element );
296 $newLine->appendChild( $element );
297 $ret['result'] = $newLine;
298 }
299 elseif ( $parentName == 'paragraph' )
300 {
301 $newLine = $this->createAndPublishElement( 'line', $ret );
302 $element = $parent->replaceChild( $newLine, $element );
303 $newLine->appendChild( $element );
304 $ret['result'] = $newLine;
305 }
306 elseif ( $newParentName == 'paragraph' )
307 {
308 $newLine = $this->createAndPublishElement( 'line', $ret );
309 $element = $parent->removeChild( $element );
310 $newParent->appendChild( $newLine );
311 $newLine->appendChild( $element );
312 $ret['result'] = $newLine;
313 }
314 elseif ( $this->XMLSchema->check( $parent, 'paragraph' ) )
315 {
316 $newLine = $this->createAndPublishElement( 'line', $ret );
317 $newPara = $this->createAndPublishElement( 'paragraph', $ret );
318 $element = $parent->replaceChild( $newPara, $element );
319 $newPara->appendChild( $newLine );
320 $newLine->appendChild( $element );
321 $ret['result'] = $newLine;
322 }
323
324 return $ret;
325 }
326
327 // Structure handler for temporary <br> elements
328 function structHandlerBr( $element, $newParent )
329 {
330 $ret = array();
331 $ret['result'] = $newParent;
332 $parent = $element->parentNode;
333
334 $next = $element->nextSibling;
335
336 if ( $element->getAttribute( 'ignore' ) != 'true' &&
337 $next &&
338 $next->nodeName == 'br' )
339 {
340 if ( $this->XMLSchema->check( $parent, 'paragraph' ) )
341 {
342 if ( !$newParent )
343 {
344 // create paragraph in case of the first empty paragraph
345 $newPara = $this->createAndPublishElement( 'paragraph', $ret );
346 $parent->replaceChild( $newPara, $element );
347 }
348 elseif ( $newParent->nodeName == 'paragraph' ||
349 $newParent->nodeName == 'line' )
350 {
351 // break paragraph or line flow
352 unset( $ret );
353 $ret = array();
354
355 // Do not process next <br> tag
356 $next->setAttribute( 'ignore', 'true' );
357
358 // create paragraph in case of the last empty paragraph (not inside section)
359 $nextToNext = $next->nextSibling;
360 $tmp = $parent;
361 while( !$nextToNext && $tmp && $tmp->nodeName == 'section' )
362 {
363 $nextToNext = $tmp->nextSibling;
364 $tmp = $tmp->parentNode;
365 }
366 if ( !$nextToNext )
367 {
368 $newPara = $this->createAndPublishElement( 'paragraph', $ret );
369 $parent->replaceChild( $newPara, $element );
370 }
371 }
372 }
373 }
374 else
375 {
376 if ( $newParent && $newParent->nodeName == 'line' )
377 {
378 $ret['result'] = $newParent->parentNode;
379 }
380 }
381
382 // Trim spaces used for tag indenting
383 if ( $next && $next->nodeType == XML_TEXT_NODE && !trim( $next->textContent ) )
384 {
385 $nextToNext = $next->nextSibling;
386 if ( !$nextToNext || $nextToNext->nodeName != 'br' )
387 {
388 $next = $parent->removeChild( $next );
389 }
390 }
391 return $ret;
392 }
393
394 // Structure handler for in-paragraph nodes.
395 function appendParagraph( $element, &$newParent )
396 {
397 $ret = array();
398 $parent = $element->parentNode;
399 if ( !$parent )
400 {
401 return $ret;
402 }
403
404 $parentName = $parent->nodeName;
405
406 if ( $parentName != 'paragraph' )
407 {
408 if ( $newParent && $newParent->nodeName == 'paragraph' )
409 {
410 $element = $parent->removeChild( $element );
411 $newParent->appendChild( $element );
412 $ret['result'] = $newParent;
413 }
414 elseif ( $newParent && $newParent->parentNode && $newParent->parentNode->nodeName == 'paragraph' )
415 {
416 $para = $newParent->parentNode;
417 $element = $parent->removeChild( $element );
418 $para->appendChild( $element );
419 $ret['result'] = $newParent->parentNode;
420 }
421 elseif ( $this->XMLSchema->check( $parentName, 'paragraph' ) )
422 {
423 $newPara = $this->createAndPublishElement( 'paragraph', $ret );
424 $parent->replaceChild( $newPara, $element );
425 $newPara->appendChild( $element );
426 $ret['result'] = $newPara;
427 }
428 }
429 return $ret;
430 }
431
432 // Structure handler for 'header' tag.
433 function structHandlerHeader( $element, &$param )
434 {
435 $ret = null;
436 $parent = $element->parentNode;
437 $level = $element->getAttribute( 'level' );
438 if ( $level < 1 )
439 {
440 $level = 1;
441 }
442
443 $element->removeAttribute( 'level' );
444 if ( $level )
445 {
446 $sectionLevel = -1;
447 $current = $element;
448 while( $current->parentNode )
449 {
450 $current = $current->parentNode;
451 if ( $current->nodeName == 'section' )
452 {
453 $sectionLevel++;
454 }
455 else
456 {
457 if ( $current->nodeName == 'td' )
458 {
459 $sectionLevel++;
460 break;
461 }
462 }
463 }
464 if ( $level > $sectionLevel )
465 {
466 if ( $this->StrictHeaders &&
467 $level - $sectionLevel > 1 )
468 {
469 $this->handleError( eZXMLInputParser::ERROR_SCHEMA,
470 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Incorrect headers nesting" ) );
471 }
472
473 $newParent = $parent;
474 for ( $i = $sectionLevel; $i < $level; $i++ )
475 {
476 $newSection = $this->Document->createElement( 'section' );
477 if ( $i == $sectionLevel )
478 {
479 $newSection = $newParent->insertBefore( $newSection, $element );
480 }
481 else
482 {
483 $newParent->appendChild( $newSection );
484 }
485
486 $newParent = $newSection;
487 unset( $newSection );
488 }
489 $elementToMove = $element;
490 while( $elementToMove &&
491 $elementToMove->nodeName != 'section' )
492 {
493 $next = $elementToMove->nextSibling;
494 $elementToMove = $parent->removeChild( $elementToMove );
495 $newParent->appendChild( $elementToMove );
496 $elementToMove = $next;
497
498 if ( $elementToMove && $elementToMove->nodeName == 'header' )
499 {
500 // in the case of non-strict headers
501 $headerLevel = $elementToMove->getAttribute( 'level' );
502 if ( $level - $sectionLevel > 1 )
503 {
504 if ( $headerLevel == $level )
505 {
506 $newParent2 = $this->Document->createElement( 'section' );
507 $newParent->parentNode->appendChild( $newParent2 );
508 $newParent = $newParent2;
509 }
510 elseif ( $headerLevel < $level )
511 {
512 break;
513 }
514 }
515 else
516 {
517 if ( $headerLevel <= $level )
518 {
519 break;
520 }
521 }
522 }
523 }
524 }
525 elseif ( $level < $sectionLevel )
526 {
527 $newLevel = $sectionLevel + 1;
528 $current = $element;
529 while( $level < $newLevel )
530 {
531 $current = $current->parentNode;
532 if ( $current->nodeName == 'section' )
533 {
534 $newLevel--;
535 }
536 }
537 $elementToMove = $element;
538 while ( $elementToMove->parentNode->nodeName === 'custom' )
539 {
540 $elementToMove = $elementToMove->parentNode;
541 $parent = $elementToMove->parentNode;
542 }
543 while( $elementToMove &&
544 $elementToMove->nodeName != 'section' )
545 {
546 $next = $elementToMove->nextSibling;
547 $elementToMove = $parent->removeChild( $elementToMove );
548 $current->appendChild( $elementToMove );
549 $elementToMove = $next;
550
551 if (
552 !$elementToMove ||
553 (
554 $elementToMove->nodeName == 'header' &&
555 $elementToMove->getAttribute( 'level' ) <= $level
556 )
557 )
558 {
559 break;
560 }
561 }
562 }
563 }
564 return $ret;
565 }
566
567 // Structure handler for 'custom' tag.
568 function structHandlerCustom( $element, &$params )
569 {
570 $ret = null;
571 if ( $this->XMLSchema->isInline( $element ) )
572 {
573 $ret = $this->appendLineParagraph( $element, $params );
574 }
575 else
576 {
577 $ret = $this->appendParagraph( $element, $params );
578 }
579 return $ret;
580 }
581
582 // Structure handler for 'ul' and 'ol' tags.
583 function structHandlerLists( $element, &$params )
584 {
585 $ret = array();
586 $parent = $element->parentNode;
587 $parentName = $parent->nodeName;
588
589 if ( $parentName == 'paragraph' )
590 {
591 return $ret;
592 }
593
594 // If we are inside a list
595 if ( $parentName == 'ol' || $parentName == 'ul' )
596 {
597 // If previous 'li' doesn't exist, create it,
598 // else append to the previous 'li' element.
599 $prev = $element->previousSibling;
600 if ( !$prev )
601 {
602 $li = $this->Document->createElement( 'li' );
603 $li = $parent->insertBefore( $li, $element );
604 $element = $parent->removeChild( $element );
605 $li->appendChild( $element );
606 }
607 else
608 {
609 $lastChild = $prev->lastChild;
610 if ( $lastChild->nodeName != 'paragraph' )
611 {
612 $para = $this->Document->createElement( 'paragraph' );
613 $element = $parent->removeChild( $element );
614 $prev->appendChild( $element );
615 $ret['result'] = $para;
616 }
617 else
618 {
619 $element = $parent->removeChild( $element );
620 $lastChild->appendChild( $element );
621 $ret['result'] = $lastChild;
622 }
623 return $ret;
624 }
625 }
626 if ( $parentName == 'li' )
627 {
628 $prev = $element->previousSibling;
629 if ( $prev )
630 {
631 $element = $parent->removeChild( $element );
632 $prev->appendChild( $element );
633 $ret['result'] = $prev;
634 return $ret;
635 }
636 }
637 $ret = $this->appendParagraph( $element, $params );
638
639 return $ret;
640 }
641
642 // Structure handler for #text
643 function structHandlerText( $element, &$newParent )
644 {
645 $ret = null;
646 $parent = $element->parentNode;
647 if ( !$parent )
648 {
649 return $ret;
650 }
651
652 // Remove empty text elements
653 if ( $element->textContent == '' )
654 {
655 $element = $parent->removeChild( $element );
656 return $ret;
657 }
658
659 $ret = $this->appendLineParagraph( $element, $newParent );
660
661 // Left trim spaces:
662 if ( $this->TrimSpaces )
663 {
664 $trim = false;
665 $currentElement = $element;
666
667 // Check if it is the first element in line
668 do
669 {
670 $prev = $currentElement->previousSibling;
671 if ( $prev )
672 {
673 break;
674 }
675
676 $currentElement = $currentElement->parentNode;
677
678 if ( $currentElement instanceof DOMElement &&
679 ( $currentElement->nodeName == 'line' ||
680 $currentElement->nodeName == 'paragraph' ) )
681 {
682 $trim = true;
683 break;
684 }
685
686 } while ( $currentElement instanceof DOMElement );
687
688 if ( $trim )
689 {
690 // Trim and remove if empty
691 $parent = $element->parentNode;
692 $trimmedElement = new DOMText( ltrim( $element->textContent ) );
693
694 if ( $trimmedElement->textContent == '' )
695 {
696 $parent->removeChild( $element );
697 }
698 else
699 {
700 $parent->replaceChild( $trimmedElement, $element );
701 }
702 }
703 }
704
705 return $ret;
706 }
707
708 /*
709 Publish handlers. (called at pass 2)
710 */
711 // Publish handler for 'paragraph' element.
712 function publishHandlerParagraph( $element, &$params )
713 {
714 $ret = null;
715 // Removes single line tag
716 $line = $element->lastChild;
717 if ( $element->childNodes->length == 1 && $line->nodeName == 'line' )
718 {
719 $lineChildren = array();
720 $lineChildNodes = $line->childNodes;
721 foreach ( $lineChildNodes as $lineChildNode )
722 {
723 $lineChildren[] = $lineChildNode;
724 }
725
726 $line = $element->removeChild( $line );
727 foreach ( $lineChildren as $lineChild )
728 {
729 $element->appendChild( $lineChild );
730 }
731 }
732
733 return $ret;
734 }
735
736 // Publish handler for 'link' element.
737 function publishHandlerLink( $element, &$params )
738 {
739 $ret = null;
740
741 $href = $element->getAttribute( 'href' );
742
743 if ( $href )
744 {
745 if ( preg_match( "@^ezobject://[0-9]+(#.*)?$@", $href ) )
746 {
747 $url = strtok( $href, '#' );
748 $anchorName = strtok( '#' );
749 $objectID = substr( strrchr( $url, "/" ), 1 );
750 $element->setAttribute( 'object_id', $objectID );
751
752 if ( !in_array( $objectID, $this->linkedObjectIDArray ) )
753 {
754 $this->linkedObjectIDArray[] = $objectID;
755 }
756 }
757 elseif ( preg_match( "@^eznode://.+(#.*)?$@" , $href ) )
758 {
759 $objectID = null;
760 $url = strtok( $href, '#' );
761 $anchorName = strtok( '#' );
762 $nodePath = substr( strchr( $url, "/" ), 2 );
763 if ( preg_match( "@^[0-9]+$@", $nodePath ) )
764 {
765 $nodeID = $nodePath;
766 $node = eZContentObjectTreeNode::fetch( $nodeID, false, false );
767 if ( !$node )
768 {
769 $this->handleError( eZXMLInputParser::ERROR_DATA,
770 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Node '%1' does not exist.", '', array( $nodeID ) ) );
771 }
772 else
773 {
774 $objectID = $node['id'];
775 }
776 }
777 else
778 {
779 $node = eZContentObjectTreeNode::fetchByURLPath( $nodePath, false );
780 if ( !$node )
781 {
782 $this->handleError( eZXMLInputParser::ERROR_DATA,
783 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Node '%1' does not exist.", '', array( $nodePath ) ) );
784 }
785 else
786 {
787 $nodeID = $node['node_id'];
788 $objectID = $node['id'];
789 }
790 $element->setAttribute( 'show_path', 'true' );
791 }
792 $element->setAttribute( 'node_id', $nodeID );
793
794 if ( $objectID && !in_array( $objectID, $this->linkedObjectIDArray ) )
795 {
796 $this->linkedObjectIDArray[] = $objectID;
797 }
798 }
799 elseif ( preg_match( "@^#.*$@" , $href ) )
800 {
801 $anchorName = substr( $href, 1 );
802 }
803 else
804 {
805 //washing href. single and double quotes replaced with their urlencoded form
806 $href = str_replace( array('\'','"'), array('%27','%22'), $href );
807
808 $temp = explode( '#', $href );
809 $url = $temp[0];
810 if ( isset( $temp[1] ) )
811 {
812 $anchorName = $temp[1];
813 }
814
815 if ( $url )
816 {
817 // Protection from XSS attack
818 if ( preg_match( "/^(java|vb)script:.*/i" , $url ) )
819 {
820 $this->handleError( eZXMLInputParser::ERROR_DATA,
821 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Using scripts in links is not allowed, link '%1' has been removed", '', array( $url ) ) );
822
823 $element->removeAttribute( 'href' );
824 return $ret;
825
826 }
827 // Check mail address validity following RFC 5322 and RFC 5321
828 if ( preg_match( "/^mailto:([^.][a-z0-9!#\$%&'*+-\/=?`{|}~^]+@([a-z0-9.-]+))/i" , $url, $mailAddr ) &&
829 !eZMail::validate( $mailAddr[1] ) )
830 {
831 $this->handleError( eZXMLInputParser::ERROR_DATA,
832 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Invalid e-mail address: '%1'", '' , array( $mailAddr[1] ) ) );
833
834 $element->removeAttribute( 'href' );
835 return $ret;
836 }
837 // Store urlID instead of href
838 $urlID = $this->convertHrefToID( $url );
839 if ( $urlID )
840 {
841 $urlIDAttributeName = 'url_id';
842
843 $element->setAttribute( $urlIDAttributeName, $urlID );
844 }
845 }
846 }
847
848 if ( isset( $anchorName ) && $anchorName )
849 {
850 $element->setAttribute( 'anchor_name', $anchorName );
851 }
852
853 $element->removeAttribute( 'href' );
854 }
855
856 return $ret;
857 }
858
859 function convertHrefToID( $href )
860 {
861 $href = str_replace("&amp;", "&", $href );
862
863 $urlID = eZURL::registerURL( $href );
864
865 if ( !in_array( $urlID, $this->urlIDArray ) )
866 {
867 $this->urlIDArray[] = $urlID;
868 }
869
870 return $urlID;
871 }
872
873 // Publish handler for 'embed' element.
874 function publishHandlerEmbed( $element, &$params )
875 {
876 $ret = null;
877
878 $href = $element->getAttribute( 'href' );
879 //washing href. single and double quotes replaced with their urlencoded form
880 $href = str_replace( array('\'','"'), array('%27','%22'), $href );
881
882 if ( $href != null )
883 {
884 if ( preg_match( "@^ezobject://[0-9]+$@" , $href ) )
885 {
886 $objectID = substr( strrchr( $href, "/" ), 1 );
887
888 // protection from self-embedding
889 if ( $objectID == $this->contentObjectID )
890 {
891 $this->handleError( eZXMLInputParser::ERROR_DATA,
892 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', 'Object %1 can not be embeded to itself.', '', array( $objectID ) ) );
893
894 $element->removeAttribute( 'href' );
895 return $ret;
896 }
897
898 $element->setAttribute( 'object_id', $objectID );
899
900 if ( !in_array( $objectID, $this->relatedObjectIDArray ) )
901 {
902 $this->relatedObjectIDArray[] = $objectID;
903 }
904 }
905 elseif ( preg_match( "@^eznode://.+$@" , $href ) )
906 {
907 $nodePath = substr( strchr( $href, "/" ), 2 );
908
909 if ( preg_match( "@^[0-9]+$@", $nodePath ) )
910 {
911 $nodeID = $nodePath;
912 $node = eZContentObjectTreeNode::fetch( $nodeID, false, false );
913 if ( !$node )
914 {
915 $this->handleError( eZXMLInputParser::ERROR_DATA,
916 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Node '%1' does not exist.", '', array( $nodeID ) ) );
917
918 $element->removeAttribute( 'href' );
919 return $ret;
920 }
921 }
922 else
923 {
924 $node = eZContentObjectTreeNode::fetchByURLPath( $nodePath, false );
925 if ( !$node )
926 {
927 $this->handleError( eZXMLInputParser::ERROR_DATA,
928 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', 'Node \'%1\' does not exist.', '', array( $nodePath ) ) );
929
930 $element->removeAttribute( 'href' );
931 return $ret;
932 }
933 $nodeID = $node['node_id'];
934 $element->setAttribute( 'show_path', 'true' );
935 }
936
937 $element->setAttribute( 'node_id', $nodeID );
938 $objectID = $node['id'];
939
940 // protection from self-embedding
941 if ( $objectID == $this->contentObjectID )
942 {
943 $this->handleError( eZXMLInputParser::ERROR_DATA,
944 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', 'Object %1 can not be embeded to itself.', '', array( $objectID ) ) );
945
946 $element->removeAttribute( 'href' );
947 return $ret;
948 }
949
950 if ( !in_array( $objectID, $this->relatedObjectIDArray ) )
951 {
952 $this->relatedObjectIDArray[] = $objectID;
953 }
954 }
955 else
956 {
957 $this->isInputValid = false;
958 $this->Messages[] = ezpI18n::tr( 'kernel/classes/datatypes', 'Invalid reference in &lt;embed&gt; tag. Note that <embed> tag supports only \'eznode\' and \'ezobject\' protocols.' );
959 $element->removeAttribute( 'href' );
960 return $ret;
961 }
962 }
963
964 $element->removeAttribute( 'href' );
965 $this->convertCustomAttributes( $element );
966 return $ret;
967 }
968
969 // Publish handler for 'object' element.
970 function publishHandlerObject( $element, &$params )
971 {
972 $ret = null;
973
974 $objectID = $element->getAttribute( 'id' );
975 // protection from self-embedding
976 if ( $objectID == $this->contentObjectID )
977 {
978 $this->isInputValid = false;
979 $this->Messages[] = ezpI18n::tr( 'kernel/classes/datatypes',
980 'Object %1 can not be embeded to itself.', false, array( $objectID ) );
981 return $ret;
982 }
983
984 if ( !in_array( $objectID, $this->relatedObjectIDArray ) )
985 {
986 $this->relatedObjectIDArray[] = $objectID;
987 }
988
989 // If there are any image object with links.
990 $href = $element->getAttributeNS( $this->Namespaces['image'], 'ezurl_href' );
991 //washing href. single and double quotes inside url replaced with their urlencoded form
992 $href = str_replace( array('\'','"'), array('%27','%22'), $href );
993
994 $urlID = $element->getAttributeNS( $this->Namespaces['image'], 'ezurl_id' );
995
996 if ( $href != null )
997 {
998 $urlID = eZURL::registerURL( $href );
999 $element->setAttributeNS( $this->Namespaces['image'], 'image:ezurl_id', $urlID );
1000 $element->removeAttributeNS( $this->Namespaces['image'], 'ezurl_href' );
1001 }
1002
1003 if ( $urlID != null )
1004 {
1005 $this->urlIDArray[] = $urlID;
1006 }
1007
1008 $this->convertCustomAttributes( $element );
1009
1010 return $ret;
1011 }
1012
1013 // Publish handler for 'custom' element.
1014 function publishHandlerCustom( $element, &$params )
1015 {
1016 $ret = null;
1017
1018 $element->removeAttribute( 'inline' );
1019 $this->convertCustomAttributes( $element );
1020
1021 return $ret;
1022 }
1023
1024 function convertCustomAttributes( $element )
1025 {
1026 $schemaAttrs = $this->XMLSchema->attributes( $element );
1027 $attributes = $element->attributes;
1028
1029 for ( $i = $attributes->length - 1; $i >= 0; $i-- )
1030 {
1031 $attr = $attributes->item( $i );
1032 if ( !$attr->prefix && !in_array( $attr->nodeName, $schemaAttrs ) )
1033 {
1034 $element->setAttributeNS( $this->Namespaces['custom'], 'custom:' . $attr->name, $element->getAttribute( $attr->name ) );
1035 $element->removeAttributeNode( $attr );
1036 }
1037 }
1038 }
1039
1040 function getRelatedObjectIDArray()
1041 {
1042 return $this->relatedObjectIDArray;
1043 }
1044
1045 function getLinkedObjectIDArray()
1046 {
1047 return $this->linkedObjectIDArray;
1048 }
1049
1050 function getUrlIDArray()
1051 {
1052 return $this->urlIDArray;
1053 }
1054
1055 public $urlIDArray = array();
1056 public $relatedObjectIDArray = array();
1057 public $linkedObjectIDArray = array();
1058
1059 // needed for self-embedding protection
1060 public $contentObjectID = 0;
1061 }
1062 ?>
eZContentObjectTreeNode\fetch
static fetch( $nodeID=false, $lang=false, $asObject=true, $conditions=false)
Definition: ezcontentobjecttreenode.php:3058
eZContentObjectTreeNode\fetchByURLPath
static fetchByURLPath( $pathString, $asObject=true)
Definition: ezcontentobjecttreenode.php:2943
eZDebugSetting\writeDebug
static writeDebug( $conditionName, $string, $label="")
Definition: ezdebugsetting.php:127
eZMail\validate
static validate( $address)
Definition: ezmail.php:747
eZSimplifiedXMLInputParser
Definition: ezsimplifiedxmlinputparser.php:13
eZSimplifiedXMLInputParser\$urlIDArray
$urlIDArray
Definition: ezsimplifiedxmlinputparser.php:1055
eZSimplifiedXMLInputParser\convertCustomAttributes
convertCustomAttributes( $element)
Definition: ezsimplifiedxmlinputparser.php:1024
eZSimplifiedXMLInputParser\publishHandlerLink
publishHandlerLink( $element, &$params)
Definition: ezsimplifiedxmlinputparser.php:737
eZSimplifiedXMLInputParser\parsingHandlerLiteral
parsingHandlerLiteral( $element, &$param)
Definition: ezsimplifiedxmlinputparser.php:163
eZSimplifiedXMLInputParser\structHandlerCustom
structHandlerCustom( $element, &$params)
Definition: ezsimplifiedxmlinputparser.php:568
eZSimplifiedXMLInputParser\structHandlerHeader
structHandlerHeader( $element, &$param)
Definition: ezsimplifiedxmlinputparser.php:433
eZSimplifiedXMLInputParser\$OutputTags
$OutputTags
Definition: ezsimplifiedxmlinputparser.php:37
eZSimplifiedXMLInputParser\$relatedObjectIDArray
$relatedObjectIDArray
Definition: ezsimplifiedxmlinputparser.php:1056
eZSimplifiedXMLInputParser\getRelatedObjectIDArray
getRelatedObjectIDArray()
Definition: ezsimplifiedxmlinputparser.php:1040
eZSimplifiedXMLInputParser\convertHrefToID
convertHrefToID( $href)
Definition: ezsimplifiedxmlinputparser.php:859
eZSimplifiedXMLInputParser\$linkedObjectIDArray
$linkedObjectIDArray
Definition: ezsimplifiedxmlinputparser.php:1057
eZSimplifiedXMLInputParser\appendParagraph
appendParagraph( $element, &$newParent)
Definition: ezsimplifiedxmlinputparser.php:395
eZSimplifiedXMLInputParser\structHandlerLists
structHandlerLists( $element, &$params)
Definition: ezsimplifiedxmlinputparser.php:583
eZSimplifiedXMLInputParser\publishHandlerEmbed
publishHandlerEmbed( $element, &$params)
Definition: ezsimplifiedxmlinputparser.php:874
eZSimplifiedXMLInputParser\tagNameHeader
tagNameHeader( $tagName, &$attributes)
Definition: ezsimplifiedxmlinputparser.php:124
eZSimplifiedXMLInputParser\$contentObjectID
$contentObjectID
Definition: ezsimplifiedxmlinputparser.php:1060
eZSimplifiedXMLInputParser\getLinkedObjectIDArray
getLinkedObjectIDArray()
Definition: ezsimplifiedxmlinputparser.php:1045
eZSimplifiedXMLInputParser\publishHandlerCustom
publishHandlerCustom( $element, &$params)
Definition: ezsimplifiedxmlinputparser.php:1014
eZSimplifiedXMLInputParser\breakInlineFlow
breakInlineFlow( $element, $param)
Definition: ezsimplifiedxmlinputparser.php:191
eZSimplifiedXMLInputParser\structHandlerText
structHandlerText( $element, &$newParent)
Definition: ezsimplifiedxmlinputparser.php:643
eZSimplifiedXMLInputParser\structHandlerBr
structHandlerBr( $element, $newParent)
Definition: ezsimplifiedxmlinputparser.php:328
eZSimplifiedXMLInputParser\publishHandlerParagraph
publishHandlerParagraph( $element, &$params)
Definition: ezsimplifiedxmlinputparser.php:712
eZSimplifiedXMLInputParser\getUrlIDArray
getUrlIDArray()
Definition: ezsimplifiedxmlinputparser.php:1050
eZSimplifiedXMLInputParser\__construct
__construct( $contentObjectID, $validateErrorLevel=eZXMLInputParser::ERROR_ALL, $detectErrorLevel=eZXMLInputParser::ERROR_ALL, $parseLineBreaks=false, $removeDefaultAttrs=false)
Definition: ezsimplifiedxmlinputparser.php:114
eZSimplifiedXMLInputParser\$isInputValid
$isInputValid
Definition: ezsimplifiedxmlinputparser.php:17
eZSimplifiedXMLInputParser\$InputTags
$InputTags
Definition: ezsimplifiedxmlinputparser.php:18
eZSimplifiedXMLInputParser\publishHandlerObject
publishHandlerObject( $element, &$params)
Definition: ezsimplifiedxmlinputparser.php:970
eZSimplifiedXMLInputParser\appendLineParagraph
appendLineParagraph( $element, $newParent)
Definition: ezsimplifiedxmlinputparser.php:258
eZURL\registerURL
static registerURL( $url)
Definition: ezurl.php:96
eZXMLInputParser
Definition: ezxmlinputparser.php:25
eZXMLInputParser\ERROR_SCHEMA
const ERROR_SCHEMA
Definition: ezxmlinputparser.php:34
eZXMLInputParser\handleError
handleError( $type, $message)
Definition: ezxmlinputparser.php:1309
eZXMLInputParser\createAndPublishElement
createAndPublishElement( $elementName, &$ret)
Definition: ezxmlinputparser.php:1204
eZXMLInputParser\ERROR_ALL
const ERROR_ALL
Definition: ezxmlinputparser.php:36
eZXMLInputParser\ERROR_DATA
const ERROR_DATA
Definition: ezxmlinputparser.php:35
ezpI18n\tr
static tr( $context, $source, $comment=null, $arguments=null)
Definition: ezpi18n.php:86
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.