Esempio n. 1
0
bool XMLReader::set_relaxng_schema(String source, int type) {
  SYNC_VM_REGS_SCOPED();
  if (source.empty()) {
    raise_warning("Schema data source is required");
    return false;
  }

  if (m_ptr) {
    int ret = -1;
    xmlRelaxNGPtr schema = nullptr;
    if (!source.empty()) {
      schema =  _xmlreader_get_relaxNG(source, type, nullptr, nullptr);
      if (schema) {
        ret = xmlTextReaderRelaxNGSetSchema(m_ptr, schema);
      }
    } else {
      ret = xmlTextReaderRelaxNGSetSchema(m_ptr, nullptr);
    }

    if (ret == 0) {
      if (m_schema) {
        xmlRelaxNGFree((xmlRelaxNGPtr) m_schema);
      }
      m_schema = schema;
      return true;
    }
  }

  raise_warning("Unable to set schema. This must be set prior to reading or schema contains errors.");
  return false;
}
Esempio n. 2
0
bool PDOSqliteStatement::fetcher(PDOFetchOrientation ori, long offset) {
  SYNC_VM_REGS_SCOPED();
  if (!m_stmt) {
    return false;
  }
  if (m_pre_fetched) {
    m_pre_fetched = 0;
    return true;
  }
  if (m_done) {
    return false;
  }
  switch (sqlite3_step(m_stmt)) {
  case SQLITE_ROW:
    return true;

  case SQLITE_DONE:
    m_done = 1;
    sqlite3_reset(m_stmt);
    return false;

  case SQLITE_ERROR:
    sqlite3_reset(m_stmt);
  default:
    handleError(__FILE__, __LINE__);
    return false;
  }
}
Esempio n. 3
0
Variant HHVM_METHOD(XMLReader, getAttributeNs,
                    const String& name,
                    const String& namespaceURI) {
  auto* data = Native::data<XMLReader>(this_);
  SYNC_VM_REGS_SCOPED();
  if (name.empty() || namespaceURI.empty()) {
    raise_warning("Attribute Name and Namespace URI cannot be empty");
    return false;
  }

  char *retchar = nullptr;
  if (data->m_ptr) {
    retchar = (char *)xmlTextReaderGetAttributeNs(data->m_ptr,
                                                  (xmlChar *)name.data(),
                                                  (xmlChar *)namespaceURI.data());
  }

  if (retchar) {
    String ret((const char*)retchar, CopyString);
    xmlFree(retchar);
    return ret;
  } else {
    return init_null();
  }
}
Esempio n. 4
0
Variant c_SQLite3::t_querysingle(const String& sql, bool entire_row /* = false */) {
  SYNC_VM_REGS_SCOPED();
  validate();
  if (!sql.empty()) {
    Variant stmt = t_prepare(sql);
    if (!same(stmt, false)) {
      sqlite3_stmt *pstmt =
        stmt.toObject().getTyped<c_SQLite3Stmt>()->m_raw_stmt;
      switch (sqlite3_step(pstmt)) {
      case SQLITE_ROW: /* Valid Row */
        if (entire_row) {
          Array ret = Array::Create();
          for (int i = 0; i < sqlite3_data_count(pstmt); i++) {
            ret.set(String((char*)sqlite3_column_name(pstmt, i), CopyString),
                    get_column_value(pstmt, i));
          }
          return ret;
        }
        return get_column_value(pstmt, 0);
      case SQLITE_DONE: /* Valid but no results */
        if (entire_row) {
          return empty_array;
        } else {
          return uninit_null();
        }
      default:
        raise_warning("Unable to execute statement: %s",
                      sqlite3_errmsg(m_raw_db));
      }
    }
  }
  return false;
}
Esempio n. 5
0
bool HHVM_METHOD(XMLReader, next,
                 const Variant& localname /*= null_variant*/) {
  auto* data = Native::data<XMLReader>(this_);
  const String& str_localname = localname.isNull()
                              ? null_string
                              : localname.toString();
  SYNC_VM_REGS_SCOPED();
  if (data->m_ptr) {
    int ret = xmlTextReaderNext(data->m_ptr);
    while (!str_localname.empty() && ret == 1) {
      if (xmlStrEqual(xmlTextReaderConstLocalName(data->m_ptr),
          (xmlChar *)str_localname.data())) {
        return true;
      }
      ret = xmlTextReaderNext(data->m_ptr);
    }
    if (ret == -1) {
      raise_warning("An Error Occurred while reading");
      return false;
    } else {
      return ret;
    }
  }
  raise_warning("Load Data before trying to read");
  return false;
}
Esempio n. 6
0
bool XMLReader::bool_func_no_arg(xmlreader_read_int_t internal_function) {
  SYNC_VM_REGS_SCOPED();
  if (m_ptr) {
    int ret = internal_function(m_ptr);
    if (ret == 1) {
      return true;
    }
  }
  return false;
}
Esempio n. 7
0
  Variant execute() {
    ASSERT(!m_exception);
    if (m_cp == NULL) {
      return false;
    }
    if (m_emptyPost) {
      // As per curl docs, an empty post must set POSTFIELDSIZE to be 0 or
      // the reader function will be called
      curl_easy_setopt(m_cp, CURLOPT_POSTFIELDSIZE, 0);
    }
    m_write.buf.reset();
    m_write.content.clear();
    m_header.clear();
    memset(m_error_str, 0, sizeof(m_error_str));

    {
      IOStatusHelper io("curl_easy_perform", m_url.data());
      SYNC_VM_REGS_SCOPED();
      m_error_no = curl_easy_perform(m_cp);
      if (m_exception) {
        if (m_phpException) {
          Object e((ObjectData*)m_exception);
          m_exception = NULL;
          e.get()->decRefCount();
          throw e;
        } else {
          Exception *e = (Exception*)m_exception;
          m_exception = NULL;
          e->throwException();
        }
      }
    }
    set_curl_statuses(m_cp, m_url.data());

    /* CURLE_PARTIAL_FILE is returned by HEAD requests */
    if (m_error_no != CURLE_OK && m_error_no != CURLE_PARTIAL_FILE) {
      m_write.buf.reset();
      m_write.content.clear();
      return false;
    }

    if (m_write.method == PHP_CURL_RETURN) {
      if (!m_write.buf.empty()) {
        m_write.content = m_write.buf.detach();
      }
      if (!m_write.content.empty()) {
        return m_write.content;
      }
    }
    if (m_write.method == PHP_CURL_RETURN) {
      return String("");
    }
    return true;
  }
Esempio n. 8
0
Variant c_SQLite3::t_query(const String& sql) {
  SYNC_VM_REGS_SCOPED();
  validate();
  if (!sql.empty()) {
    Variant stmt = t_prepare(sql);
    if (!same(stmt, false)) {
      return stmt.toObject().getTyped<c_SQLite3Stmt>()->t_execute();
    }
  }
  return false;
}
Esempio n. 9
0
bool c_SQLite3::t_exec(const String& sql) {
  SYNC_VM_REGS_SCOPED();
  validate();

  char *errtext = NULL;
  if (sqlite3_exec(m_raw_db, sql.data(), NULL, NULL, &errtext) != SQLITE_OK) {
    raise_warning("%s", errtext);
    sqlite3_free(errtext);
    return false;
  }
  return true;
}
Esempio n. 10
0
bool HHVM_METHOD(XMLReader, moveToAttributeNo,
                 int64_t index) {
  auto* data = Native::data<XMLReader>(this_);
  SYNC_VM_REGS_SCOPED();
  if (data->m_ptr) {
    int ret = xmlTextReaderMoveToAttributeNo(data->m_ptr, index);
    if (ret == 1) {
      return true;
    }
  }
  return false;
}
Esempio n. 11
0
void BaseExecutionContext::handleError(const std::string &msg,
                                       int errnum,
                                       bool callUserHandler,
                                       ErrorThrowMode mode,
                                       const std::string &prefix) {
  SYNC_VM_REGS_SCOPED();

  int newErrorState = ErrorRaised;
  switch (getErrorState()) {
  case ErrorRaised:
  case ErrorRaisedByUserHandler:
    return;
  case ExecutingUserHandler:
    newErrorState = ErrorRaisedByUserHandler;
    break;
  default:
    break;
  }
  ErrorStateHelper esh(this, newErrorState);
  ExtendedException ee(msg);
  recordLastError(ee, errnum);
  bool handled = false;
  if (callUserHandler) {
    handled = callUserErrorHandler(ee, errnum, false);
  }
  if (mode == AlwaysThrow || (mode == ThrowIfUnhandled && !handled)) {
    try {
      if (!Eval::Debugger::InterruptException(String(msg))) return;
    } catch (const Eval::DebuggerClientExitException &e) {}
    throw FatalErrorException(msg.c_str());
  }
  if (!handled &&
      (RuntimeOption::NoSilencer ||
       (getErrorReportingLevel() & errnum) != 0)) {
    try {
      if (!Eval::Debugger::InterruptException(String(msg))) return;
    } catch (const Eval::DebuggerClientExitException &e) {}

    const char *file = NULL;
    int line = 0;
    if (RuntimeOption::InjectedStackTrace) {
      ArrayPtr bt = ee.getBackTrace();
      if (!bt->empty()) {
        Array top = bt->rvalAt(0).toArray();
        if (top.exists("file")) file = top.rvalAt("file").toString();
        if (top.exists("line")) line = top.rvalAt("line");
      }
    }

    Logger::Log(Logger::LogError, prefix.c_str(), ee, file, line);
  }
}
Esempio n. 12
0
int64_t f_xml_parse(CObjRef parser, CStrRef data, bool is_final /* = true */) {
  // XML_Parse can reenter the VM, and it will do so after we've lost
  // the frame pointer by calling through the system's copy of XML_Parse
  // in libexpat.so.
  SYNC_VM_REGS_SCOPED();
  XmlParser * p = parser.getTyped<XmlParser>();
  int ret;
  long isFinal = is_final ? 1 : 0;
  p->isparsing = 1;
  ret = XML_Parse(p->parser, (const XML_Char*)data.data(), data.size(),
                  isFinal);
  p->isparsing = 0;
  return ret;
}
Esempio n. 13
0
String XMLReader::read_string_func(xmlreader_read_char_t internal_function) {
  SYNC_VM_REGS_SCOPED();
  char *retchar = nullptr;
  if (m_ptr) {
    retchar = (char *)internal_function(m_ptr);
  }
  if (retchar) {
    String ret((const char*)retchar, CopyString);
    xmlFree(retchar);
    return ret;
  } else {
    return empty_string();
  }
}
Esempio n. 14
0
Variant HHVM_METHOD(XMLReader, open,
                 const String& uri,
                 const Variant& encoding /*= null_variant*/,
                 int64_t options /*= 0*/) {
  auto* data = Native::data<XMLReader>(this_);
  const String& str_encoding = encoding.isNull()
                            ? null_string
                            : encoding.toString();
  SYNC_VM_REGS_SCOPED();
  if (data->m_ptr) {
    data->close();
  }

  if (uri.empty()) {
    raise_warning("Empty string supplied as input");
    return false;
  } else if (!FileUtil::checkPathAndWarn(uri, "XMLReader::open", 1)) {
    return init_null();
  }

  String valid_file = libxml_get_valid_file_path(uri.c_str());
  xmlTextReaderPtr reader = nullptr;

  if (!valid_file.empty()) {
    // Manually create the IO context to support custom stream wrappers.
    data->m_stream = File::Open(valid_file, "rb");
    if (data->m_stream != nullptr && !data->m_stream->isInvalid()) {
      // The XML context is owned by the native data attached to 'this_'.
      // The File is also owned by the native data so it does not need
      // to be cleaned up by an XML callback.  The libxml_streams_IO_nop_close
      // callback does nothing.
      reader = xmlReaderForIO(libxml_streams_IO_read,
                              libxml_streams_IO_nop_close,
                              &data->m_stream,
                              valid_file.data(),
                              str_encoding.data(),
                              options);
    }
  }

  if (reader == nullptr) {
    raise_warning("Unable to open source data");
    return false;
  }

  data->m_ptr = reader;

  return true;
}
Esempio n. 15
0
bool HHVM_METHOD(SQLite3, exec,
                 const String& sql) {
  auto *data = Native::data<SQLite3>(this_);
  SYNC_VM_REGS_SCOPED();
  data->validate();

  char *errtext = nullptr;
  if (sqlite3_exec(data->m_raw_db, sql.data(), nullptr, nullptr, &errtext)
      != SQLITE_OK) {
    raise_warning("%s", errtext);
    sqlite3_free(errtext);
    return false;
  }
  return true;
}
Esempio n. 16
0
bool HHVM_METHOD(XMLReader, read) {
  auto* data = Native::data<XMLReader>(this_);
  SYNC_VM_REGS_SCOPED();
  if (data->m_ptr) {
    int ret = xmlTextReaderRead(data->m_ptr);
    if (ret == -1) {
      raise_warning("An Error Occurred while reading");
      return false;
    } else {
      return ret;
    }
  }
  raise_warning("Load Data before trying to read");
  return false;
}
Esempio n. 17
0
Variant HHVM_METHOD(SQLite3, query,
                    const String& sql) {
  auto *data = Native::data<SQLite3>(this_);
  SYNC_VM_REGS_SCOPED();
  data->validate();
  if (!sql.empty()) {
    Variant stmt = HHVM_MN(SQLite3, prepare)(this_, sql);
    if (!same(stmt, false)) {
      Object obj_stmt = stmt.toObject();
      assert(obj_stmt.instanceof(SQLite3Stmt::getClass()));
      return HHVM_MN(SQLite3Stmt, execute)(obj_stmt.get());
    }
  }
  return false;
}
Esempio n. 18
0
void XMLReader::close() {
  SYNC_VM_REGS_SCOPED();
  if (m_ptr) {
    xmlFreeTextReader(m_ptr);
    m_ptr = nullptr;
  }
  if (m_input) {
    xmlFreeParserInputBuffer(m_input);
    m_input = nullptr;
  }
  if (m_schema) {
    xmlRelaxNGFree((xmlRelaxNGPtr) m_schema);
    m_schema = nullptr;
  }
}
Esempio n. 19
0
Variant HHVM_METHOD(XMLReader, getAttributeNo,
                    int64_t index) {
  auto* data = Native::data<XMLReader>(this_);
  SYNC_VM_REGS_SCOPED();
  char *retchar = nullptr;
  if (data->m_ptr) {
    retchar = (char *)xmlTextReaderGetAttributeNo(data->m_ptr, index);
  }
  if (retchar) {
    String ret((const char*)retchar, CopyString);
    xmlFree(retchar);
    return ret;
  } else {
    return init_null();
  }
}
Esempio n. 20
0
bool HHVM_METHOD(XMLReader, moveToAttribute,
                 const String& name) {
  auto* data = Native::data<XMLReader>(this_);
  SYNC_VM_REGS_SCOPED();
  if (name.empty()) {
    raise_warning("Attribute Name is required");
    return false;
  }

  if (data->m_ptr) {
    int ret = xmlTextReaderMoveToAttribute(data->m_ptr, (xmlChar *)name.data());
    if (ret == 1) {
      return true;
    }
  }
  return false;
}
Esempio n. 21
0
bool HHVM_METHOD(XMLReader, open,
                 const String& uri,
                 const Variant& encoding /*= null_variant*/,
                 int64_t options /*= 0*/) {
  auto* data = Native::data<XMLReader>(this_);
  const String& str_encoding = encoding.isNull()
                            ? null_string
                            : encoding.toString();
  SYNC_VM_REGS_SCOPED();
  if (data->m_ptr) {
    data->close();
  }

  if (uri.empty()) {
    raise_warning("Empty string supplied as input");
    return false;
  }

  String valid_file = libxml_get_valid_file_path(uri.c_str());
  xmlTextReaderPtr reader = nullptr;

  if (!valid_file.empty()) {
    // Manually create the IO context to support custom stream wrappers.
    auto stream = File::Open(valid_file, "rb");
    if (!stream->isInvalid()) {
      reader = xmlReaderForIO(libxml_streams_IO_read,
                              libxml_streams_IO_close,
                              stream.get(),
                              valid_file.data(),
                              str_encoding.data(),
                              options);
      // The xmlTextReaderPtr owns a reference to stream.
      if (reader) stream.get()->incRefCount();
    }
  }

  if (reader == nullptr) {
    raise_warning("Unable to open source data");
    return false;
  }

  data->m_ptr = reader;

  return true;
}
Esempio n. 22
0
bool HHVM_METHOD(XMLReader, setSchema,
                 const String& source) {
  auto* data = Native::data<XMLReader>(this_);
  SYNC_VM_REGS_SCOPED();
  if (source.empty()) {
    raise_warning("Schema data source is required");
    return false;
  }

  if (data->m_ptr) {
    int ret = xmlTextReaderSchemaValidate(data->m_ptr, source.c_str());
    if (ret == 0) {
      return true;
    }
  }
  raise_warning("Unable to set schema. This must be set prior to reading or schema contains errors.");
  return false;
}
Esempio n. 23
0
bool HHVM_METHOD(XMLReader, moveToAttributeNs,
                 const String& name,
                 const String& namespaceURI) {
  auto* data = Native::data<XMLReader>(this_);
  SYNC_VM_REGS_SCOPED();
  if (name.empty() || namespaceURI.empty()) {
    raise_warning("Attribute Name and Namespace URI cannot be empty");
    return false;
  }
  if (data->m_ptr) {
    int ret = xmlTextReaderMoveToAttributeNs(data->m_ptr,
                                             (xmlChar *)name.data(),
                                             (xmlChar *)namespaceURI.data());
    if (ret == 1) {
      return true;
    }
  }
  return false;
}
Esempio n. 24
0
Variant XMLReader::string_func_string_arg(String value,
    xmlreader_read_one_char_t internal_function) {
  SYNC_VM_REGS_SCOPED();

  if (value.empty()) {
    raise_warning("Argument cannot be an empty string");
    return false;
  }

  char *retchar = nullptr;
  if (m_ptr) {
    retchar = (char *)internal_function(m_ptr, (const unsigned char *)value.data());
  }

  if (retchar) {
    String ret((const char*)retchar, CopyString);
    xmlFree(retchar);
    return ret;
  } else {
    return init_null();
  }
}
Esempio n. 25
0
Variant HHVM_METHOD(XMLReader, expand,
                    const Variant& basenode /* = null */) {
  auto* data = Native::data<XMLReader>(this_);
  Object doc;
  xmlDocPtr docp = nullptr;
  SYNC_VM_REGS_SCOPED();

  if (!basenode.isNull()) {
    DOMNode *dombasenode = toDOMNode(basenode.toObject().get());
    doc = dombasenode->doc();
    docp = (xmlDocPtr) toDOMNode(doc.get())->m_node;
    if (docp == nullptr) {
      raise_warning("Invalid State Error");
      return false;
    }
  } else {
    doc = DOMDocument::newInstance();
  }

  if (data->m_ptr) {
    xmlNodePtr node = xmlTextReaderExpand(data->m_ptr);
    if (node == nullptr) {
      raise_warning("An Error Occurred while expanding");
      return false;
    } else {
      xmlNodePtr nodec = xmlDocCopyNode(node, docp, 1);
      if (nodec == nullptr) {
        raise_notice("Cannot expand this node type");
        return false;
      } else {
        return php_dom_create_object(nodec, doc, false);
      }
    }
  }

  raise_warning("Load Data before trying to read");
  return false;
}
Esempio n. 26
0
Variant HHVM_METHOD(SQLite3, querysingle,
                    const String& sql,
                    bool entire_row /* = false */) {
  auto *data = Native::data<SQLite3>(this_);
  SYNC_VM_REGS_SCOPED();
  data->validate();
  if (!sql.empty()) {
    Variant stmt = HHVM_MN(SQLite3, prepare)(this_, sql);
    if (!same(stmt, false)) {
      Object obj_stmt = stmt.toObject();
      assert(obj_stmt.instanceof(SQLite3Stmt::getClass()));
      sqlite3_stmt *pstmt =
        Native::data<SQLite3Stmt>(obj_stmt)->m_raw_stmt;
      switch (sqlite3_step(pstmt)) {
      case SQLITE_ROW: /* Valid Row */
        if (entire_row) {
          Array ret = Array::Create();
          for (int i = 0; i < sqlite3_data_count(pstmt); i++) {
            ret.set(String((char*)sqlite3_column_name(pstmt, i), CopyString),
                    get_column_value(pstmt, i));
          }
          return ret;
        }
        return get_column_value(pstmt, 0);
      case SQLITE_DONE: /* Valid but no results */
        if (entire_row) {
          return empty_array();
        } else {
          return init_null();
        }
      default:
        raise_warning("Unable to execute statement: %s",
                      sqlite3_errmsg(data->m_raw_db));
      }
    }
  }
  return false;
}
Esempio n. 27
0
static void HHVM_METHOD(XSLTProcessor, importStylesheet,
                        const Object& stylesheet) {
  SYNC_VM_REGS_SCOPED();

  auto data = Native::data<XSLTProcessorData>(this_);
  xmlDocPtr doc = nullptr;

  if (stylesheet.instanceof(s_DOMDocument)) {
    auto domdoc = Native::data<DOMNode>(stylesheet);
    // This doc will be freed by xsltFreeStylesheet.
    doc = xmlCopyDoc((xmlDocPtr)domdoc->nodep(), /*recursive*/ 1);
    if (doc == nullptr) {
      raise_error("Unable to import stylesheet");
    }
  } else if (stylesheet.instanceof(c_SimpleXMLElement::classof())) {
    auto elem = cast<c_SimpleXMLElement>(stylesheet);
    // This doc will be freed by xsltFreeStylesheet.
    doc = xmlNewDoc((const xmlChar*)"1.0");
    xmlNodePtr node = xmlCopyNode(elem->nodep(), /*extended*/ 1);
    if (doc == nullptr || node == nullptr) {
      raise_error("Unable to import stylesheet");
    }
    xmlDocSetRootElement(doc, node);
  } else {
    raise_error("Object must be an instance of DOMDocument or "
                "SimpleXMLElement");
  }

  if (doc) {
    data->m_stylesheet = xsltParseStylesheetDoc(doc);
    if (data->m_stylesheet == nullptr) {
      xmlFreeDoc(doc);
      raise_error("Unable to import stylesheet");
    }
  }
}
Esempio n. 28
0
xmlDocPtr c_XSLTProcessor::apply_stylesheet() {
  SYNC_VM_REGS_SCOPED();

  if (m_stylesheet == nullptr || m_doc == nullptr) {
    raise_error("Unable to apply stylesheet");
    return nullptr;
  }

  xsltTransformContextPtr ctxt = xsltNewTransformContext (m_stylesheet, m_doc);
  if (ctxt == nullptr) {
    raise_error("Unable to apply stylesheet");
    return nullptr;
  }

  ctxt->_private = this;

  xsltSecurityPrefsPtr prefs = nullptr;
  if (m_secprefs != k_XSL_SECPREF_NONE) {
    prefs = xsltNewSecurityPrefs();
    int error = 0;

    if (m_secprefs & k_XSL_SECPREF_READ_FILE) {
      if (xsltSetSecurityPrefs(prefs,
                               XSLT_SECPREF_READ_FILE,
                               xsltSecurityForbid) != 0) {
        error = 1;
      }
    }

    if (m_secprefs & k_XSL_SECPREF_WRITE_FILE) {
      if (xsltSetSecurityPrefs(prefs,
                               XSLT_SECPREF_WRITE_FILE,
                               xsltSecurityForbid) != 0) {
        error = 1;
      }
    }

    if (m_secprefs & k_XSL_SECPREF_CREATE_DIRECTORY) {
      if (xsltSetSecurityPrefs(prefs,
                               XSLT_SECPREF_CREATE_DIRECTORY,
                               xsltSecurityForbid) != 0) {
        error = 1;
      }
    }

    if (m_secprefs & k_XSL_SECPREF_READ_NETWORK) {
      if (xsltSetSecurityPrefs(prefs,
                               XSLT_SECPREF_READ_NETWORK,
                               xsltSecurityForbid) != 0) {
        error = 1;
      }
    }

    if (m_secprefs & k_XSL_SECPREF_WRITE_NETWORK) {
      if (xsltSetSecurityPrefs(prefs,
                               XSLT_SECPREF_WRITE_NETWORK,
                               xsltSecurityForbid) != 0) {
        error = 1;
      }
    }

    if (xsltSetCtxtSecurityPrefs(prefs, ctxt) != 0) {
      error = 1;
    }

    if (error == 1) {
      raise_error("Can't set libxslt security properties, not doing "
                  "transformation for security reasons");
      return nullptr;
    }
  }

  xsltRegisterExtFunction(ctxt,
    (const xmlChar*) "functionString",
    (const xmlChar*) "http://php.net/xsl",
    xslt_ext_function_string_php
  );

  xsltRegisterExtFunction(ctxt,
    (const xmlChar*) "function",
    (const xmlChar*) "http://php.net/xsl",
    xslt_ext_function_object_php
  );

  for (ArrayIter iter(m_params); iter; ++iter) {
    assert(iter.first().isString());
    assert(iter.second().isString());

    xmlChar *value = xslt_string_to_xpathexpr(iter.second().toString().c_str());
    if (value) {
      xsltEvalOneUserParam(ctxt,
        (const xmlChar*)iter.first().toString().c_str(),
        (const xmlChar*)value
      );

      xmlFree(value);
    }
  }

  FILE *profile = nullptr;
  if (m_profile) {
    profile = fopen(m_profile.data(), "w");
  }

  xmlDocPtr res = xsltApplyStylesheetUser(m_stylesheet,
                                          m_doc,
                                          nullptr,
                                          nullptr,
                                          profile,
                                          ctxt);

  if (profile) {
    fclose(profile);
  }

  xsltFreeTransformContext(ctxt);

  if (prefs) {
    xsltFreeSecurityPrefs(prefs);
  }

  return res;
}