| OLD | NEW |
| 1 #define IN_LIBEXSLT | 1 #define IN_LIBEXSLT |
| 2 #include "libexslt/libexslt.h" | 2 #include "libexslt/libexslt.h" |
| 3 | 3 |
| 4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__) | 4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__) |
| 5 #include <win32config.h> | 5 #include <win32config.h> |
| 6 #else | 6 #else |
| 7 #include "config.h" | 7 #include "config.h" |
| 8 #endif | 8 #endif |
| 9 | 9 |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 struct _exsltFuncFunctionData { | 28 struct _exsltFuncFunctionData { |
| 29 int nargs; /* number of arguments to the function */ | 29 int nargs; /* number of arguments to the function */ |
| 30 xmlNodePtr content; /* the func:fuction template content */ | 30 xmlNodePtr content; /* the func:fuction template content */ |
| 31 }; | 31 }; |
| 32 | 32 |
| 33 typedef struct _exsltFuncData exsltFuncData; | 33 typedef struct _exsltFuncData exsltFuncData; |
| 34 struct _exsltFuncData { | 34 struct _exsltFuncData { |
| 35 xmlHashTablePtr funcs; /* pointer to the stylesheet module data */ | 35 xmlHashTablePtr funcs; /* pointer to the stylesheet module data */ |
| 36 xmlXPathObjectPtr result; /* returned by func:result */ | 36 xmlXPathObjectPtr result; /* returned by func:result */ |
| 37 int error; /* did an error occur? */ | 37 int error; /* did an error occur? */ |
| 38 xmlDocPtr RVT; /* result tree fragment */ | |
| 39 }; | 38 }; |
| 40 | 39 |
| 41 typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp; | 40 typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp; |
| 42 struct _exsltFuncResultPreComp { | 41 struct _exsltFuncResultPreComp { |
| 43 xsltElemPreComp comp; | 42 xsltElemPreComp comp; |
| 44 xmlXPathCompExprPtr select; | 43 xmlXPathCompExprPtr select; |
| 45 xmlNsPtr *nsList; | 44 xmlNsPtr *nsList; |
| 46 int nsNr; | 45 int nsNr; |
| 47 }; | 46 }; |
| 48 | 47 |
| 49 /* Used for callback function in exsltInitFunc */ | 48 /* Used for callback function in exsltInitFunc */ |
| 50 typedef struct _exsltFuncImportRegData exsltFuncImportRegData; | 49 typedef struct _exsltFuncImportRegData exsltFuncImportRegData; |
| 51 struct _exsltFuncImportRegData { | 50 struct _exsltFuncImportRegData { |
| 52 xsltTransformContextPtr ctxt; | 51 xsltTransformContextPtr ctxt; |
| 53 xmlHashTablePtr hash; | 52 xmlHashTablePtr hash; |
| 54 }; | 53 }; |
| 55 | 54 |
| 56 static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, | 55 static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, |
| 57 int nargs); | 56 int nargs); |
| 58 static exsltFuncFunctionData *exsltFuncNewFunctionData(void); | 57 static exsltFuncFunctionData *exsltFuncNewFunctionData(void); |
| 59 | 58 |
| 60 #define MAX_FUNC_RECURSION 1000 | |
| 61 | |
| 62 /*static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";*/ | 59 /*static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";*/ |
| 63 | 60 |
| 64 /** | 61 /** |
| 65 * exsltFuncRegisterFunc: | 62 * exsltFuncRegisterFunc: |
| 66 * @func: the #exsltFuncFunctionData for the function | 63 * @func: the #exsltFuncFunctionData for the function |
| 67 * @ctxt: an XSLT transformation context | 64 * @ctxt: an XSLT transformation context |
| 68 * @URI: the function namespace URI | 65 * @URI: the function namespace URI |
| 69 * @name: the function name | 66 * @name: the function name |
| 70 * | 67 * |
| 71 * Registers a function declared by a func:function element | 68 * Registers a function declared by a func:function element |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 paramNode = func->content->prev; | 323 paramNode = func->content->prev; |
| 327 } | 324 } |
| 328 else | 325 else |
| 329 paramNode = NULL; | 326 paramNode = NULL; |
| 330 if ((paramNode == NULL) && (func->nargs != 0)) { | 327 if ((paramNode == NULL) && (func->nargs != 0)) { |
| 331 xsltGenericError(xsltGenericErrorContext, | 328 xsltGenericError(xsltGenericErrorContext, |
| 332 "exsltFuncFunctionFunction: nargs != 0 and " | 329 "exsltFuncFunctionFunction: nargs != 0 and " |
| 333 "param == NULL\n"); | 330 "param == NULL\n"); |
| 334 return; | 331 return; |
| 335 } | 332 } |
| 336 if (tctxt->funcLevel > MAX_FUNC_RECURSION) { | |
| 337 xsltGenericError(xsltGenericErrorContext, | |
| 338 "{%s}%s: detected a recursion\n", | |
| 339 ctxt->context->functionURI, ctxt->context->function); | |
| 340 ctxt->error = XPATH_MEMORY_ERROR; | |
| 341 return; | |
| 342 } | |
| 343 tctxt->funcLevel++; | |
| 344 | 333 |
| 345 /* | 334 /* |
| 346 * We have a problem with the evaluation of function parameters. | 335 * We have a problem with the evaluation of function parameters. |
| 347 * The original library code did not evaluate XPath expressions until | 336 * The original library code did not evaluate XPath expressions until |
| 348 * the last moment. After version 1.1.17 of the libxslt, the logic | 337 * the last moment. After version 1.1.17 of the libxslt, the logic |
| 349 * of other parts of the library was changed, and the evaluation of | 338 * of other parts of the library was changed, and the evaluation of |
| 350 * XPath expressions within parameters now takes place as soon as the | 339 * XPath expressions within parameters now takes place as soon as the |
| 351 * parameter is parsed/evaluated (xsltParseStylesheetCallerParam). | 340 * parameter is parsed/evaluated (xsltParseStylesheetCallerParam). |
| 352 * This means that the parameters need to be evaluated in lexical | 341 * This means that the parameters need to be evaluated in lexical |
| 353 * order (since a variable is "in scope" as soon as it is declared). | 342 * order (since a variable is "in scope" as soon as it is declared). |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 tctxt->insert = fake; | 406 tctxt->insert = fake; |
| 418 xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt), | 407 xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt), |
| 419 func->content, NULL, NULL); | 408 func->content, NULL, NULL); |
| 420 xsltLocalVariablePop(tctxt, tctxt->varsBase, -2); | 409 xsltLocalVariablePop(tctxt, tctxt->varsBase, -2); |
| 421 tctxt->insert = oldInsert; | 410 tctxt->insert = oldInsert; |
| 422 tctxt->varsBase = oldBase; /* restore original scope */ | 411 tctxt->varsBase = oldBase; /* restore original scope */ |
| 423 if (params != NULL) | 412 if (params != NULL) |
| 424 xsltFreeStackElemList(params); | 413 xsltFreeStackElemList(params); |
| 425 | 414 |
| 426 if (data->error != 0) | 415 if (data->error != 0) |
| 427 » goto error; | 416 » return; |
| 428 | 417 |
| 429 if (data->result != NULL) { | 418 if (data->result != NULL) { |
| 430 ret = data->result; | 419 ret = data->result; |
| 420 /* |
| 421 * IMPORTANT: This enables previously tree fragments marked as |
| 422 * being results of a function, to be garbage-collected after |
| 423 * the calling process exits. |
| 424 */ |
| 425 xsltFlagRVTs(tctxt, ret, XSLT_RVT_LOCAL); |
| 431 } else | 426 } else |
| 432 ret = xmlXPathNewCString(""); | 427 ret = xmlXPathNewCString(""); |
| 433 | 428 |
| 434 data->result = oldResult; | 429 data->result = oldResult; |
| 435 | 430 |
| 436 /* | 431 /* |
| 437 * It is an error if the instantiation of the template results in | 432 * It is an error if the instantiation of the template results in |
| 438 * the generation of result nodes. | 433 * the generation of result nodes. |
| 439 */ | 434 */ |
| 440 if (fake->children != NULL) { | 435 if (fake->children != NULL) { |
| 441 #ifdef LIBXML_DEBUG_ENABLED | 436 #ifdef LIBXML_DEBUG_ENABLED |
| 442 xmlDebugDumpNode (stderr, fake, 1); | 437 xmlDebugDumpNode (stderr, fake, 1); |
| 443 #endif | 438 #endif |
| 444 xsltGenericError(xsltGenericErrorContext, | 439 xsltGenericError(xsltGenericErrorContext, |
| 445 "{%s}%s: cannot write to result tree while " | 440 "{%s}%s: cannot write to result tree while " |
| 446 "executing a function\n", | 441 "executing a function\n", |
| 447 ctxt->context->functionURI, ctxt->context->function); | 442 ctxt->context->functionURI, ctxt->context->function); |
| 448 xmlFreeNode(fake); | 443 xmlFreeNode(fake); |
| 449 » goto error; | 444 » return; |
| 450 } | 445 } |
| 451 xmlFreeNode(fake); | 446 xmlFreeNode(fake); |
| 452 valuePush(ctxt, ret); | 447 valuePush(ctxt, ret); |
| 453 | |
| 454 error: | |
| 455 /* | |
| 456 * IMPORTANT: This enables previously tree fragments marked as | |
| 457 * being results of a function, to be garbage-collected after | |
| 458 * the calling process exits. | |
| 459 */ | |
| 460 xsltExtensionInstructionResultFinalize(tctxt); | |
| 461 tctxt->funcLevel--; | |
| 462 } | 448 } |
| 463 | 449 |
| 464 | 450 |
| 465 static void | 451 static void |
| 466 exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) { | 452 exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) { |
| 467 xmlChar *name, *prefix; | 453 xmlChar *name, *prefix; |
| 468 xmlNsPtr ns; | 454 xmlNsPtr ns; |
| 469 xmlHashTablePtr data; | 455 xmlHashTablePtr data; |
| 470 exsltFuncFunctionData *func; | 456 exsltFuncFunctionData *func; |
| 471 | 457 |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 | 703 |
| 718 if (ret == NULL) { | 704 if (ret == NULL) { |
| 719 xsltGenericError(xsltGenericErrorContext, | 705 xsltGenericError(xsltGenericErrorContext, |
| 720 "exsltFuncResultElem: ret == NULL\n"); | 706 "exsltFuncResultElem: ret == NULL\n"); |
| 721 return; | 707 return; |
| 722 } | 708 } |
| 723 /* | 709 /* |
| 724 * Mark it as a function result in order to avoid garbage | 710 * Mark it as a function result in order to avoid garbage |
| 725 * collecting of tree fragments before the function exits. | 711 * collecting of tree fragments before the function exits. |
| 726 */ | 712 */ |
| 727 » xsltExtensionInstructionResultRegister(ctxt, ret); | 713 » xsltFlagRVTs(ctxt, ret, XSLT_RVT_FUNC_RESULT); |
| 728 } else if (inst->children != NULL) { | 714 } else if (inst->children != NULL) { |
| 729 /* If the func:result element does not have a select attribute | 715 /* If the func:result element does not have a select attribute |
| 730 * and has non-empty content (i.e. the func:result element has | 716 * and has non-empty content (i.e. the func:result element has |
| 731 * one or more child nodes), then the content of the | 717 * one or more child nodes), then the content of the |
| 732 * func:result element specifies the value. | 718 * func:result element specifies the value. |
| 733 */ | 719 */ |
| 734 xmlNodePtr oldInsert; | 720 xmlNodePtr oldInsert; |
| 735 xmlDocPtr container; | 721 xmlDocPtr container; |
| 736 | 722 |
| 737 container = xsltCreateRVT(ctxt); | 723 container = xsltCreateRVT(ctxt); |
| 738 if (container == NULL) { | 724 if (container == NULL) { |
| 739 xsltGenericError(xsltGenericErrorContext, | 725 xsltGenericError(xsltGenericErrorContext, |
| 740 "exsltFuncResultElem: out of memory\n"); | 726 "exsltFuncResultElem: out of memory\n"); |
| 741 data->error = 1; | 727 data->error = 1; |
| 742 return; | 728 return; |
| 743 } | 729 } |
| 744 » xsltRegisterLocalRVT(ctxt, container); | 730 /* Mark as function result. */ |
| 731 container->psvi = XSLT_RVT_FUNC_RESULT; |
| 745 | 732 |
| 746 oldInsert = ctxt->insert; | 733 oldInsert = ctxt->insert; |
| 747 ctxt->insert = (xmlNodePtr) container; | 734 ctxt->insert = (xmlNodePtr) container; |
| 748 xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node, | 735 xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node, |
| 749 inst->children, NULL, NULL); | 736 inst->children, NULL, NULL); |
| 750 ctxt->insert = oldInsert; | 737 ctxt->insert = oldInsert; |
| 751 | 738 |
| 752 ret = xmlXPathNewValueTree((xmlNodePtr) container); | 739 ret = xmlXPathNewValueTree((xmlNodePtr) container); |
| 753 if (ret == NULL) { | 740 if (ret == NULL) { |
| 754 xsltGenericError(xsltGenericErrorContext, | 741 xsltGenericError(xsltGenericErrorContext, |
| 755 "exsltFuncResultElem: ret == NULL\n"); | 742 "exsltFuncResultElem: ret == NULL\n"); |
| 756 data->error = 1; | 743 data->error = 1; |
| 757 } else { | 744 } else { |
| 758 ret->boolval = 0; /* Freeing is not handled there anymore */ | 745 ret->boolval = 0; /* Freeing is not handled there anymore */ |
| 759 /* | |
| 760 * Mark it as a function result in order to avoid garbage | |
| 761 * collecting of tree fragments before the function exits. | |
| 762 */ | |
| 763 xsltExtensionInstructionResultRegister(ctxt, ret); | |
| 764 } | 746 } |
| 765 } else { | 747 } else { |
| 766 /* If the func:result element has empty content and does not | 748 /* If the func:result element has empty content and does not |
| 767 * have a select attribute, then the returned value is an | 749 * have a select attribute, then the returned value is an |
| 768 * empty string. | 750 * empty string. |
| 769 */ | 751 */ |
| 770 ret = xmlXPathNewCString(""); | 752 ret = xmlXPathNewCString(""); |
| 771 } | 753 } |
| 772 data->result = ret; | 754 data->result = ret; |
| 773 } | 755 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 786 (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown); | 768 (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown); |
| 787 | 769 |
| 788 xsltRegisterExtModuleTopLevel ((const xmlChar *) "function", | 770 xsltRegisterExtModuleTopLevel ((const xmlChar *) "function", |
| 789 EXSLT_FUNCTIONS_NAMESPACE, | 771 EXSLT_FUNCTIONS_NAMESPACE, |
| 790 exsltFuncFunctionComp); | 772 exsltFuncFunctionComp); |
| 791 xsltRegisterExtModuleElement ((const xmlChar *) "result", | 773 xsltRegisterExtModuleElement ((const xmlChar *) "result", |
| 792 EXSLT_FUNCTIONS_NAMESPACE, | 774 EXSLT_FUNCTIONS_NAMESPACE, |
| 793 (xsltPreComputeFunction)exsltFuncResultComp, | 775 (xsltPreComputeFunction)exsltFuncResultComp, |
| 794 (xsltTransformFunction) exsltFuncResultElem); | 776 (xsltTransformFunction) exsltFuncResultElem); |
| 795 } | 777 } |
| OLD | NEW |