1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15 
16 #include "XMLObject.hxx"
17 #include "XMLValidation.hxx"
18 #include "XMLValidationDTD.hxx"
19 #include "XMLDocument.hxx"
20 #include "VariableScope.hxx"
21 
22 extern "C"
23 {
24 #include "expandPathVariable.h"
25 #include "sci_malloc.h"
26 #include "localization.h"
27 }
28 
29 namespace org_modules_xml
30 {
31 
XMLValidationDTD(const char * path,std::string * error)32 XMLValidationDTD::XMLValidationDTD(const char *path, std::string * error): XMLValidation()
33 {
34     internalValidate = false;
35     char *expandedPath = expandPathVariable(const_cast<char *>(path));
36     if (expandedPath)
37     {
38         validationFile = (void *)xmlParseDTD(0, (const xmlChar *)expandedPath);
39         FREE(expandedPath);
40         if (!validationFile)
41         {
42             errorBuffer.clear();
43             errorBuffer.append(gettext("Cannot parse the DTD"));
44             *error = errorBuffer;
45         }
46         else
47         {
48             openValidationFiles.push_back(this);
49         }
50     }
51     else
52     {
53         *error = std::string(gettext("Invalid file name: ")) + std::string(path);
54     }
55 
56     scope->registerPointers(validationFile, this);
57     id = scope->getVariableId(*this);
58 }
59 
XMLValidationDTD()60 XMLValidationDTD::XMLValidationDTD(): XMLValidation()
61 {
62     validationFile = 0;
63     internalValidate = true;
64     id = scope->getVariableId(*this);
65     openValidationFiles.push_back(this);
66 }
67 
~XMLValidationDTD()68 XMLValidationDTD::~XMLValidationDTD()
69 {
70     scope->unregisterPointer(validationFile);
71     scope->removeId(id);
72 
73     if (validationFile)
74     {
75         xmlFreeDtd(getValidationFile < xmlDtd > ());
76     }
77 
78     if (validationFile || internalValidate)
79     {
80         openValidationFiles.remove(this);
81         if (openValidationFiles.size() == 0 && XMLDocument::getOpenDocuments().size() == 0)
82         {
83             resetScope();
84         }
85     }
86 
87     errorBuffer.clear();
88 }
89 
validate(const XMLDocument & doc,std::string * error) const90 bool XMLValidationDTD::validate(const XMLDocument & doc, std::string * error) const
91 {
92     bool ret;
93     xmlValidCtxt *vctxt = xmlNewValidCtxt();
94 
95     errorBuffer.clear();
96 
97     if (!vctxt)
98     {
99         errorBuffer.append(gettext("Cannot create a valid context"));
100         *error = errorBuffer;
101         return false;
102     }
103 
104     vctxt->error = (xmlValidityErrorFunc) XMLValidation::errorFunction;
105 
106     ret = xmlValidateDtd(vctxt, doc.getRealDocument(), getValidationFile < xmlDtd > ()) == 1;
107 
108     vctxt->error = 0;
109     xmlFreeValidCtxt(vctxt);
110 
111     if (!ret)
112     {
113         *error = errorBuffer;
114     }
115 
116     return ret;
117 }
118 
validate(xmlTextReader * reader,std::string * error) const119 bool XMLValidationDTD::validate(xmlTextReader * reader, std::string * error) const
120 {
121     int last;
122     int valid;
123 
124     errorBuffer.clear();
125 
126     if (!internalValidate)
127     {
128         errorBuffer.append(gettext("Due to a libxml2 limitation, it is not possible to validate a document against an external DTD\nPlease see help xmlValidate.\n"));
129         *error = errorBuffer;
130         return false;
131     }
132 
133     xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
134     xmlTextReaderSetErrorHandler(reader, (xmlTextReaderErrorFunc) XMLValidation::errorReaderFunction, 0);
135     while ((last = xmlTextReaderRead(reader)) == 1)
136     {
137         ;
138     }
139     valid = xmlTextReaderIsValid(reader);
140 
141     xmlTextReaderSetErrorHandler(reader, 0, 0);
142     xmlFreeTextReader(reader);
143 
144     if (last == -1 || valid != 1)
145     {
146         *error = errorBuffer;
147         return false;
148     }
149 
150     return true;
151 }
152 
toString() const153 const std::string XMLValidationDTD::toString() const
154 {
155     std::ostringstream oss;
156     xmlDtd *dtd = getValidationFile < xmlDtd > ();
157 
158     oss << "XML DTD" << std::endl;
159     oss << "name: " << (dtd->name ? (const char *)dtd->name : "") << std::endl;
160     oss << "external ID: " << (dtd->ExternalID ? (const char *)dtd->ExternalID : "") << std::endl;
161     oss << "system ID: " << (dtd->SystemID ? (const char *)dtd->SystemID : "");
162 
163     return oss.str();
164 }
165 }
166 
167