static void extBitCompare (xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *res1, *res2; xmlXPathObjectPtr xop; int width1, width2, off1, off2, rc, delta; if (nargs != 2) { xmlXPathSetArityError(ctxt); return; } /* Pop args in reverse order */ xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; res2 = extBitStringVal(ctxt, xop); if (res2 == NULL) return; xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; res1 = extBitStringVal(ctxt, xop); if (res1 == NULL) return; width1 = xmlStrlen(res1); width2 = xmlStrlen(res2); delta = width1 - width2; rc = 0; off1 = off2 = 0; if (delta < 0) { for ( ; delta < 0; delta++, off2++) { if (res2[off2] != '0') { rc = -1; goto done; } } } else if (delta > 0) { for ( ; delta > 0; delta--, off1++) { if (res1[off1] != '0') { rc = 1; goto done; } } } rc = xmlStrcmp(res1 + off1, res2 + off2); done: xmlFree(res1); xmlFree(res2); xmlXPathReturnNumber(ctxt, rc); }
/** * xsltFormatNumberFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the format-number() XSLT function * string format-number(number, string, string?) */ void xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr numberObj = NULL; xmlXPathObjectPtr formatObj = NULL; xmlXPathObjectPtr decimalObj = NULL; xsltStylesheetPtr sheet; xsltDecimalFormatPtr formatValues; xmlChar *result; xsltTransformContextPtr tctxt; tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) return; sheet = tctxt->style; if (sheet == NULL) return; formatValues = sheet->decimalFormat; switch (nargs) { case 3: CAST_TO_STRING; decimalObj = valuePop(ctxt); formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval); if (formatValues == NULL) { xsltTransformError(tctxt, NULL, NULL, "format-number() : undeclared decimal format '%s'\n", decimalObj->stringval); } /* Intentional fall-through */ case 2: CAST_TO_STRING; formatObj = valuePop(ctxt); CAST_TO_NUMBER; numberObj = valuePop(ctxt); break; default: XP_ERROR(XPATH_INVALID_ARITY); } if (formatValues != NULL) { if (xsltFormatNumberConversion(formatValues, formatObj->stringval, numberObj->floatval, &result) == XPATH_EXPRESSION_OK) { valuePush(ctxt, xmlXPathNewString(result)); xmlFree(result); } } xmlXPathFreeObject(numberObj); xmlXPathFreeObject(formatObj); xmlXPathFreeObject(decimalObj); }
static void gda_xslt_getnodeset_function (xmlXPathParserContextPtr ctxt, int nargs) { GdaXsltIntCont *data; xsltTransformContextPtr tctxt; xmlXPathObjectPtr setname, nodeset; GdaXsltExCont *execc; if (nargs != 1) { xsltGenericError (xsltGenericErrorContext, "gda_xslt_getnodeset_function: invalid number of arguments\n"); return; } tctxt = xsltXPathGetTransformContext (ctxt); if (tctxt == NULL) { xsltGenericError (xsltGenericErrorContext, "sqlxslt: failed to get the transformation context\n"); return; } execc = (GdaXsltExCont *) tctxt->_private; data = (GdaXsltIntCont *) xsltGetExtData (tctxt, BAD_CAST GDA_XSLT_EXTENSION_URI); if (data == NULL) { xsltGenericError (xsltGenericErrorContext, "sqlxslt: failed to get module data\n"); return; } setname = valuePop (ctxt); if (setname == NULL) { xsltGenericError (xsltGenericErrorContext, "sqlxslt: internal error\n"); return; } if (setname->type != XPATH_STRING) { valuePush (ctxt, setname); xmlXPathStringFunction (ctxt, 1); setname = valuePop (ctxt); if (setname == NULL) { xsltGenericError (xsltGenericErrorContext, "sqlxslt: internal error\n"); return; } } nodeset = _gda_xslt_bk_fun_getnodeset (setname->stringval, execc, data); if (nodeset == NULL) { xsltGenericError (xsltGenericErrorContext, "exsltDynMapFunctoin: ret == NULL\n"); return; } valuePush (ctxt, nodeset); }
void RXSLT_callNamedFunction(const char *name, xmlXPathParserContextPtr ctxt, int nargs, int leaveAsRObject) { USER_OBJECT_ e, ans; // xmlXPathObjectPtr obj; int errorOccurred; int i, j; #if 0 PROTECT(e = allocVector(LANGSXP, 2)); SETCAR(e, Rf_install((char *) name)); SETCAR(CDR(e), tmp = NEW_CHARACTER(1)); obj = valuePop(ctxt); SET_STRING_ELT(tmp, 0, COPY_TO_USER_STRING(xmlXPathCastToString(obj))); #else PROTECT(e = allocVector(LANGSXP, nargs+1)); SETCAR(e, Rf_install((char *) name)); #if 0 for(i = 0; i < nargs; i++) { ans = CDR(e); for(j = nargs-1; j > i ; j--) { ans = CDR(ans); } SETCAR(ans, tmp = NEW_CHARACTER(1)); obj = valuePop(ctxt); SET_STRING_ELT(tmp, 0, COPY_TO_USER_STRING(xmlXPathCastToString(obj))); } #else for(i = 0; i < nargs; i++) { ans = CDR(e); for(j = nargs-1; j > i ; j--) { ans = CDR(ans); } SETCAR(ans, convertFromXPath(ctxt, valuePop(ctxt))); } #endif #endif ans = R_tryEval(e, R_GlobalEnv, &errorOccurred); if(errorOccurred) { RXSLT_Error(ctxt, "error in call to R function"); } else { PROTECT(ans); valuePush(ctxt, convertToXPath(ctxt, ans)); UNPROTECT(1); } UNPROTECT(1); return; }
static void extBitOperation (xmlXPathParserContextPtr ctxt, int nargs, slax_bit_callback_t func, const char *name) { xmlChar *lv, *rv, *res; int llen, rlen, width, i; xmlXPathObjectPtr xop; if (nargs != 2) { xmlXPathSetArityError(ctxt); return; } /* Pop args in reverse order */ xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; rv = extBitStringVal(ctxt, xop); if (rv == NULL) return; xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; lv = extBitStringVal(ctxt, xop); if (lv == NULL) { xmlFree(rv); return; } llen = xmlStrlen(lv); rlen = xmlStrlen(rv); width = (llen > rlen) ? llen : rlen; res = xmlMalloc(width + 1); if (res) { res[width] = '\0'; for (i = 0; i < width; i++) { xmlChar lb = (i >= width - llen) ? lv[i - (width - llen)] : '0'; xmlChar rb = (i >= width - rlen) ? rv[i - (width - rlen)] : '0'; res[i] = (*func)(lb, rb); } } slaxLog("bit:%s:: %d [%s] -> [%s] == [%s]", name, width, lv, rv, res); xmlFree(lv); xmlFree(rv); xmlXPathReturnString(ctxt, res); }
/** * xsltUnparsedEntityURIFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the unparsed-entity-uri() XSLT function * string unparsed-entity-uri(string) */ void xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){ xmlXPathObjectPtr obj; xmlChar *str; if ((nargs != 1) || (ctxt->value == NULL)) { xsltGenericError(xsltGenericErrorContext, "unparsed-entity-uri() : expects one string arg\n"); ctxt->error = XPATH_INVALID_ARITY; return; } obj = valuePop(ctxt); if (obj->type != XPATH_STRING) { obj = xmlXPathConvertString(obj); } str = obj->stringval; if (str == NULL) { valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); } else { xmlEntityPtr entity; entity = xmlGetDocEntity(ctxt->context->doc, str); if (entity == NULL) { valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); } else { if (entity->URI != NULL) valuePush(ctxt, xmlXPathNewString(entity->URI)); else valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); } } xmlXPathFreeObject(obj); }
static void extBitNot (xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *res; int width, i; xmlXPathObjectPtr xop; if (nargs != 1) { xmlXPathSetArityError(ctxt); return; } /* Pop args in reverse order */ xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; res = extBitStringVal(ctxt, xop); if (res == NULL) return; width = xmlStrlen(res); for (i = 0; i < width; i++) { xmlChar lb = res[i]; res[i] = (lb == '0') ? '1' : '0'; } xmlXPathReturnString(ctxt, res); }
static void extBitToInt (xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *res; xmlXPathObjectPtr xop; unsigned long long val; int i; if (nargs != 1) { xmlXPathSetArityError(ctxt); return; } xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; res = extBitStringVal(ctxt, xop); if (res == NULL) return; for (i = 0, val = 0; i <= 64 && res[i]; i++) { val <<= 1; if (res[i] == '1') val += 1; } if (i > 64) xmlXPathReturnNumber(ctxt, (double) -1); else xmlXPathReturnNumber(ctxt, (double) val); }
/** * xsltElementAvailableFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the element-available() XSLT function * boolean element-available(string) */ void xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){ xmlXPathObjectPtr obj; xmlChar *prefix, *name; const xmlChar *nsURI = NULL; xsltTransformContextPtr tctxt; if (nargs != 1) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "element-available() : expects one string arg\n"); ctxt->error = XPATH_INVALID_ARITY; return; } xmlXPathStringFunction(ctxt, 1); if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "element-available() : invalid arg expecting a string\n"); ctxt->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctxt); tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "element-available() : internal error tctxt == NULL\n"); xmlXPathFreeObject(obj); valuePush(ctxt, xmlXPathNewBoolean(0)); return; } name = xmlSplitQName2(obj->stringval, &prefix); if (name == NULL) { xmlNsPtr ns; name = xmlStrdup(obj->stringval); ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL); if (ns != NULL) nsURI = xmlStrdup(ns->href); } else { nsURI = xmlXPathNsLookup(ctxt->context, prefix); if (nsURI == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "element-available() : prefix %s is not bound\n", prefix); } } if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) { valuePush(ctxt, xmlXPathNewBoolean(1)); } else { valuePush(ctxt, xmlXPathNewBoolean(0)); } xmlXPathFreeObject(obj); if (name != NULL) xmlFree(name); if (prefix != NULL) xmlFree(prefix); }
/** * @arg str the XPath expression * @arg ctxt the XPath context * @arg pctxt pointer to a XPath Parser context pointer * * Evaluate the XPath expression in the given context. The XPath Parser * context is saved in pctxt, so that it can be accessed from another thread. * Especially the error state is interesting, since it can be used to stop a * never ending evaluation. * * Taken from xpath.c in libxml2-2.6.16. * * @return the xmlXPathObjectPtr resulting from the evaluation or NULL. * The caller has to free the object. */ xmlXPathObjectPtr my_xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt, xmlXPathParserContextPtr *pctxt) { xmlXPathObjectPtr res, tmp; int stack = 0; xmlXPathInit(); // it is nice that gcc gives no warning anymore, // but the bad thing is that *pctxt normally is still NULL at this point CHECK_CONTEXT(ctxt,*pctxt) g_mutex_lock(find_nodeset_pcontext_mutex); //g_printerr("Allocating parser context\n"); *pctxt = xmlXPathNewParserContext(str, ctxt); g_mutex_unlock(find_nodeset_pcontext_mutex); xmlXPathEvalExpr(*pctxt); if (*(*pctxt)->cur != 0) { xmlXPatherror(*pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR); res = NULL; } else { res = valuePop(*pctxt); } do { tmp = valuePop(*pctxt); if (tmp != NULL) { xmlXPathFreeObject(tmp); stack++; } } while (tmp != NULL); if ((stack != 0) && (res != NULL)) { xmlGenericError(xmlGenericErrorContext, "xmlXPathEvalExpression: %d object left on the stack\n", stack); } g_mutex_lock(find_nodeset_pcontext_mutex); xmlXPathFreeParserContext(*pctxt); *pctxt = NULL; //g_printerr("Freed parser context\n"); g_mutex_unlock(find_nodeset_pcontext_mutex); return(res); }
void RXSLT_source(xmlXPathParserContextPtr ctxt, int nargs) { Rboolean ok; xmlXPathObjectPtr obj; obj = valuePop(ctxt); ok = RXSLT_internalSource(xmlXPathCastToString(obj)); valuePush(ctxt, xmlXPathNewBoolean(ok)); }
static void GDALGMLJP2XPathIf(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cond_val,then_val,else_val; CHECK_ARITY(3); else_val = valuePop(ctxt); then_val = valuePop(ctxt); CAST_TO_BOOLEAN cond_val = valuePop(ctxt); if( cond_val->boolval ) { xmlXPathFreeObject(else_val); valuePush(ctxt, then_val); } else { xmlXPathFreeObject(then_val); valuePush(ctxt, else_val); } xmlXPathFreeObject(cond_val); }
/** * xsltGenerateIdFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the generate-id() XSLT function * string generate-id(node-set?) */ void xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){ static char base_address; xmlNodePtr cur = NULL; xmlXPathObjectPtr obj = NULL; long val; xmlChar str[30]; if (nargs == 0) { cur = ctxt->context->node; } else if (nargs == 1) { xmlNodeSetPtr nodelist; int i, ret; if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) { ctxt->error = XPATH_INVALID_TYPE; xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "generate-id() : invalid arg expecting a node-set\n"); return; } obj = valuePop(ctxt); nodelist = obj->nodesetval; if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) { xmlXPathFreeObject(obj); valuePush(ctxt, xmlXPathNewCString("")); return; } cur = nodelist->nodeTab[0]; for (i = 1;i < nodelist->nodeNr;i++) { ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]); if (ret == -1) cur = nodelist->nodeTab[i]; } } else { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "generate-id() : invalid number of args %d\n", nargs); ctxt->error = XPATH_INVALID_ARITY; return; } if (obj) xmlXPathFreeObject(obj); val = (long)((char *)cur - (char *)&base_address); if (val >= 0) { snprintf((char *)str, sizeof(str), "idp%ld", val); } else { snprintf((char *)str, sizeof(str), "idm%ld", -val); } valuePush(ctxt, xmlXPathNewString(str)); }
/** * xsltGenerateIdFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the generate-id() XSLT function * string generate-id(node-set?) */ void xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){ xmlNodePtr cur = NULL; unsigned long val; xmlChar str[20]; if (nargs == 0) { cur = ctxt->context->node; } else if (nargs == 1) { xmlXPathObjectPtr obj; xmlNodeSetPtr nodelist; int i, ret; if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) { ctxt->error = XPATH_INVALID_TYPE; xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "generate-id() : invalid arg expecting a node-set\n"); return; } obj = valuePop(ctxt); nodelist = obj->nodesetval; if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) { xmlXPathFreeObject(obj); valuePush(ctxt, xmlXPathNewCString("")); return; } cur = nodelist->nodeTab[0]; for (i = 1;i < nodelist->nodeNr;i++) { ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]); if (ret == -1) cur = nodelist->nodeTab[i]; } xmlXPathFreeObject(obj); } else { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "generate-id() : invalid number of args %d\n", nargs); ctxt->error = XPATH_INVALID_ARITY; return; } /* * Okay this is ugly but should work, use the NodePtr address * to forge the ID */ val = (unsigned long)((char *)cur - (char *)0); val /= sizeof(xmlNode); sprintf((char *)str, "id%ld", val); valuePush(ctxt, xmlXPathNewString(str)); }
void RXSLT_init(xmlXPathParserContextPtr ctxt, int nargs) { const char *defaultArgs[] = {"Rxsltproc", "--silent"}; char **args; int argc, i; int mustFree; if(R_alreadyInitialized) return; #ifdef XSLT_DEBUG fprintf(stderr, "in RXSLT_init %d\n", nargs);fflush(stderr); #endif if(nargs == 0) { argc = sizeof(defaultArgs)/sizeof(defaultArgs[0]); args = (char **)defaultArgs; } else { args = (char **) malloc((nargs+1) * sizeof(char*)); args[0] = strdup("Rxsltproc"); argc = nargs+1; for(i = 0; i < nargs; i++) { xmlXPathObjectPtr obj = valuePop(ctxt); if(obj->type) { args[i+1] = strdup(xmlXPathCastToString(obj)); } } mustFree = TRUE; } Rf_initEmbeddedR(argc, args); loadXSLPackage(); valuePush(ctxt, xmlXPathNewBoolean(1)); if(mustFree) { for(i = 0; i < nargs+1; i++) { free(args[i]); } free(args); } #if DEBUG_REGISTRATION xsltRegisterExtFunction(getTransformCtxt(), "foo", R_URI, RXSLT_genericFunctionCall); RXSLT_addFunction("foo", NULL_USER_OBJECT); #endif R_alreadyInitialized = 1; return; }
/** * xsltFunctionAvailableFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the function-available() XSLT function * boolean function-available(string) */ void xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){ xmlXPathObjectPtr obj; xmlChar *prefix, *name; const xmlChar *nsURI = NULL; if (nargs != 1) { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "function-available() : expects one string arg\n"); ctxt->error = XPATH_INVALID_ARITY; return; } if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "function-available() : invalid arg expecting a string\n"); ctxt->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctxt); name = xmlSplitQName2(obj->stringval, &prefix); if (name == NULL) { name = xmlStrdup(obj->stringval); } else { nsURI = xmlXPathNsLookup(ctxt->context, prefix); if (nsURI == NULL) { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "function-available() : prefix %s is not bound\n", prefix); } } if (xmlXPathFunctionLookupNS(ctxt->context, name, nsURI) != NULL) { valuePush(ctxt, xmlXPathNewBoolean(1)); } else { valuePush(ctxt, xmlXPathNewBoolean(0)); } xmlXPathFreeObject(obj); if (name != NULL) xmlFree(name); if (prefix != NULL) xmlFree(prefix); }
static void extBitClearOrSet (xmlXPathParserContextPtr ctxt, int nargs, xmlChar value) { xmlChar *res; int width, bitnum = 0, delta; xmlXPathObjectPtr xop; if (nargs != 1 && nargs != 2) { xmlXPathSetArityError(ctxt); return; } /* Pop args in reverse order */ if (nargs == 2) { bitnum = xmlXPathPopNumber(ctxt); if (bitnum < 0 || xmlXPathCheckError(ctxt)) return; } xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; res = extBitStringVal(ctxt, xop); if (res == NULL) return; width = xmlStrlen(res); delta = width - bitnum - 1; if (delta < 0) { xmlChar *newp = xmlRealloc(res, bitnum + 2); if (newp == NULL) return; delta = -delta; memmove(newp + delta, newp, width + 1); newp[0] = value; memset(newp + 1, '0', delta - 1); res = newp; } else { res[delta] = value; } xmlXPathReturnString(ctxt, res); }
static void extBitToHex (xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *res; xmlXPathObjectPtr xop; unsigned long long val; int i, len1, len2; if (nargs != 1) { xmlXPathSetArityError(ctxt); return; } /* Pop args in reverse order */ xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; res = extBitStringVal(ctxt, xop); if (res == NULL) return; for (i = 0, val = 0; i <= 64 && res[i]; i++) { val <<= 1; if (res[i] == '1') val += 1; } if (i > 64) xmlXPathReturnNumber(ctxt, (double) -1); else { len1 = xmlStrlen(res); len2 = snprintf((char *) res, len1 + 1, "0x%qx", val); if (len2 > len1) { res = xmlRealloc(res, len2 + 1); if (res) snprintf((char *) res, len2 + 1, "0x%qx", val); } xmlXPathReturnString(ctxt, res); } }
static void exsltObjectTypeFunction (xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr obj, ret; if (nargs != 1) { xmlXPathSetArityError(ctxt); return; } obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: ret = xmlXPathNewCString("string"); break; case XPATH_NUMBER: ret = xmlXPathNewCString("number"); break; case XPATH_BOOLEAN: ret = xmlXPathNewCString("boolean"); break; case XPATH_NODESET: ret = xmlXPathNewCString("node-set"); break; case XPATH_XSLT_TREE: ret = xmlXPathNewCString("RTF"); break; case XPATH_USERS: ret = xmlXPathNewCString("external"); break; default: xsltGenericError(xsltGenericErrorContext, "object-type() invalid arg\n"); ctxt->error = XPATH_INVALID_TYPE; xmlXPathFreeObject(obj); return; } xmlXPathFreeObject(obj); valuePush(ctxt, ret); }
static void extBitFromInt (xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *res; xmlXPathObjectPtr xop; int width = 0, len; if (nargs != 1 && nargs != 2) { xmlXPathSetArityError(ctxt); return; } /* Pop args in reverse order */ if (nargs == 2) { width = xmlXPathPopNumber(ctxt); if (width < 0 || xmlXPathCheckError(ctxt)) return; } xop = valuePop(ctxt); if (xop == NULL || xmlXPathCheckError(ctxt)) return; res = extBitStringVal(ctxt, xop); if (res == NULL) return; len = xmlStrlen(res); if (width > len) { res = xmlRealloc(res, width + 1); if (res) { int count = width - len; memmove(res + count, res, len + 1); memset(res, '0', count); } } xmlXPathReturnString(ctxt, res); }
/** * exsltStrConcatFunction: * @ctxt: an XPath parser context * @nargs: the number of arguments * * Takes a node set and returns the concatenation of the string values * of the nodes in that node set. If the node set is empty, it * returns an empty string. */ static void exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr obj; xmlChar *ret = NULL; int i; if (nargs != 1) { xmlXPathSetArityError(ctxt); return; } if (!xmlXPathStackIsNodeSet(ctxt)) { xmlXPathSetTypeError(ctxt); return; } obj = valuePop (ctxt); if (xmlXPathNodeSetIsEmpty(obj->nodesetval)) { xmlXPathReturnEmptyString(ctxt); return; } for (i = 0; i < obj->nodesetval->nodeNr; i++) { xmlChar *tmp; tmp = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]); ret = xmlStrcat (ret, tmp); xmlFree(tmp); } xmlXPathFreeObject (obj); xmlXPathReturnString(ctxt, ret); }
/** * xsltFunctionLocalTime: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the localTime XSLT function used by NORM * string localTime(???) * * This function is available in Norm's extension namespace * Code (and comments) contributed by Norm */ static void xsltFunctionLocalTime(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr obj; char *str; char digits[5]; char result[29]; long int field; time_t gmt, lmt; struct tm gmt_tm; struct tm *local_tm; if (nargs != 1) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "localTime() : invalid number of args %d\n", nargs); ctxt->error = XPATH_INVALID_ARITY; return; } obj = valuePop(ctxt); if (obj->type != XPATH_STRING) { obj = xmlXPathConvertString(obj); } if (obj == NULL) { valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); return; } str = (char *) obj->stringval; /* str = "$Date: Tuesday, November 03, 2009 11:37:25 AM$" */ memset(digits, 0, sizeof(digits)); strncpy(digits, str+7, 4); field = strtol(digits, NULL, 10); gmt_tm.tm_year = field - 1900; memset(digits, 0, sizeof(digits)); strncpy(digits, str+12, 2); field = strtol(digits, NULL, 10); gmt_tm.tm_mon = field - 1; memset(digits, 0, sizeof(digits)); strncpy(digits, str+15, 2); field = strtol(digits, NULL, 10); gmt_tm.tm_mday = field; memset(digits, 0, sizeof(digits)); strncpy(digits, str+18, 2); field = strtol(digits, NULL, 10); gmt_tm.tm_hour = field; memset(digits, 0, sizeof(digits)); strncpy(digits, str+21, 2); field = strtol(digits, NULL, 10); gmt_tm.tm_min = field; memset(digits, 0, sizeof(digits)); strncpy(digits, str+24, 2); field = strtol(digits, NULL, 10); gmt_tm.tm_sec = field; /* Now turn gmt_tm into a time. */ gmt = mktime(&gmt_tm); /* * FIXME: it's been too long since I did manual memory management. * (I swore never to do it again.) Does this introduce a memory leak? */ local_tm = localtime(&gmt); /* * Calling localtime() has the side-effect of setting timezone. * After we know the timezone, we can adjust for it */ lmt = gmt - timezone; /* * FIXME: it's been too long since I did manual memory management. * (I swore never to do it again.) Does this introduce a memory leak? */ local_tm = localtime(&lmt); /* * Now convert local_tm back into a string. This doesn't introduce * a memory leak, so says asctime(3). */ str = asctime(local_tm); /* "Tue Jun 26 05:02:16 2001" */ /* 0123456789 123456789 123 */ memset(result, 0, sizeof(result)); /* "Thu, 26 Jun 2001" */ /* 0123456789 12345 */ strncpy(result, str, 20); strcpy(result+20, "???"); /* tzname doesn't work, fake it */ strncpy(result+23, str+19, 5); /* Ok, now result contains the string I want to send back. */ valuePush(ctxt, xmlXPathNewString((xmlChar *)result)); }
/** * xsltDocumentFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the document() XSLT function * node-set document(object, node-set?) */ void xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr obj, obj2 = NULL; xmlChar *base = NULL, *URI; if ((nargs < 1) || (nargs > 2)) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "document() : invalid number of args %d\n", nargs); ctxt->error = XPATH_INVALID_ARITY; return; } if (ctxt->value == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "document() : invalid arg value\n"); ctxt->error = XPATH_INVALID_TYPE; return; } if (nargs == 2) { if (ctxt->value->type != XPATH_NODESET) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "document() : invalid arg expecting a nodeset\n"); ctxt->error = XPATH_INVALID_TYPE; return; } obj2 = valuePop(ctxt); } if (ctxt->value->type == XPATH_NODESET) { int i; xmlXPathObjectPtr newobj, ret; obj = valuePop(ctxt); ret = xmlXPathNewNodeSet(NULL); if ((obj != NULL) && obj->nodesetval) { for (i = 0; i < obj->nodesetval->nodeNr; i++) { valuePush(ctxt, xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i])); xmlXPathStringFunction(ctxt, 1); if (nargs == 2) { valuePush(ctxt, xmlXPathObjectCopy(obj2)); } else { valuePush(ctxt, xmlXPathNewNodeSet(obj->nodesetval-> nodeTab[i])); } xsltDocumentFunction(ctxt, 2); newobj = valuePop(ctxt); ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval, newobj->nodesetval); xmlXPathFreeObject(newobj); } } if (obj != NULL) xmlXPathFreeObject(obj); if (obj2 != NULL) xmlXPathFreeObject(obj2); valuePush(ctxt, ret); return; } /* * Make sure it's converted to a string */ xmlXPathStringFunction(ctxt, 1); if (ctxt->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "document() : invalid arg expecting a string\n"); ctxt->error = XPATH_INVALID_TYPE; if (obj2 != NULL) xmlXPathFreeObject(obj2); return; } obj = valuePop(ctxt); if (obj->stringval == NULL) { valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } else { xsltTransformContextPtr tctxt; tctxt = xsltXPathGetTransformContext(ctxt); if ((obj2 != NULL) && (obj2->nodesetval != NULL) && (obj2->nodesetval->nodeNr > 0) && IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) { xmlNodePtr target; target = obj2->nodesetval->nodeTab[0]; if ((target->type == XML_ATTRIBUTE_NODE) || (target->type == XML_PI_NODE)) { target = ((xmlAttrPtr) target)->parent; } base = xmlNodeGetBase(target->doc, target); } else { if ((tctxt != NULL) && (tctxt->inst != NULL)) { base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst); } else if ((tctxt != NULL) && (tctxt->style != NULL) && (tctxt->style->doc != NULL)) { base = xmlNodeGetBase(tctxt->style->doc, (xmlNodePtr) tctxt->style->doc); } } URI = xmlBuildURI(obj->stringval, base); if (base != NULL) xmlFree(base); if (URI == NULL) { if ((tctxt != NULL) && (tctxt->style != NULL) && (tctxt->style->doc != NULL) && (xmlStrEqual(URI, tctxt->style->doc->URL))) { /* This selects the stylesheet's doc itself. */ valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) tctxt->style->doc)); } else { valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } } else { xsltDocumentFunctionLoadDocument( ctxt, URI ); xmlFree(URI); } } xmlXPathFreeObject(obj); if (obj2 != NULL) xmlXPathFreeObject(obj2); }
/** * xsltKeyFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the key() XSLT function * node-set key(string, object) */ void xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){ xmlXPathObjectPtr obj1, obj2; if (nargs != 2) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "key() : expects two arguments\n"); ctxt->error = XPATH_INVALID_ARITY; return; } /* * Get the key's value. */ obj2 = valuePop(ctxt); xmlXPathStringFunction(ctxt, 1); if ((obj2 == NULL) || (ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "key() : invalid arg expecting a string\n"); ctxt->error = XPATH_INVALID_TYPE; xmlXPathFreeObject(obj2); return; } /* * Get the key's name. */ obj1 = valuePop(ctxt); if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) { int i; xmlXPathObjectPtr newobj, ret; ret = xmlXPathNewNodeSet(NULL); if (obj2->nodesetval != NULL) { for (i = 0; i < obj2->nodesetval->nodeNr; i++) { valuePush(ctxt, xmlXPathObjectCopy(obj1)); valuePush(ctxt, xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i])); xmlXPathStringFunction(ctxt, 1); xsltKeyFunction(ctxt, 2); newobj = valuePop(ctxt); ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval, newobj->nodesetval); xmlXPathFreeObject(newobj); } } valuePush(ctxt, ret); } else { xmlNodeSetPtr nodelist = NULL; xmlChar *key = NULL, *value; const xmlChar *keyURI; xsltTransformContextPtr tctxt; xmlChar *qname, *prefix; xmlXPathContextPtr xpctxt = ctxt->context; xmlNodePtr tmpNode = NULL; xsltDocumentPtr oldDocInfo; tctxt = xsltXPathGetTransformContext(ctxt); oldDocInfo = tctxt->document; if (xpctxt->node == NULL) { xsltTransformError(tctxt, NULL, tctxt->inst, "Internal error in xsltKeyFunction(): " "The context node is not set on the XPath context.\n"); tctxt->state = XSLT_STATE_STOPPED; goto error; } /* * Get the associated namespace URI if qualified name */ qname = obj1->stringval; key = xmlSplitQName2(qname, &prefix); if (key == NULL) { key = xmlStrdup(obj1->stringval); keyURI = NULL; if (prefix != NULL) xmlFree(prefix); } else { if (prefix != NULL) { keyURI = xmlXPathNsLookup(xpctxt, prefix); if (keyURI == NULL) { xsltTransformError(tctxt, NULL, tctxt->inst, "key() : prefix %s is not bound\n", prefix); /* * TODO: Shouldn't we stop here? */ } xmlFree(prefix); } else { keyURI = NULL; } } /* * Force conversion of first arg to string */ valuePush(ctxt, obj2); xmlXPathStringFunction(ctxt, 1); if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { xsltTransformError(tctxt, NULL, tctxt->inst, "key() : invalid arg expecting a string\n"); ctxt->error = XPATH_INVALID_TYPE; goto error; } obj2 = valuePop(ctxt); value = obj2->stringval; /* * We need to ensure that ctxt->document is available for * xsltGetKey(). * First find the relevant doc, which is the context node's * owner doc; using context->doc is not safe, since * the doc could have been acquired via the document() function, * or the doc might be a Result Tree Fragment. * FUTURE INFO: In XSLT 2.0 the key() function takes an additional * argument indicating the doc to use. */ if (xpctxt->node->type == XML_NAMESPACE_DECL) { /* * REVISIT: This is a libxml hack! Check xpath.c for details. * The XPath module sets the owner element of a ns-node on * the ns->next field. */ if ((((xmlNsPtr) xpctxt->node)->next != NULL) && (((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE)) { tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next; } } else tmpNode = xpctxt->node; if ((tmpNode == NULL) || (tmpNode->doc == NULL)) { xsltTransformError(tctxt, NULL, tctxt->inst, "Internal error in xsltKeyFunction(): " "Couldn't get the doc of the XPath context node.\n"); goto error; } if ((tctxt->document == NULL) || (tctxt->document->doc != tmpNode->doc)) { if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) { /* * This is a Result Tree Fragment. */ if (tmpNode->doc->_private == NULL) { tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc); if (tmpNode->doc->_private == NULL) goto error; } tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private; } else { /* * May be the initial source doc or a doc acquired via the * document() function. */ tctxt->document = xsltFindDocument(tctxt, tmpNode->doc); } if (tctxt->document == NULL) { xsltTransformError(tctxt, NULL, tctxt->inst, "Internal error in xsltKeyFunction(): " "Could not get the document info of a context doc.\n"); tctxt->state = XSLT_STATE_STOPPED; goto error; } } /* * Get/compute the key value. */ nodelist = xsltGetKey(tctxt, key, keyURI, value); error: tctxt->document = oldDocInfo; valuePush(ctxt, xmlXPathWrapNodeSet( xmlXPathNodeSetMerge(NULL, nodelist))); if (key != NULL) xmlFree(key); } if (obj1 != NULL) xmlXPathFreeObject(obj1); if (obj2 != NULL) xmlXPathFreeObject(obj2); }
static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */ { xsltTransformContextPtr tctxt; zval *args; zval retval; int result, i; int error = 0; zend_fcall_info fci; zval handler; xmlXPathObjectPtr obj; char *str; xsl_object *intern; zend_string *callable = NULL; if (! zend_is_executing()) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: Function called from outside of PHP\n"); error = 1; } else { tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the transformation context\n"); error = 1; } else { intern = (xsl_object*)tctxt->_private; if (intern == NULL) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the internal object\n"); error = 1; } else if (intern->registerPhpFunctions == 0) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: PHP Object did not register PHP functions\n"); error = 1; } } } if (error == 1) { for (i = nargs - 1; i >= 0; i--) { obj = valuePop(ctxt); xmlXPathFreeObject(obj); } return; } fci.param_count = nargs - 1; if (fci.param_count > 0) { args = safe_emalloc(fci.param_count, sizeof(zval), 0); } /* Reverse order to pop values off ctxt stack */ for (i = nargs - 2; i >= 0; i--) { obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: ZVAL_STRING(&args[i], (char *)obj->stringval); break; case XPATH_BOOLEAN: ZVAL_BOOL(&args[i], obj->boolval); break; case XPATH_NUMBER: ZVAL_DOUBLE(&args[i], obj->floatval); break; case XPATH_NODESET: if (type == 1) { str = (char*)xmlXPathCastToString(obj); ZVAL_STRING(&args[i], str); xmlFree(str); } else if (type == 2) { int j; dom_object *domintern = (dom_object *)intern->doc; array_init(&args[i]); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { for (j = 0; j < obj->nodesetval->nodeNr; j++) { xmlNodePtr node = obj->nodesetval->nodeTab[j]; zval child; /* not sure, if we need this... it's copied from xpath.c */ if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr curns; xmlNodePtr nsparent; nsparent = node->_private; curns = xmlNewNs(NULL, node->name, NULL); if (node->children) { curns->prefix = xmlStrdup((char *)node->children); } if (node->children) { node = xmlNewDocNode(node->doc, NULL, (char *) node->children, node->name); } else { node = xmlNewDocNode(node->doc, NULL, (const xmlChar *) "xmlns", node->name); } node->type = XML_NAMESPACE_DECL; node->parent = nsparent; node->ns = curns; } else { node = xmlDocCopyNodeList(domintern->document->ptr, node); } php_dom_create_object(node, &child, domintern); add_next_index_zval(&args[i], &child); } } } break; default: str = (char *) xmlXPathCastToString(obj); ZVAL_STRING(&args[i], str); xmlFree(str); } xmlXPathFreeObject(obj); } fci.size = sizeof(fci); fci.function_table = EG(function_table); if (fci.param_count > 0) { fci.params = args; } else { fci.params = NULL; } obj = valuePop(ctxt); if (obj->stringval == NULL) { php_error_docref(NULL, E_WARNING, "Handler name must be a string"); xmlXPathFreeObject(obj); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&args[i]); } efree(args); } return; } ZVAL_STRING(&handler, (char *) obj->stringval); xmlXPathFreeObject(obj); ZVAL_COPY_VALUE(&fci.function_name, &handler); fci.symbol_table = NULL; fci.object = NULL; fci.retval = &retval; fci.no_separation = 0; /*fci.function_handler_cache = &function_ptr;*/ if (!zend_make_callable(&handler, &callable)) { php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", ZSTR_VAL(callable)); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); } else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable) == 0) { php_error_docref(NULL, E_WARNING, "Not allowed to call handler '%s()'", ZSTR_VAL(callable)); /* Push an empty string, so that we at least have an xslt result... */ valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); } else { result = zend_call_function(&fci, NULL); if (result == FAILURE) { if (Z_TYPE(handler) == IS_STRING) { php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", Z_STRVAL(handler)); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); } /* retval is == NULL, when an exception occurred, don't report anything, because PHP itself will handle that */ } else if (Z_ISUNDEF(retval)) { } else { if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), dom_node_class_entry)) { xmlNode *nodep; dom_object *obj; if (intern->node_list == NULL) { ALLOC_HASHTABLE(intern->node_list); zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0); } Z_ADDREF(retval); zend_hash_next_index_insert(intern->node_list, &retval); obj = Z_DOMOBJ_P(&retval); nodep = dom_object_get_node(obj); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); } else if (Z_TYPE(retval) == IS_TRUE || Z_TYPE(retval) == IS_FALSE) { valuePush(ctxt, xmlXPathNewBoolean(Z_LVAL(retval))); } else if (Z_TYPE(retval) == IS_OBJECT) { php_error_docref(NULL, E_WARNING, "A PHP Object cannot be converted to a XPath-string"); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); } else { convert_to_string_ex(&retval); valuePush(ctxt, xmlXPathNewString((xmlChar *) Z_STRVAL(retval))); } zval_ptr_dtor(&retval); } } zend_string_release(callable); zval_ptr_dtor(&handler); if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&args[i]); } efree(args); } }
static void ruby_funcall(xmlXPathParserContextPtr ctx, int nargs) { VALUE xpath_handler = Qnil; VALUE result; VALUE *argv; VALUE doc; VALUE node_set = Qnil; xmlNodeSetPtr xml_node_set = NULL; xmlXPathObjectPtr obj; int i; nokogiriNodeSetTuple *node_set_tuple; assert(ctx); assert(ctx->context); assert(ctx->context->userData); assert(ctx->context->doc); assert(DOC_RUBY_OBJECT_TEST(ctx->context->doc)); xpath_handler = (VALUE)(ctx->context->userData); argv = (VALUE *)calloc((size_t)nargs, sizeof(VALUE)); for (i = 0 ; i < nargs ; ++i) { rb_gc_register_address(&argv[i]); } doc = DOC_RUBY_OBJECT(ctx->context->doc); if (nargs > 0) { i = nargs - 1; do { obj = valuePop(ctx); switch(obj->type) { case XPATH_STRING: argv[i] = NOKOGIRI_STR_NEW2(obj->stringval); break; case XPATH_BOOLEAN: argv[i] = obj->boolval == 1 ? Qtrue : Qfalse; break; case XPATH_NUMBER: argv[i] = rb_float_new(obj->floatval); break; case XPATH_NODESET: argv[i] = Nokogiri_wrap_xml_node_set(obj->nodesetval, doc); break; default: argv[i] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(obj)); } xmlXPathFreeNodeSetList(obj); } while(i-- > 0); } result = rb_funcall2( xpath_handler, rb_intern((const char *)ctx->context->function), nargs, argv ); for (i = 0 ; i < nargs ; ++i) { rb_gc_unregister_address(&argv[i]); } free(argv); switch(TYPE(result)) { case T_FLOAT: case T_BIGNUM: case T_FIXNUM: xmlXPathReturnNumber(ctx, NUM2DBL(result)); break; case T_STRING: xmlXPathReturnString( ctx, (xmlChar *)xmlXPathWrapCString(StringValuePtr(result)) ); break; case T_TRUE: xmlXPathReturnTrue(ctx); break; case T_FALSE: xmlXPathReturnFalse(ctx); break; case T_NIL: break; case T_ARRAY: { VALUE args[2]; args[0] = doc; args[1] = result; node_set = rb_class_new_instance(2, args, cNokogiriXmlNodeSet); Data_Get_Struct(node_set, nokogiriNodeSetTuple, node_set_tuple); xml_node_set = node_set_tuple->node_set; xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set)); } break; case T_DATA: if(rb_obj_is_kind_of(result, cNokogiriXmlNodeSet)) { Data_Get_Struct(result, nokogiriNodeSetTuple, node_set_tuple); xml_node_set = node_set_tuple->node_set; /* Copy the node set, otherwise it will get GC'd. */ xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set)); break; } default: rb_raise(rb_eRuntimeError, "Invalid return type"); } }
static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */ { zval retval; int result, i; int error = 0; zend_fcall_info fci; xmlXPathObjectPtr obj; char *str; zend_string *callable = NULL; dom_xpath_object *intern; if (! zend_is_executing()) { xmlGenericError(xmlGenericErrorContext, "xmlExtFunctionTest: Function called from outside of PHP\n"); error = 1; } else { intern = (dom_xpath_object *) ctxt->context->userData; if (intern == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlExtFunctionTest: failed to get the internal object\n"); error = 1; } else if (intern->registerPhpFunctions == 0) { xmlGenericError(xmlGenericErrorContext, "xmlExtFunctionTest: PHP Object did not register PHP functions\n"); error = 1; } } if (error == 1) { for (i = nargs - 1; i >= 0; i--) { obj = valuePop(ctxt); xmlXPathFreeObject(obj); } return; } fci.param_count = nargs - 1; if (fci.param_count > 0) { fci.params = safe_emalloc(fci.param_count, sizeof(zval), 0); } /* Reverse order to pop values off ctxt stack */ for (i = nargs - 2; i >= 0; i--) { obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: ZVAL_STRING(&fci.params[i], (char *)obj->stringval); break; case XPATH_BOOLEAN: ZVAL_BOOL(&fci.params[i], obj->boolval); break; case XPATH_NUMBER: ZVAL_DOUBLE(&fci.params[i], obj->floatval); break; case XPATH_NODESET: if (type == 1) { str = (char *)xmlXPathCastToString(obj); ZVAL_STRING(&fci.params[i], str); xmlFree(str); } else if (type == 2) { int j; array_init(&fci.params[i]); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { for (j = 0; j < obj->nodesetval->nodeNr; j++) { xmlNodePtr node = obj->nodesetval->nodeTab[j]; zval child; /* not sure, if we need this... it's copied from xpath.c */ if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr curns; xmlNodePtr nsparent; nsparent = node->_private; curns = xmlNewNs(NULL, node->name, NULL); if (node->children) { curns->prefix = xmlStrdup((xmlChar *) node->children); } if (node->children) { node = xmlNewDocNode(node->doc, NULL, (xmlChar *) node->children, node->name); } else { node = xmlNewDocNode(node->doc, NULL, (xmlChar *) "xmlns", node->name); } node->type = XML_NAMESPACE_DECL; node->parent = nsparent; node->ns = curns; } php_dom_create_object(node, &child, &intern->dom); add_next_index_zval(&fci.params[i], &child); } } } break; default: ZVAL_STRING(&fci.params[i], (char *)xmlXPathCastToString(obj)); } xmlXPathFreeObject(obj); } fci.size = sizeof(fci); fci.function_table = EG(function_table); obj = valuePop(ctxt); if (obj->stringval == NULL) { php_error_docref(NULL, E_WARNING, "Handler name must be a string"); xmlXPathFreeObject(obj); if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&fci.params[i]); } efree(fci.params); } return; } ZVAL_STRING(&fci.function_name, (char *) obj->stringval); xmlXPathFreeObject(obj); fci.symbol_table = NULL; fci.object = NULL; fci.retval = &retval; fci.no_separation = 0; if (!zend_make_callable(&fci.function_name, &callable)) { php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", callable->val); } else if (intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable) == 0) { php_error_docref(NULL, E_WARNING, "Not allowed to call handler '%s()'.", callable->val); /* Push an empty string, so that we at least have an xslt result... */ valuePush(ctxt, xmlXPathNewString((xmlChar *)"")); } else { result = zend_call_function(&fci, NULL); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), dom_node_class_entry)) { xmlNode *nodep; dom_object *obj; if (intern->node_list == NULL) { ALLOC_HASHTABLE(intern->node_list); zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0); } GC_REFCOUNT(&retval)++; zend_hash_next_index_insert(intern->node_list, &retval); obj = Z_DOMOBJ_P(&retval); nodep = dom_object_get_node(obj); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); } else if (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE) { valuePush(ctxt, xmlXPathNewBoolean(Z_TYPE(retval) == IS_TRUE)); } else if (Z_TYPE(retval) == IS_OBJECT) { php_error_docref(NULL, E_WARNING, "A PHP Object cannot be converted to a XPath-string"); valuePush(ctxt, xmlXPathNewString((xmlChar *)"")); } else { zend_string *str = zval_get_string(&retval); valuePush(ctxt, xmlXPathNewString((xmlChar *) str->val)); zend_string_release(str); } zval_ptr_dtor(&retval); } } zend_string_release(callable); zval_dtor(&fci.function_name); if (fci.param_count > 0) { for (i = 0; i < nargs - 1; i++) { zval_ptr_dtor(&fci.params[i]); } efree(fci.params); } }
static void method_caller(xmlXPathParserContextPtr ctxt, int nargs) { const xmlChar * function; const xmlChar * functionURI; size_t i, count; xsltTransformContextPtr transform; xmlXPathObjectPtr xpath; VALUE obj; VALUE *args; VALUE result; transform = xsltXPathGetTransformContext(ctxt); function = ctxt->context->function; functionURI = ctxt->context->functionURI; obj = (VALUE)xsltGetExtData(transform, functionURI); count = (size_t)ctxt->valueNr; args = calloc(count, sizeof(VALUE *)); for(i = 0; i < count; i++) { VALUE thing; xpath = valuePop(ctxt); switch(xpath->type) { case XPATH_STRING: thing = NOKOGIRI_STR_NEW2(xpath->stringval); break; case XPATH_NODESET: if(NULL == xpath->nodesetval) { thing = Nokogiri_wrap_xml_node_set( xmlXPathNodeSetCreate(NULL), DOC_RUBY_OBJECT(ctxt->context->doc)); } else { thing = Nokogiri_wrap_xml_node_set(xpath->nodesetval, DOC_RUBY_OBJECT(ctxt->context->doc)); } break; default: rb_raise(rb_eRuntimeError, "do not handle type: %d", xpath->type); } args[i] = thing; xmlFree(xpath); } result = rb_funcall3(obj, rb_intern((const char *)function), (int)count, args); free(args); switch(TYPE(result)) { case T_FLOAT: case T_BIGNUM: case T_FIXNUM: xmlXPathReturnNumber(ctxt, NUM2DBL(result)); break; case T_STRING: xmlXPathReturnString( ctxt, xmlStrdup((xmlChar *)StringValuePtr(result)) ); break; case T_TRUE: xmlXPathReturnTrue(ctxt); break; case T_FALSE: xmlXPathReturnFalse(ctxt); break; case T_NIL: break; default: rb_raise(rb_eRuntimeError, "Invalid return type"); } }
static void xslt_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) { XSLTProcessorData *intern = nullptr; int error = 0; xsltTransformContextPtr tctxt = xsltXPathGetTransformContext (ctxt); if (tctxt == nullptr) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the transformation context\n" ); error = 1; } else { intern = (XSLTProcessorData*)tctxt->_private; if (intern == nullptr) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the internal object\n" ); error = 1; } else { if (intern->m_registerPhpFunctions == 0) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: PHP Object did not register PHP functions\n" ); error = 1; } } } xmlXPathObjectPtr obj; if (error == 1) { for (int i = nargs - 1; i >= 0; i--) { obj = valuePop(ctxt); xmlXPathFreeObject(obj); } return; } Array args; // Reverse order to pop values off ctxt stack for (int i = nargs - 2; i >= 0; i--) { Variant arg; obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: arg = String((char*)obj->stringval, CopyString); break; case XPATH_BOOLEAN: arg = (bool)obj->boolval; break; case XPATH_NUMBER: arg = (double)obj->floatval; break; case XPATH_NODESET: if (type == 1) { char *str = (char*)xmlXPathCastToString(obj); arg = String(str, CopyString); xmlFree(str); } else if (type == 2) { arg = Array::Create(); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { for (int j = 0; j < obj->nodesetval->nodeNr; j++) { // TODO: not sure this is the right thing to do. xmlNodePtr node = obj->nodesetval->nodeTab[j]; if (node->type == XML_ELEMENT_NODE) { Object element = newNode(s_DOMElement, xmlCopyNode(node, /*extended*/ 1)); arg.toArrRef().append(element); } else if (node->type == XML_ATTRIBUTE_NODE) { Object attribute = newNode(s_DOMAttr, (xmlNodePtr)xmlCopyProp(nullptr, (xmlAttrPtr)node)); arg.toArrRef().append(attribute); } else if (node->type == XML_TEXT_NODE) { Object text = newNode(s_DOMText, (xmlNodePtr)xmlNewText(xmlNodeGetContent(node))); arg.toArrRef().append(text); } else { raise_warning("Unhandled node type '%d'", node->type); // Use a generic DOMNode as fallback for now. Object nodeobj = newNode(s_DOMNode, xmlCopyNode(node, /*extended*/ 1)); arg.toArrRef().append(nodeobj); } } } } break; default: arg = String((char*)xmlXPathCastToString(obj), CopyString); } xmlXPathFreeObject(obj); args.prepend(arg); } obj = valuePop(ctxt); if (obj->stringval == nullptr) { raise_warning("Handler name must be a string"); xmlXPathFreeObject(obj); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); return; } String handler((char*)obj->stringval, CopyString); xmlXPathFreeObject(obj); if (!HHVM_FN(is_callable)(handler)) { raise_warning("Unable to call handler %s()", handler.data()); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else if (intern->m_registerPhpFunctions == 2 && !intern->m_registered_phpfunctions.exists(handler)) { raise_warning("Not allowed to call handler '%s()'", handler.data()); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else { Variant retval = vm_call_user_func(handler, args); if (retval.isObject() && retval.getObjectData()->instanceof(s_DOMNode)) { ObjectData *retval_data = retval.asCObjRef().get(); xmlNode* nodep = Native::data<DOMNode>(retval_data)->nodep(); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); intern->m_usedElements.prepend(retval); } else if (retval.is(KindOfBoolean)) { valuePush(ctxt, xmlXPathNewBoolean(retval.toBoolean())); } else if (retval.isObject()) { raise_warning("A PHP Object cannot be converted to an XPath-string"); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else { String sretval = retval.toString(); valuePush(ctxt, xmlXPathNewString((xmlChar*)sretval.data())); } } }
/** * xsltSystemPropertyFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the system-property() XSLT function * object system-property(string) */ void xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){ xmlXPathObjectPtr obj; xmlChar *prefix, *name; const xmlChar *nsURI = NULL; if (nargs != 1) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "system-property() : expects one string arg\n"); ctxt->error = XPATH_INVALID_ARITY; return; } if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "system-property() : invalid arg expecting a string\n"); ctxt->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctxt); if (obj->stringval == NULL) { valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); } else { name = xmlSplitQName2(obj->stringval, &prefix); if (name == NULL) { name = xmlStrdup(obj->stringval); } else { nsURI = xmlXPathNsLookup(ctxt->context, prefix); if (nsURI == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "system-property() : prefix %s is not bound\n", prefix); } } if (xmlStrEqual(nsURI, XSLT_NAMESPACE)) { #ifdef DOCBOOK_XSL_HACK if (xmlStrEqual(name, (const xmlChar *)"vendor")) { xsltStylesheetPtr sheet; xsltTransformContextPtr tctxt; tctxt = xsltXPathGetTransformContext(ctxt); if ((tctxt != NULL) && (tctxt->inst != NULL) && (xmlStrEqual(tctxt->inst->name, BAD_CAST "variable")) && (tctxt->inst->parent != NULL) && (xmlStrEqual(tctxt->inst->parent->name, BAD_CAST "template"))) sheet = tctxt->style; else sheet = NULL; if ((sheet != NULL) && (sheet->doc != NULL) && (sheet->doc->URL != NULL) && (xmlStrstr(sheet->doc->URL, (const xmlChar *)"chunk") != NULL)) { valuePush(ctxt, xmlXPathNewString( (const xmlChar *)"libxslt (SAXON 6.2 compatible)")); } else { valuePush(ctxt, xmlXPathNewString( (const xmlChar *)XSLT_DEFAULT_VENDOR)); } } else #else if (xmlStrEqual(name, (const xmlChar *)"vendor")) { valuePush(ctxt, xmlXPathNewString( (const xmlChar *)XSLT_DEFAULT_VENDOR)); } else #endif if (xmlStrEqual(name, (const xmlChar *)"version")) { valuePush(ctxt, xmlXPathNewString( (const xmlChar *)XSLT_DEFAULT_VERSION)); } else if (xmlStrEqual(name, (const xmlChar *)"vendor-url")) { valuePush(ctxt, xmlXPathNewString( (const xmlChar *)XSLT_DEFAULT_URL)); } else { valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); } } else { valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); } if (name != NULL) xmlFree(name); if (prefix != NULL) xmlFree(prefix); } xmlXPathFreeObject(obj); }