Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 368 lines (326 sloc) 10.331 kb
6e2fba5 @fizx inner-xml
authored
1 #include <stdbool.h>
17601e4 html-document
Kyle Maxwell authored
2 #include <libxml/xpath.h>
3 #include <libxml/xpathInternals.h>
4 #include <libxml/parserInternals.h>
5 #include <libxml/uri.h>
6 #include <libxml/xpointer.h>
7 #include <libxml/xinclude.h>
8 #include <libxml/HTMLparser.h>
9 #include <libxml/HTMLtree.h>
10 #include <libxslt/xslt.h>
11 #include <libxslt/imports.h>
12 #include <libxslt/xsltInternals.h>
13 #include <libxslt/security.h>
14 #include <libxslt/xsltutils.h>
15 #include <libxslt/transform.h>
16 #include <libxslt/extensions.h>
17 #include <libxslt/documents.h>
18 #include "functions.h"
19
20
712f3a6 tentative rename, etc
Kyle Maxwell authored
21 void parsley_register_all(){
1b1fbae refactor works, still have quote error
Kyle Maxwell authored
22 xsltRegisterExtModuleFunction ((const xmlChar *) "html-document", "http://parselets.com/stdlib",
17601e4 html-document
Kyle Maxwell authored
23 xsltHtmlDocumentFunction);
c8f1e9e outer-xml failing test (failing) [0.589708]
Kyle Maxwell authored
24 xsltRegisterExtModuleFunction ((const xmlChar *) "outer-xml", "http://parselets.com/stdlib",
25 xsltOuterXmlFunction);
6e2fba5 @fizx inner-xml
authored
26 xsltRegisterExtModuleFunction ((const xmlChar *) "inner-xml", "http://parselets.com/stdlib",
27 xsltInnerXmlFunction);
28 }
29
30 static void
31 xsltStarXMLFunction(xmlXPathParserContextPtr ctxt, int nargs, bool is_inner) {
32 if (nargs != 1) {
33 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
34 "outer-xml() : invalid number of args %d\n",
35 nargs);
36 ctxt->error = XPATH_INVALID_ARITY;
37 return;
38 }
39 if (ctxt->value->type == XPATH_NODESET) {
40 xmlXPathObjectPtr obj, newobj;
41
42 obj = valuePop(ctxt);
43
44 xmlBufferPtr buf = xmlBufferCreate();
45 int n = obj->nodesetval->nodeNr;
46 for(int i = 0; i < n; i++) {
47 xmlNodePtr node = obj->nodesetval->nodeTab[i];
48 xmlDocPtr doc = node->doc;
49 if(is_inner){
50 xmlNodePtr child = node->children;
51 while(child != NULL) {
52 xmlNodeDump(buf, doc, child, 0, 0);
53 child = child->next;
54 }
55 } else {
56 xmlNodeDump(buf, doc, node, 0, 0);
57 }
58 }
59 newobj = xmlXPathNewCString(xmlBufferContent(buf));
60 xmlBufferFree(buf);
61 valuePush(ctxt, newobj);
62 }
63 }
64
65 void
66 xsltInnerXmlFunction(xmlXPathParserContextPtr ctxt, int nargs) {
67 xsltStarXMLFunction(ctxt, nargs, true);
c8f1e9e outer-xml failing test (failing) [0.589708]
Kyle Maxwell authored
68 }
69
70 void
71 xsltOuterXmlFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6e2fba5 @fizx inner-xml
authored
72 xsltStarXMLFunction(ctxt, nargs, false);
17601e4 html-document
Kyle Maxwell authored
73 }
74
75 void
76 xsltHtmlDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
77 {
78 xmlXPathObjectPtr obj, obj2 = NULL;
79 xmlChar *base = NULL, *URI;
80
81
82 if ((nargs < 1) || (nargs > 2)) {
83 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
84 "document() : invalid number of args %d\n",
85 nargs);
86 ctxt->error = XPATH_INVALID_ARITY;
87 return;
88 }
89 if (ctxt->value == NULL) {
90 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
91 "document() : invalid arg value\n");
92 ctxt->error = XPATH_INVALID_TYPE;
93 return;
94 }
95
96 if (nargs == 2) {
97 if (ctxt->value->type != XPATH_NODESET) {
98 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
99 "document() : invalid arg expecting a nodeset\n");
100 ctxt->error = XPATH_INVALID_TYPE;
101 return;
102 }
103
104 obj2 = valuePop(ctxt);
105 }
106
107 if (ctxt->value->type == XPATH_NODESET) {
108 int i;
109 xmlXPathObjectPtr newobj, ret;
110
111 obj = valuePop(ctxt);
112 ret = xmlXPathNewNodeSet(NULL);
113
114 if (obj->nodesetval) {
115 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
116 valuePush(ctxt,
117 xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
118 xmlXPathStringFunction(ctxt, 1);
119 if (nargs == 2) {
120 valuePush(ctxt, xmlXPathObjectCopy(obj2));
121 } else {
122 valuePush(ctxt,
123 xmlXPathNewNodeSet(obj->nodesetval->
124 nodeTab[i]));
125 }
126 xsltHtmlDocumentFunction(ctxt, 2);
127 newobj = valuePop(ctxt);
128 ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
129 newobj->nodesetval);
130 xmlXPathFreeObject(newobj);
131 }
132 }
133
134 xmlXPathFreeObject(obj);
135 if (obj2 != NULL)
136 xmlXPathFreeObject(obj2);
137 valuePush(ctxt, ret);
138 return;
139 }
140 /*
141 * Make sure it's converted to a string
142 */
143 xmlXPathStringFunction(ctxt, 1);
144 if (ctxt->value->type != XPATH_STRING) {
145 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
146 "document() : invalid arg expecting a string\n");
147 ctxt->error = XPATH_INVALID_TYPE;
148 if (obj2 != NULL)
149 xmlXPathFreeObject(obj2);
150 return;
151 }
152 obj = valuePop(ctxt);
153 if (obj->stringval == NULL) {
154 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
155 } else {
156 if ((obj2 != NULL) && (obj2->nodesetval != NULL) &&
157 (obj2->nodesetval->nodeNr > 0) &&
158 IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) {
159 xmlNodePtr target;
160
161 target = obj2->nodesetval->nodeTab[0];
162 if ((target->type == XML_ATTRIBUTE_NODE) ||
163 (target->type == XML_PI_NODE)) {
164 target = ((xmlAttrPtr) target)->parent;
165 }
166 base = xmlNodeGetBase(target->doc, target);
167 } else {
168 xsltTransformContextPtr tctxt;
169
170 tctxt = xsltXPathGetTransformContext(ctxt);
171 if ((tctxt != NULL) && (tctxt->inst != NULL)) {
172 base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst);
173 } else if ((tctxt != NULL) && (tctxt->style != NULL) &&
174 (tctxt->style->doc != NULL)) {
175 base = xmlNodeGetBase(tctxt->style->doc,
176 (xmlNodePtr) tctxt->style->doc);
177 }
178 }
179 URI = xmlBuildURI(obj->stringval, base);
180 if (base != NULL)
181 xmlFree(base);
182 if (URI == NULL) {
183 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
184 } else {
185 xsltHtmlDocumentFunctionLoadDocument( ctxt, URI );
186 xmlFree(URI);
187 }
188 }
189 xmlXPathFreeObject(obj);
190 if (obj2 != NULL)
191 xmlXPathFreeObject(obj2);
192 }
193
194 static void
195 xsltHtmlDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
196 {
197 xsltTransformContextPtr tctxt;
198 xmlURIPtr uri;
199 xmlChar *fragment;
200 xsltDocumentPtr idoc; /* document info */
201 xmlDocPtr doc;
202 xmlXPathContextPtr xptrctxt = NULL;
203 xmlXPathObjectPtr resObj = NULL;
204
205 tctxt = xsltXPathGetTransformContext(ctxt);
206 if (tctxt == NULL) {
207 xsltTransformError(NULL, NULL, NULL,
208 "document() : internal error tctxt == NULL\n");
209 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
210 return;
211 }
212
213 uri = xmlParseURI((const char *) URI);
214 if (uri == NULL) {
215 xsltTransformError(tctxt, NULL, NULL,
216 "document() : failed to parse URI\n");
217 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
218 return;
219 }
220
221 /*
222 * check for and remove fragment identifier
223 */
224 fragment = (xmlChar *)uri->fragment;
225 if (fragment != NULL) {
226 xmlChar *newURI;
227 uri->fragment = NULL;
228 newURI = xmlSaveUri(uri);
229 idoc = xsltLoadHtmlDocument(tctxt, newURI);
230 xmlFree(newURI);
231 } else
232 idoc = xsltLoadHtmlDocument(tctxt, URI);
233 xmlFreeURI(uri);
234
235 if (idoc == NULL) {
236 if ((URI == NULL) ||
237 (URI[0] == '#') ||
238 ((tctxt->style->doc != NULL) &&
239 (xmlStrEqual(tctxt->style->doc->URL, URI))))
240 {
241 /*
242 * This selects the stylesheet's doc itself.
243 */
244 doc = tctxt->style->doc;
245 } else {
246 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
247
248 if (fragment != NULL)
249 xmlFree(fragment);
250
251 return;
252 }
253 } else
254 doc = idoc->doc;
255
256 if (fragment == NULL) {
257 valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));
258 return;
259 }
260
261 /* use XPointer of HTML location for fragment ID */
262 #ifdef LIBXML_XPTR_ENABLED
263 xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
264 if (xptrctxt == NULL) {
265 xsltTransformError(tctxt, NULL, NULL,
266 "document() : internal error xptrctxt == NULL\n");
267 goto out_fragment;
268 }
269
270 resObj = xmlXPtrEval(fragment, xptrctxt);
271 xmlXPathFreeContext(xptrctxt);
272 #endif
273 xmlFree(fragment);
274
275 if (resObj == NULL)
276 goto out_fragment;
277
278 switch (resObj->type) {
279 case XPATH_NODESET:
280 break;
281 case XPATH_UNDEFINED:
282 case XPATH_BOOLEAN:
283 case XPATH_NUMBER:
284 case XPATH_STRING:
285 case XPATH_POINT:
286 case XPATH_USERS:
287 case XPATH_XSLT_TREE:
288 case XPATH_RANGE:
289 case XPATH_LOCATIONSET:
290 xsltTransformError(tctxt, NULL, NULL,
291 "document() : XPointer does not select a node set: #%s\n",
292 fragment);
293 goto out_object;
294 }
295
296 valuePush(ctxt, resObj);
297 return;
298
299 out_object:
300 xmlXPathFreeObject(resObj);
301
302 out_fragment:
303 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
304 }
305
306 xsltDocumentPtr
307 xsltLoadHtmlDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
308 xsltDocumentPtr ret;
309 xmlDocPtr doc;
310
311 if ((ctxt == NULL) || (URI == NULL))
312 return(NULL);
313
314 /*
315 * Security framework check
316 */
317 if (ctxt->sec != NULL) {
318 int res;
319
320 res = xsltCheckRead(ctxt->sec, ctxt, URI);
321 if (res == 0) {
322 xsltTransformError(ctxt, NULL, NULL,
323 "xsltLoadHtmlDocument: read rights for %s denied\n",
324 URI);
325 return(NULL);
326 }
327 }
328
329 /*
330 * Walk the context list to find the document if preparsed
331 */
332 ret = ctxt->docList;
333 while (ret != NULL) {
334 if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
335 (xmlStrEqual(ret->doc->URL, URI)))
336 return(ret);
337 ret = ret->next;
338 }
339
87d5ae6 ignore malformed html, handle funny encodings
Kyle Maxwell authored
340 doc = htmlReadFile(URI, NULL, ctxt->parserOptions | HTML_PARSE_RECOVER | HTML_PARSE_NOERROR |HTML_PARSE_NOWARNING);
17601e4 html-document
Kyle Maxwell authored
341
342 if (doc == NULL)
343 return(NULL);
344
345 if (ctxt->xinclude != 0) {
346 #ifdef LIBXML_XINCLUDE_ENABLED
347 #if LIBXML_VERSION >= 20603
348 xmlXIncludeProcessFlags(doc, ctxt->parserOptions);
349 #else
350 xmlXIncludeProcess(doc);
351 #endif
352 #else
353 xsltTransformError(ctxt, NULL, NULL,
354 "xsltLoadHtmlDocument(%s) : XInclude processing not compiled in\n",
355 URI);
356 #endif
357 }
358 /*
359 * Apply white-space stripping if asked for
360 */
361 if (xsltNeedElemSpaceHandling(ctxt))
362 xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));
363 if (ctxt->debugStatus == XSLT_DEBUG_NONE)
364 xmlXPathOrderDocElems(doc);
365
366 ret = xsltNewDocument(ctxt, doc);
367 return(ret);
df15251 remote html works, some function aliases work
Kyle Maxwell authored
368 }
Something went wrong with that request. Please try again.