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 "XMLValidationSchema.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 #include "BOOL.h"
28 }
29 
30 namespace org_modules_xml
31 {
32 
XMLValidationSchema(const char * path,std::string * error)33 XMLValidationSchema::XMLValidationSchema(const char *path, std::string * error): XMLValidation()
34 {
35     char *expandedPath = expandPathVariable(const_cast < char *>(path));
36     if (expandedPath)
37     {
38         xmlSchemaParserCtxt *pctxt = xmlSchemaNewParserCtxt(expandedPath);
39         FREE(expandedPath);
40         if (!pctxt)
41         {
42             errorBuffer.clear();
43             errorBuffer.append(gettext("Cannot create a validation context"));
44             *error = errorBuffer;
45         }
46         else
47         {
48             validationFile = (void *)xmlSchemaParse(pctxt);
49             xmlSchemaFreeParserCtxt(pctxt);
50             if (!validationFile)
51             {
52                 errorBuffer.clear();
53                 errorBuffer.append(gettext("Cannot parse the schema"));
54                 *error = errorBuffer;
55             }
56             else
57             {
58                 openValidationFiles.push_back(this);
59             }
60         }
61     }
62     else
63     {
64         *error = std::string(gettext("Invalid file name: ")) + std::string(path);
65     }
66     scope->registerPointers(validationFile, this);
67     id = scope->getVariableId(*this);
68 }
69 
~XMLValidationSchema()70 XMLValidationSchema::~XMLValidationSchema()
71 {
72     scope->unregisterPointer(validationFile);
73     scope->removeId(id);
74     if (validationFile)
75     {
76         xmlSchemaFree((xmlSchema *) validationFile);
77         openValidationFiles.remove(this);
78         if (openValidationFiles.size() == 0 && XMLDocument::getOpenDocuments().size() == 0)
79         {
80             resetScope();
81         }
82     }
83 
84     errorBuffer.clear();
85 }
86 
validate(const XMLDocument & doc,std::string * error) const87 bool XMLValidationSchema::validate(const XMLDocument & doc, std::string * error) const
88 {
89     bool ret;
90     xmlSchemaValidCtxt *vctxt = xmlSchemaNewValidCtxt((xmlSchema *) validationFile);
91 
92     errorBuffer.clear();
93 
94     if (!vctxt)
95     {
96         errorBuffer.append(gettext("Cannot create a validation context"));
97         *error = errorBuffer;
98         return false;
99     }
100 
101     xmlSchemaSetValidErrors(vctxt, (xmlSchemaValidityErrorFunc) XMLValidation::errorFunction, 0, 0);
102 
103     ret = BOOLtobool(xmlSchemaValidateDoc(vctxt, doc.getRealDocument()));
104 
105     xmlSchemaSetValidErrors(vctxt, 0, 0, 0);
106     xmlSchemaFreeValidCtxt(vctxt);
107 
108     if (ret)
109     {
110         *error = errorBuffer;
111     }
112 
113     return ret == 0;
114 }
115 
validate(xmlTextReader * reader,std::string * error) const116 bool XMLValidationSchema::validate(xmlTextReader * reader, std::string * error) const
117 {
118     xmlSchemaValidCtxt *vctxt = 0;
119     int last;
120     int valid;
121 
122     errorBuffer.clear();
123 
124     if (!reader)
125     {
126         errorBuffer.append(gettext("Cannot read the stream"));
127         *error = errorBuffer;
128         return false;
129     }
130 
131     vctxt = xmlSchemaNewValidCtxt(getValidationFile < xmlSchema > ());
132     if (!vctxt)
133     {
134         errorBuffer.append(gettext("Cannot create a validation context"));
135         *error = errorBuffer;
136         return false;
137     }
138 
139     xmlSchemaSetValidErrors(vctxt, (xmlSchemaValidityErrorFunc) XMLValidation::errorFunction, 0, 0);
140     xmlTextReaderSetErrorHandler(reader, (xmlTextReaderErrorFunc) XMLValidation::errorReaderFunction, 0);
141     xmlTextReaderSchemaValidateCtxt(reader, vctxt, 0);
142 
143     while ((last = xmlTextReaderRead(reader)) == 1)
144     {
145         ;
146     }
147     valid = xmlTextReaderIsValid(reader);
148 
149     xmlTextReaderSetErrorHandler(reader, 0, 0);
150     xmlSchemaSetValidErrors(vctxt, 0, 0, 0);
151     xmlFreeTextReader(reader);
152     xmlSchemaFreeValidCtxt(vctxt);
153 
154     if (last == -1 || valid != 1)
155     {
156         *error = errorBuffer;
157         return false;
158     }
159 
160     return true;
161 }
162 
toString() const163 const std::string XMLValidationSchema::toString() const
164 {
165     std::ostringstream oss;
166     xmlSchema *schema = getValidationFile < xmlSchema > ();
167 
168     oss << "XML Schema" << std::endl;
169     oss << "name: " << (schema->name ? (const char *)schema->name : "") << std::endl;
170     oss << "target namespace: " << (schema->targetNamespace ? (const char *)schema->targetNamespace : "") << std::endl;
171     oss << "version: " << (schema->version ? (const char *)schema->version : "");
172 
173     return oss.str();
174 }
175 
176 }
177 
178