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 "XMLValidationRelaxNG.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 
XMLValidationRelaxNG(const char * path,std::string * error)33 XMLValidationRelaxNG::XMLValidationRelaxNG(const char *path, std::string * error): XMLValidation()
34 {
35     char *expandedPath = expandPathVariable(const_cast < char *>(path));
36     if (expandedPath)
37     {
38         xmlRelaxNGParserCtxt *pctxt = xmlRelaxNGNewParserCtxt(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 *)xmlRelaxNGParse(pctxt);
49             xmlRelaxNGFreeParserCtxt(pctxt);
50             if (!validationFile)
51             {
52                 errorBuffer.clear();
53                 errorBuffer.append(gettext("Cannot parse the Relax NG grammar"));
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 
67     scope->registerPointers(validationFile, this);
68     id = scope->getVariableId(*this);
69 }
70 
~XMLValidationRelaxNG()71 XMLValidationRelaxNG::~XMLValidationRelaxNG()
72 {
73     scope->unregisterPointer(validationFile);
74     scope->removeId(id);
75     if (validationFile)
76     {
77         xmlRelaxNGFree((xmlRelaxNG *) validationFile);
78         openValidationFiles.remove(this);
79         if (openValidationFiles.size() == 0 && XMLDocument::getOpenDocuments().size() == 0)
80         {
81             resetScope();
82         }
83     }
84 
85     errorBuffer.clear();
86 }
87 
validate(const XMLDocument & doc,std::string * error) const88 bool XMLValidationRelaxNG::validate(const XMLDocument & doc, std::string * error) const
89 {
90     bool ret;
91     xmlRelaxNGValidCtxt *vctxt = xmlRelaxNGNewValidCtxt((xmlRelaxNG *) validationFile);
92 
93     errorBuffer.clear();
94 
95     if (!vctxt)
96     {
97         errorBuffer.append(gettext("Cannot create a validation context"));
98         *error = errorBuffer;
99         return false;
100     }
101 
102     xmlRelaxNGSetValidErrors(vctxt, (xmlRelaxNGValidityErrorFunc) XMLValidation::errorFunction, 0, 0);
103 
104     ret = BOOLtobool(xmlRelaxNGValidateDoc(vctxt, doc.getRealDocument()));
105 
106     xmlRelaxNGSetValidErrors(vctxt, 0, 0, 0);
107     xmlRelaxNGFreeValidCtxt(vctxt);
108 
109     if (ret)
110     {
111         *error = errorBuffer;
112     }
113 
114     return ret == 0;
115 }
116 
validate(xmlTextReader * reader,std::string * error) const117 bool XMLValidationRelaxNG::validate(xmlTextReader * reader, std::string * error) const
118 {
119     int last;
120     int valid;
121 
122     errorBuffer.clear();
123 
124     xmlTextReaderSetErrorHandler(reader, (xmlTextReaderErrorFunc) XMLValidation::errorReaderFunction, 0);
125     xmlTextReaderRelaxNGSetSchema(reader, getValidationFile < xmlRelaxNG > ());
126 
127     while ((last = xmlTextReaderRead(reader)) == 1)
128     {
129         ;
130     }
131     valid = xmlTextReaderIsValid(reader);
132 
133     xmlTextReaderSetErrorHandler(reader, 0, 0);
134     xmlFreeTextReader(reader);
135 
136     if (last == -1 || valid != 1)
137     {
138         *error = errorBuffer;
139         return false;
140     }
141 
142     return true;
143 }
144 
toString() const145 const std::string XMLValidationRelaxNG::toString() const
146 {
147     return std::string("XML Relax NG\nNo public information");
148 }
149 }
150 
151