/**
 * Copyright 2009  Michael Leupold <lemma@confuego.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) version 3, or any
 * later version accepted by the membership of KDE e.V. (or its
 * successor approved by the membership of KDE e.V.), which shall
 * act as a proxy defined in Section 6 of version 3 of the license.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef PARSERPRIVATE_H
#define PARSERPRIVATE_H

#include <KUrl>
#include <QtCore/QList>

extern "C" {
    #include <libxml/parserInternals.h>
    #include <libexslt/exslt.h>
    #include <libxslt/transform.h>
}

/**
 * Stores transformation errors
 */
struct TransformationError
{
    // transformation error
    enum ErrorType {
        ErrorSecurity,   // security error - loading a file was forbidden
        ErrorInvalid,    // invalid input data/url
        ErrorEncoding,   // invalid output encoding
        ErrorNotFound,   // a file was not found
        ErrorParser,     // the parser returned an error
        ErrorTransform   // an error happened during transformation
    };

    ErrorType m_errorType; // always set
    int m_code; // error code (for parser/transform)
    QString m_message; // error message (for encoding/parser/transform)
    KUrl m_file; // file the error happened in/for (for all but encoding)
    int line; // line the error happened in/for (for parser/transform)
};

/**
 * This class is passed as _private member of xmlParserCtxt,
 * xsltTransformContext and xmlDoc if needed.
 * It also contains static functions that add ParserPrivate
 * to those types and add error messages.
 */
class ParserPrivate
{
private:
    /**
     * Private constructor as this is only constructed by the various
     * static methods.
     */
    ParserPrivate();

public:
    ~ParserPrivate();

    /**
     * Add a _private member of type ParserPrivate* to an xmlDoc
     */
    static void docCreatePrivate(xmlDocPtr doc);

    /**
     * Free the _private member of an xmlDoc added using docCreatePrivate
     */
    static void docFreePrivate(xmlDocPtr doc);

    /**
     * Get the errors from xmlDoc's _private member
     */
    static QList<TransformationError> docGetErrors(xmlDocPtr doc);

    /**
     * Add a list of previous errors to the xmlDoc
     */
    static void docAddErrors(xmlDocPtr doc, const QList<TransformationError> &errors);

    /**
     * Add a security error to an xmlDoc
     */
    static void docAddSecurityError(xmlDocPtr doc, const KUrl &url);

    /**
     * Construct a transform context containing a _private member
     * of type ParserPrivate* which is added to
     * ParserPrivate::s_knownPrivates
     */
    static xsltTransformContextPtr createTransformContext(xsltStylesheetPtr style,
                                                          xmlDocPtr doc);

    /**
     * Free a transform context created by createTransformContext
     */
    static void freeTransformContext(xsltTransformContextPtr ctxt);

    /**
     * Get the errors from the transform context
     */
    static QList<TransformationError> contextGetErrors(xsltTransformContextPtr ctxt);

    /**
     * Add a list of previous errors to the transform context
     */
    static void contextAddErrors(xsltTransformContextPtr ctxt,
                                 const QList<TransformationError> &errors);

    /**
     * Add a security error to the private part of a transform context
     */
    static void contextAddSecurityError(xsltTransformContextPtr ctxt, const KUrl &url);

    /**
     * Construct a parser context containing a _private member of
     * type ParserPrivate* which is added to ParserPrivate::s_knownPrivates
     */
    static xmlParserCtxtPtr createParserContext(bool allowLocal,
                                                xmlDictPtr dict = 0,
                                                int options = 0);

    /**
     * Free a parser context created by createParserContext and return
     * the parsed document.
     */
    static xmlDocPtr freeParserContext(xmlParserCtxtPtr ctxt);

    /**
     * Get the errors from the entity loader's context
     */
    static QList<TransformationError> contextGetErrors(xmlParserCtxtPtr ctxt);

    /**
     * Check if security allows loading the url in the given context. Also
     * set a new security policy on the context if the loaded url is remote.
     */
    static bool securityLoadCheck(const KUrl &url, xmlParserCtxtPtr ctxt);

    /**
     * Add a security error to the private part of an xmlParserCtxt
     */
    static void contextAddSecurityError(xmlParserCtxtPtr ctxt, const KUrl &url);

    /**
     * Add a file-not-found error to the private part of an xmlParserCtxt
     */
    static void contextAddNotFoundError(xmlParserCtxtPtr ctxt, const KUrl &url);
    
private:
    // allow loading local entities?
    bool m_allowLocal;
    // list of errors
    QList<TransformationError> m_errors;

    // list of known ParserPrivate pointers
    static QList<void*> s_knownPrivates;
};


#endif
