/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.modules.cp;
import org.olat.core.gui.components.tree.TreeNode;
import org.olat.core.util.StringHelper;
import org.olat.core.util.WebappHelper;
import org.olat.core.util.nodes.INode;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VFSLeaf;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* Description:<br>
* SAX handler for the NekoParser
*
* <P>
* Initial Date: 18 mars 2011 <br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
//fxdiff VCRP-14: print cp
public class NekoHtmlPageHandler extends DefaultHandler {
private final StringBuilder header = new StringBuilder();
private final StringBuilder body = new StringBuilder();
private final String HEAD = "HEAD";
private final String BODY = "BODY";
private final String SCRIPT = "SCRIPT";
private boolean pauseOutput;
private StringBuilder output;
private String relativePath;
private final TreeNode node;
private final String baseUri;
private final VFSLeaf document;
private final VFSContainer rootContainer;
public NekoHtmlPageHandler(TreeNode node, VFSLeaf document, VFSContainer rootDir, String baseUri) {
this.document = document;
this.rootContainer = rootDir;
this.baseUri = baseUri;
this.node = node;
}
public boolean isEmpty() {
return document == null;
}
public String getTitle() {
return node.getTitle();
}
public int getLevel() {
int count = 0;
INode currentNode = node;
while(currentNode != null) {
currentNode = currentNode.getParent();
count++;
}
return count;
}
public VFSLeaf getDocument() {
return document;
}
public StringBuilder getHeader() {
return header;
}
public StringBuilder getBody() {
return body;
}
public String getRelativePath() {
return relativePath;
}
public void setRelativePath(String relativePath) {
this.relativePath = relativePath;
}
@Override
public final void startDocument() {
//
}
@Override
public final void startElement(String uri, String localName, String qName, Attributes attributes) {
if (HEAD.equals(localName)) {
output = header;
} else if (BODY.equals(localName)) {
output = body;
} else if (SCRIPT.equals(localName)) {
pauseOutput = true;
} else if (output != null) {
pauseOutput = false;
output.append("<").append(localName);
int numOfAttributes = attributes.getLength();
for(int i=0; i<numOfAttributes; i++) {
String attrName = attributes.getLocalName(i);
String attrValue = attributes.getValue(i);
output.append(' ').append(attrName).append('=');
boolean useSingle = (attrValue.indexOf('"') > 0);
if(useSingle) {
output.append('\'');
} else {
output.append('"');
}
if(attrName.equalsIgnoreCase("href") || attrName.equalsIgnoreCase("src")) {
output.append(normalizeUri(attrValue));
} else {
output.append(attrValue);
}
if(useSingle) {
output.append('\'');
} else {
output.append('"');
}
}
output.append(">");
}
}
private final String normalizeUri(String uri) {
if(uri.indexOf("://") > 0 || uri.startsWith("/") || uri.startsWith("data:")) {
return uri;//absolute link or image data uri, nothing to do
}
String contextPath = WebappHelper.getServletContextPath();
if(uri.startsWith(contextPath)) {
return uri;//absolute within olat
}
if(uri.startsWith("..")) {
VFSContainer startDir;
if(relativePath == null) {
startDir = rootContainer;
} else {
startDir = (VFSContainer)rootContainer.resolve(relativePath);
}
String tmpUri = uri;
VFSContainer tmpDir = startDir;
while(tmpUri.startsWith("../") && tmpDir != null) {
tmpDir = tmpDir.getParentContainer();
tmpUri = tmpUri.substring(3);
}
if (tmpDir == null) {
// no local file uri, return unchanged
return uri;
}
String diffPath = getRelativeResultingPath(tmpDir);
if(StringHelper.containsNonWhitespace(diffPath)) {
return diffPath + tmpUri;
}
return tmpUri;
}
if (relativePath != null) {
uri = relativePath + uri;
}
return baseUri + "/" + uri;
}
private String getRelativeResultingPath(VFSContainer tmpDir) {
String diffPath = "";
while(!tmpDir.isSame(rootContainer)) {
diffPath = tmpDir.getName() + "/" + diffPath;
tmpDir = tmpDir.getParentContainer();
}
return diffPath;
}
@Override
public final void characters(char[] ch, int start, int length) {
if(output != null && !pauseOutput) {
output.append(ch, start, length);
}
}
@Override
public final void endElement(String uri, String localName, String qName) {
if(HEAD.equals(localName)) {
output = null;
} else if (BODY.equals(localName)) {
output = null;
} else if (SCRIPT.equals(localName)) {
pauseOutput = false;
} else if (output != null) {
output.append("</").append(localName).append(">");
}
}
}