1 /* Licensed to the Apache Software Foundation (ASF) under one or more
  2  * contributor license agreements.  See the NOTICE file distributed with
  3  * this work for additional information regarding copyright ownership.
  4  * The ASF licenses this file to you under the Apache License, Version 2.0
  5  * (the "License"); you may not use this file except in compliance with
  6  * the License.  You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15 */
 16 
 17 /**
 18  * @class
 19  * @name _HtmlStripper
 20  * @memberOf myfaces._impl._util
 21  * @extends myfaces._impl.core._Runtime
 22  * @description
 23  *  Fallback routine if the browser embedded xml parser fails on the document
 24  *  This fallback is not failsafe but should give enough cover to handle all cases
 25  */
 26 
 27 /** @namespace myfaces._impl._util._HtmlStripper */
 28 myfaces._impl.core._Runtime.extendClass("myfaces._impl._util._HtmlStripper", Object,
 29 /** @lends myfaces._impl._util._HtmlStripper.prototype */
 30 {
 31     BEGIN_TAG: "html",
 32     END_TAG: "lmth",
 33     /**
 34      * main parse routine parses the document for a given tag name
 35      *
 36      *
 37      * @param theString  the markup string to be parsed
 38      * @param tagNameStart the tag name to be parsed for
 39      */
 40     parse : function(theString, tagNameStart) {
 41         this.tokens = theString.split("");
 42         this.tagAttributes = {};
 43 
 44         this._tagStart = -1;
 45         this._tagEnd = -1;
 46 
 47         this._contentStart = -1;
 48         this._contentEnd = -1;
 49         this._tokenPos = 0;
 50 
 51         this._tokenForward = 1;
 52 
 53         this.tagNameStart = (!tagNameStart) ? this.BEGIN_TAG : tagNameStart;
 54 
 55         //no need for ll parsing a handful of indexofs instead of slower regepx suffices
 56 
 57         var proposedTagStartPos = theString.indexOf("<"+tagNameStart);
 58 
 59         while(this._contentStart == -1 && proposedTagStartPos != -1) {
 60             if(this.checkBackForComment(theString, proposedTagStartPos))  {
 61                 this._tagStart = proposedTagStartPos;
 62                 this._contentStart = proposedTagStartPos+theString.substring(proposedTagStartPos).indexOf(">")+1;
 63             }
 64             proposedTagStartPos = theString.substring(proposedTagStartPos+tagNameStart.length+2).indexOf("<"+tagNameStart);
 65         }
 66 
 67         var proposedEndTagPos = theString.lastIndexOf("</"+tagNameStart);
 68         while(this._contentEnd == -1 && proposedEndTagPos > 0) {
 69             if(this.checkForwardForComment(theString, proposedEndTagPos))  {
 70                 this._tagEnd = proposedEndTagPos;
 71                 this._contentEnd = proposedEndTagPos;
 72             }
 73             proposedTagStartPos = theString.substring(proposedTagStartPos-tagNameStart.length-2).lastIndexOf("</"+tagNameStart);
 74         }
 75         if(this._contentStart != -1 && this._contentEnd != -1) {
 76             return theString.substring(this._contentStart, this._contentEnd);
 77         }
 78         return null;
 79     },
 80     
 81     checkForwardForComment: function(theStr, tagPos) {
 82         var toCheck = theStr.substring(tagPos);
 83         var firstBeginComment = toCheck.indexOf("<!--");
 84         var firstEndComment = toCheck.indexOf("-->");
 85 
 86         var firstBeginCDATA = toCheck.indexOf("<[CDATA[");
 87         var firstEndCDATA = toCheck.indexOf("]]>");
 88         
 89         if(this.isValidPositionCombination(firstBeginComment, firstEndComment, firstBeginCDATA, firstEndCDATA)) {
 90             return true;
 91         }
 92 
 93         return firstBeginComment <= firstEndComment && firstBeginCDATA <= firstEndCDATA;
 94     },
 95 
 96     checkBackForComment: function(theStr, tagPos) {
 97         var toCheck = theStr.substring(tagPos);
 98         var lastBeginComment = toCheck.lastIndexOf("<!--");
 99         var lastEndComment = toCheck.lastIndexOf("-->");
100 
101         var lastBeginCDATA = toCheck.lastIndexOf("<[CDATA[");
102         var lastEndCDATA = toCheck.lastIndexOf("]]>");
103 
104 
105         if(this.isValidPositionCombination(lastBeginComment, lastEndComment, lastBeginCDATA, lastEndCDATA)) {
106             //TODO we have to handle the embedded cases, for now we leave them out
107             return true;
108         }
109 
110     },
111 
112     isValidPositionCombination: function(pos1, pos2, pos3, pos4) {
113         return pos1 <= pos2 && pos3 <= pos4;
114     },
115 
116     isFullyEmbedded: function(pos1, pos2, embedPos1, embedPos2) {
117         return embedPos1 < pos1 < pos2 < embedPos2;
118     },
119 
120     isPartiallyEmbedded: function(pos1, pos2, embedPos1, embedPos2) {
121         return embedPos1 < pos1 <  embedPos2 < pos2 || pos1 < embedPos1 < pos2 <  embedPos2  ;    
122     }
123 
124 });
125 
126 
127 
128