blob: 7433653cd657894291216bd1dcc975ec9eb6afcf [file] [log] [blame]
/**
* **********************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
*
* Use is subject to license terms.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0. You can also
* obtain a copy of the License at http://odftoolkit.org/docs/license.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
***********************************************************************
*/
package org.odftoolkit.odfvalidator;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.zip.ZipException;
import javax.xml.validation.Validator;
import org.odftoolkit.odfdom.doc.OdfDocument;
import org.odftoolkit.odfdom.pkg.OdfPackage;
import org.xml.sax.ErrorHandler;
abstract class ODFRootPackageValidator extends ODFPackageValidator implements ManifestEntryListener {
private OdfPackage m_aPkg = null;
private ArrayList<ManifestEntry> m_aSubDocs = null;
private ODFPackageErrorHandler m_ErrorHandler = null;
protected ODFRootPackageValidator(Logger.LogLevel nLogLevel, OdfValidatorMode eMode, OdfVersion aVersion, SAXParseExceptionFilter aFilter, ODFValidatorProvider aValidatorProvider) {
super(nLogLevel, eMode, aVersion, aFilter, aValidatorProvider);
}
protected abstract OdfPackage getPackage(ErrorHandler handler) throws Exception;
protected OdfPackage getPackage(Logger aLogger) {
if (m_aPkg == null) {
try {
m_ErrorHandler = new ODFPackageErrorHandler();
m_aPkg = getPackage(m_ErrorHandler);
// for additional mimetype checking, load root document
try {
OdfDocument.loadDocument(m_aPkg, "");
} catch (Exception e) {
// ignore -- the interesting stuff is passed to handler
}
} catch (IOException e) {
if (e.getMessage().startsWith("only DEFLATED entries can have EXT descriptor")) {
aLogger.logFatalError("The document is encrypted. Validation of encrypted documents is not supported.");
} else {
aLogger.logFatalError(e.getMessage());
}
} catch (Exception e) {
StringWriter errors = new StringWriter();
e.printStackTrace(new PrintWriter(errors));
aLogger.logFatalError(e.getMessage() + "\n" + errors.toString());
}
}
return m_aPkg;
}
protected String getStreamName(String aEntry) {
return aEntry;
}
@Override
protected boolean validatePre(Logger aLogger, OdfVersion aVersion) throws ODFValidatorException, IOException {
Logger aManifestLogger = new Logger(OdfPackage.OdfFile.MANIFEST.getPath(), aLogger);
Logger aMimetypeLogger = new Logger("mimetype", aLogger);
// UGLY: do something that causes ODFDOM to parse the manifest, which
// may cause m_ErrorHandler to be called
m_aPkg.getFilePaths();
// hack: just create logger again, too lazy to create a Pair class
// and return it from validateMimetype...
boolean bErrorsFound = m_ErrorHandler.processErrors(aLogger, aManifestLogger,
aMimetypeLogger, aVersion);
bErrorsFound |= validateMimetype(aMimetypeLogger, aVersion);
bErrorsFound |= validateManifest(aManifestLogger, aVersion);
aMimetypeLogger.logSummaryInfo();
return bErrorsFound;
}
@Override
protected boolean validatePost(Logger aLogger, OdfVersion aVersion) throws ODFValidatorException, IOException {
boolean bHasErrors = false;
if (m_aSubDocs != null) {
Iterator<ManifestEntry> aIter = m_aSubDocs.iterator();
while (aIter.hasNext()) {
ManifestEntry aEntry = aIter.next();
ODFPackageValidator aPackageValidator
= new ODFSubPackageValidator(getPackage(aLogger), getLoggerName(), aEntry.getFullPath(), aEntry.getMediaType(),
m_nLogLevel, m_eMode, m_aConfigVersion, m_aFilter, m_aResult.getGenerator(), m_aValidatorProvider);
bHasErrors |= aPackageValidator.validate(aLogger);
}
}
if (aVersion.compareTo(OdfVersion.V1_2) >= 0) {
bHasErrors |= validateDSig(aLogger, OdfPackageExt.STREAMNAME_DOCUMENT_SIGNATURES, aVersion);
bHasErrors |= validateDSig(aLogger, OdfPackageExt.STREAMNAME_MACRO_SIGNATURES, aVersion);
}
return bHasErrors;
}
@Override
protected void logSummary(boolean bHasErrors, Logger aLogger) {
aLogger.logSummaryInfo();
if ((bHasErrors || aLogger.hasError()) && m_nLogLevel.compareTo(Logger.LogLevel.INFO) < 0) {
aLogger.logInfo("Generator: " + m_aResult.getGenerator(), true);
}
}
public void foundManifestEntry(ManifestEntry aManifestEntry) {
if (aManifestEntry.isOpenDocumentMediaType()) {
if (m_aSubDocs == null) {
m_aSubDocs = new ArrayList<ManifestEntry>();
}
m_aSubDocs.add(aManifestEntry);
}
}
private boolean validateMimetype(Logger aLogger, OdfVersion aVersion) {
boolean bHasErrors = false;
String aMimetype = getPackage(aLogger).getMediaTypeString();
if ((aMimetype == null) || aMimetype.length() == 0) {
aLogger.logFatalError("file is not a zip file, or has no mimetype.");
bHasErrors = true;
} else if (!(aMimetype.equals(ODFMediaTypes.TEXT_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.TEXT_TEMPLATE_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.GRAPHICS_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.GRAPHICS_TEMPLATE_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.PRESENTATION_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.SPREADSHEET_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.SPREADSHEET_TEMPLATE_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.CHART_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.CHART_TEMPLATE_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.IMAGE_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.IMAGE_TEMPLATE_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.FORMULA_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.FORMULA_TEMPLATE_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.TEXT_MASTER_MEDIA_TYPE)
|| aMimetype.equals(ODFMediaTypes.TEXT_WEB_MEDIA_TYPE))) {
aLogger.logInfo("mimetype is not an ODFMediaTypes mimetype.", false);
bHasErrors = true;
}
return bHasErrors;
}
private boolean validateManifest(Logger aLogger, OdfVersion aVersion) throws IOException, ZipException, IllegalStateException, ODFValidatorException {
boolean bRet;
ManifestFilter aFilter = new ManifestFilter(aLogger, m_aResult, this);
Validator aManifestValidator = m_aValidatorProvider.getManifestValidator(aLogger.getOutputStream(), aVersion);
if (aManifestValidator != null) {
bRet = validateEntry(aFilter,
aManifestValidator, aLogger, OdfPackage.OdfFile.MANIFEST.getPath());
} else {
aLogger.logInfo("Validation of " + OdfPackage.OdfFile.MANIFEST.getPath() + " skipped.", false);
bRet = parseEntry(aFilter, aLogger, OdfPackage.OdfFile.MANIFEST.getPath(), false);
}
return bRet;
}
}