diff --git a/CMakeLists.txt b/CMakeLists.txt index df3b16ea5fd8ea39d587fe3bad2cbfe8bf4d7e67..5637038fe12191d1b45cdc0e4804a8759004361f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8.12) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMakeModules") -find_package(IRODS 4.2.6 EXACT REQUIRED) +find_package(IRODS 4.2.8 EXACT REQUIRED) message(STATUS "Building for irods-server version ${IRODS_VERSION}") @@ -10,9 +10,9 @@ message(STATUS "Building for irods-server version ${IRODS_VERSION}") # The following packages need to be installed to build the uu microservices: # # irods-externals-clang-runtime3.8-0 -# irods-externals-clang3.8-0 +# irods-externals-clang6.0-0 -set(UU_RELEASE_VERSION "0.8.0") +set(UU_RELEASE_VERSION "0.8.2") set(CMAKE_CXX_COMPILER ${IRODS_EXTERNALS_FULLPATH_CLANG}/bin/clang++) @@ -46,12 +46,6 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIR}) find_package(CURL REQUIRED) include_directories(SYSTEM ${CURL_INCLUDE_DIRS}) -find_package(LibXml2 REQUIRED) -include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR}) - -find_package(LibXslt REQUIRED) -include_directories(SYSTEM ${LIBXSLT_INCLUDE_DIR}) - find_package(Jansson REQUIRED) include_directories(SYSTEM ${JANSSON_INCLUDE_DIRS}) @@ -62,31 +56,20 @@ include_directories(SYSTEM "/usr/include/irods") add_library(msiSetUpperCaseWhereQuery SHARED src/msiSetUpperCaseWhereQuery.cc) add_library(msiStrToUpper SHARED src/msiStrToUpper.cc) -add_library(msiCurlMail SHARED src/msiCurlMail.cc) add_library(msiRegisterDataCiteDOI SHARED src/msiRegisterDataCiteDOI.cc) -add_library(msiGenerateRandomID SHARED src/msiGenerateRandomID.cc) -add_library(msiGenerateUUID SHARED src/msiGenerateUUID.cc) add_library(msiRegisterEpicPID SHARED src/msiRegisterEpicPID.cc) add_library(msiGetDataCiteDOI SHARED src/msiGetDataCiteDOI.cc) add_library(msiRemoveDataCiteMetadata SHARED src/msiRemoveDataCiteMetadata.cc) -add_library(msiLoadMetadataFromXml SHARED src/msiLoadMetadataFromXml.cc) -add_library(msiXmlDocSchemaValidate SHARED src/msiXmlDocSchemaValidate.cc) -add_library(msiXsltApply SHARED src/msiXsltApply.cc) add_library(msi_json_arrayops SHARED src/msi_json_arrayops.cc) add_library(msi_json_objops SHARED src/msi_json_objops.cc) add_library(msi_add_avu SHARED src/msi_add_avu.cpp) add_library(msi_rmw_avu SHARED src/msi_rmw_avu.cpp) -target_link_libraries(msiCurlMail LINK_PUBLIC ${CURL_LIBRARIES} ${JANSSON_LIBRARIES}) target_link_libraries(msiStrToUpper LINK_PUBLIC ${Boost_LIBRARIES}) target_link_libraries(msiRegisterDataCiteDOI LINK_PUBLIC ${CURL_LIBRARIES} ${JANSSON_LIBRARIES}) -target_link_libraries(msiGenerateUUID LINK_PUBLIC ${UUID_LIBRARIES}) target_link_libraries(msiRegisterEpicPID LINK_PUBLIC ${CURL_LIBRARIES} ${JANSSON_LIBRARIES} ${UUID_LIBRARIES}) target_link_libraries(msiGetDataCiteDOI LINK_PUBLIC ${CURL_LIBRARIES} ${JANSSON_LIBRARIES}) target_link_libraries(msiRemoveDataCiteMetadata LINK_PUBLIC ${CURL_LIBRARIES} ${JANSSON_LIBRARIES}) -target_link_libraries(msiLoadMetadataFromXml LINK_PUBLIC ${LIBXML2_LIBRARIES}) -target_link_libraries(msiXmlDocSchemaValidate LINK_PUBLIC ${LIBXML2_LIBRARIES}) -target_link_libraries(msiXsltApply LINK_PUBLIC ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${LIBXSLT_EXSLT_LIBRARIES}) target_link_libraries(msi_json_arrayops LINK_PUBLIC ${JANSSON_LIBRARIES} ${Boost_LIBRARIES}) target_link_libraries(msi_json_objops LINK_PUBLIC ${JANSSON_LIBRARIES} ${Boost_LIBRARIES}) target_link_libraries(msi_add_avu LINK_PUBLIC ${Boost_LIBRARIES}) @@ -95,18 +78,12 @@ target_link_libraries(msi_rmw_avu LINK_PUBLIC ${Boost_LIBRARIES}) install(TARGETS msiSetUpperCaseWhereQuery msiStrToUpper - msiCurlMail - msiRegisterDataCiteDOI - msiGenerateRandomID - msiGenerateUUID - msiRegisterEpicPID - msiGetDataCiteDOI - msiRemoveDataCiteMetadata - msiLoadMetadataFromXml - msiXmlDocSchemaValidate - msiXsltApply - msi_json_arrayops - msi_json_objops + msiRegisterDataCiteDOI + msiRegisterEpicPID + msiGetDataCiteDOI + msiRemoveDataCiteMetadata + msi_json_arrayops + msi_json_objops msi_add_avu msi_rmw_avu DESTINATION diff --git a/README.md b/README.md index c38eb6fca1606fd99a7e1bb8b19be40aa9730dab..e3e5c32425d2eed06ca51508f2a47bd40af6e2fb 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,6 @@ Developed at Utrecht University: * msiSetUpperCaseWhereQuery: Set the UPPERCASE flag on a irods query. * msiGenerateRandomID: Generate a Random ID to use as basis for a new DOI -Forward ported from iRODS 3: - * msiLoadMetadataFromXml: - load metadata from an xml file. Modified to accept both irods data objects as string buffers. Also skips AVU's exceeding the iRODS byte limit - * msiXsltApply: apply a XSLT to and XML. Modified to handle invalid input without crashing and added exslt support - * msiXmlDocSchemaValidate: Validate an XML against an XSD - Developed at Donders Institute: * msi\_json\_objops: get, add and set values in a json object * msi\_json\_arrayops: get, add and set values in a json array. modified to handle arrays of arrays @@ -39,20 +33,17 @@ To build from source, the following build-time dependencies must be installed: - `gcc-c++` - `irods-devel` - `irods-externals-cmake3.5.2-0` -- `irods-externals-clang3.8-0` +- `irods-externals-clang6.0-0` - `boost-devel` - `boost-locale` - `openssl-devel` - `libcurl-devel` - `libuuid-devel` -- `libxml2-devel` -- `libxslt-devel` - `jansson-devel` -- `libuuid-devel` - `rpmdevtools` (if you are creating an RPM) ``` -sudo yum install make gcc-c++ irods-devel irods-externals-cmake3.5.2-0 irods-externals-clang3.8-0 boost-devel boost-locale openssl-devel libcurl-devel libxml2-devel libxslt-devel jansson-devel libuuid-devel rpmdevtools +sudo yum install make gcc-c++ irods-devel irods-externals-cmake3.5.2-0 irods-externals-clang6.0-0 boost-devel boost-locale openssl-devel libcurl-devel jansson-devel libuuid-devel rpmdevtools ``` Follow these instructions to build from source: diff --git a/src/msiCurlMail.cc b/src/msiCurlMail.cc deleted file mode 100644 index d507bfdb485b8b0d8bf3fb60fde9c1c1531b808e..0000000000000000000000000000000000000000 --- a/src/msiCurlMail.cc +++ /dev/null @@ -1,249 +0,0 @@ -/** - * \file - * \brief iRODS microservice to send an email. - * \author Lazlo Westerhof - * \copyright Copyright (c) 2018, Utrecht University - * - * This file is part of irods-uu-microservices. - * - * irods-uu-microservices is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the License, - * or (at your option) any later version. - * - * irods-uu-microservices is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with irods-uu-microservices. - * If not, see <http://www.gnu.org/licenses/>. - */ - -#include "irods_includes.hh" -#include "CredentialsStore.hh" - -#include <ctime> -#include <string> -#include <curl/curl.h> - -static CredentialsStore credentials; - -std::string dateTimeNow() -{ - const int RFC5322_TIME_LEN = 32; - - std::string ret; - ret.resize(RFC5322_TIME_LEN); - - tm tv, *t = &tv; - time_t tt = time(&tt); - localtime_r(&tt, t); - - strftime(&ret[0], RFC5322_TIME_LEN, "%a, %d %b %Y %H:%M:%S %z", t); - - return ret; -} - -std::string messageId() -{ - const int MESSAGE_ID_LEN = 37; - - tm t; - time_t tt; - time(&tt); - - std::string ret; - ret.resize(15); - - gmtime_r(&tt, &t); - - strftime(const_cast<char *>(ret.c_str()), - MESSAGE_ID_LEN, - "%Y%m%d%H%M%S.", - &t); - - ret.reserve(MESSAGE_ID_LEN); - - static const char alphaNum[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - - while (ret.size() < MESSAGE_ID_LEN) { - ret += alphaNum[(size_t) rand() % (sizeof(alphaNum) - 1)]; - } - - return ret; -} - -std::string setPayloadText(const std::string &to, - const std::string &from, - const std::string &nameFrom, - const std::string &subject, - const std::string &replyTo, - const std::string &body) -{ - std::string ret; - - ret += "Date: " + dateTimeNow() + ">\r\n"; - ret += "To: <" + to + ">\r\n"; - ret += "From: <" + from + "> (" + nameFrom + ")\r\n"; - ret += "Message-ID: <" + messageId() + "@" + from.substr(from.find('@') + 1) + ">\r\n"; - ret += "Subject: " + subject + "\r\n"; - ret += "Reply-To: <" + replyTo + ">\r\n"; - ret += "\r\n"; - ret += body + "\r\n"; - ret += "\r\n"; - ret += "\r\n"; - ret += "\r\n"; - - return ret; -} - -struct uploadStatus { int linesRead; }; - -struct StringData -{ - std::string msg; - size_t bytesleft; - - StringData(std::string &&m) : msg{ m }, bytesleft{ msg.size() } {} - StringData(std::string &m) = delete; -}; - -size_t payloadSource(void *ptr, size_t size, size_t nmemb, void *userp) -{ - StringData *text = reinterpret_cast<StringData *>(userp); - - if ((size == 0) || (nmemb == 0) || ((size*nmemb) < 1) || (text->bytesleft == 0)) { - return 0; - } - - if ((nmemb * size) >= text->msg.size()) { - text->bytesleft = 0; - return text->msg.copy(reinterpret_cast<char *>(ptr), text->msg.size()); - } - - return 0; -} - -CURLcode sendMail(const std::string to, - const std::string from, - const std::string nameFrom, - const std::string subject, - const std::string replyTo, - const std::string body, - const std::string smtpServer, - const std::string userName, - const std::string password) -{ - CURLcode res = CURLE_OK; - - struct curl_slist *recipients = NULL; - - /* Get a curl handle. */ - CURL *curl = curl_easy_init(); - - StringData textData { setPayloadText(to, from, nameFrom, subject, replyTo, body) }; - - if (curl) { - curl_easy_setopt(curl, CURLOPT_USERNAME, userName.c_str()); - curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str()); - curl_easy_setopt(curl, CURLOPT_URL, smtpServer.c_str()); - - curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); - - curl_easy_setopt(curl, CURLOPT_MAIL_FROM, ("<" + from + ">").c_str()); - recipients = curl_slist_append(recipients, ("<" + to + ">").c_str()); - - curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); - curl_easy_setopt(curl, CURLOPT_READFUNCTION, payloadSource); - curl_easy_setopt(curl, CURLOPT_READDATA, &textData); - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); - - /* Perform the request, res will get the return code. */ - res = curl_easy_perform(curl); - - /* Check for errors. */ - if (res != CURLE_OK) { - rodsLog(LOG_ERROR, "msiCurlMail: curl error: %s", curl_easy_strerror(res)); - } - - curl_slist_free_all(recipients); - curl_easy_cleanup(curl); - } - - return res; -} - -extern "C" { - int msiCurlMail(msParam_t* toIn, - msParam_t* subjectIn, - msParam_t* bodyIn, - msParam_t* curlCodeOut, - ruleExecInfo_t *rei) - { - int curlCode = 0; - - /* Check if user is priviliged. */ - if (rei->uoic->authInfo.authFlag < LOCAL_PRIV_USER_AUTH) { - return SYS_USER_NO_PERMISSION; - } - - /* Bail early if the credential store could not be loaded */ - if (!credentials.isLoaded()) { - return SYS_CONFIG_FILE_ERR; - } - - /* Check input parameters. */ - if (strcmp(toIn->type, STR_MS_T)) { - return SYS_INVALID_INPUT_PARAM; - } - if (strcmp(subjectIn->type, STR_MS_T)) { - return SYS_INVALID_INPUT_PARAM; - } - if (strcmp(bodyIn->type, STR_MS_T)) { - return SYS_INVALID_INPUT_PARAM; - } - - /* Parse input paramaters. */ - std::string to = parseMspForStr(toIn); - std::string subject = parseMspForStr(subjectIn); - std::string body = parseMspForStr(bodyIn); - - /* obtain parameters from the credentials store */ - std::string from(credentials.get("notifications_sender_email")); - std::string nameFrom(credentials.get("notifications_sender_name")); - std::string replyTo(credentials.get("notifications_reply_to")); - std::string smtpServer(credentials.get("smtp_server")); - std::string smtpUserName(credentials.get("smtp_username")); - std::string smtpPassword(credentials.get("smtp_password")); - - curlCode = sendMail(to, from, nameFrom, subject, replyTo, body, smtpServer, smtpUserName, smtpPassword); - - fillStrInMsParam(curlCodeOut, std::to_string(curlCode).c_str()); - - return 0; - } - - irods::ms_table_entry* plugin_factory() { - irods::ms_table_entry *msvc = new irods::ms_table_entry(4); - - msvc->add_operation< - msParam_t*, - msParam_t*, - msParam_t*, - msParam_t*, - ruleExecInfo_t*>("msiCurlMail", - std::function<int( - msParam_t*, - msParam_t*, - msParam_t*, - msParam_t*, - ruleExecInfo_t*)>(msiCurlMail)); - - return msvc; - } -} diff --git a/src/msiGenerateRandomID.cc b/src/msiGenerateRandomID.cc deleted file mode 100644 index 2868dd2b6e589c36825f6e332a2a44d26eb0e521..0000000000000000000000000000000000000000 --- a/src/msiGenerateRandomID.cc +++ /dev/null @@ -1,93 +0,0 @@ -/** - * \file - * \brief iRODS microservice to generate a randam ID of x digits and (capital) letters - * \author Lazlo Westerhof - * \author Paul Frederiks - * \copyright Copyright (c) 2017, Utrecht University - * - * Copyright (c) 2017, Utrecht University - * - * This file is part of irods-uu-microservices. - * - * irods-uu-microservices is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the License, - * or (at your option) any later version. - * - * irods-uu-microservices is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with irods-uu-microservices. - * If not, see <http://www.gnu.org/licenses/>. - */ - -#include "irods_includes.hh" - -#include <string> -#include <vector> -#include <random> -#include <functional> -#include <algorithm> - -extern "C" { - int msiGenerateRandomID(msParam_t* lengthIn, - msParam_t* randomIdOut, - ruleExecInfo_t *rei) - { - /* Check input parameters. */ - if (strcmp(lengthIn->type, INT_MS_T)) { - return SYS_INVALID_INPUT_PARAM; - } - - /* Define character set to use in YoDa random ID. */ - std::vector<char> charSet = { - '0','1','2','3','4', - '5','6','7','8','9', - 'A','B','C','D','E','F', - 'G','H','I','J','K', - 'L','M','N','O','P', - 'Q','R','S','T','U', - 'V','W','X','Y','Z', - }; - - /* Create a non-deterministic random number generator. */ - std::random_device seed; - std::default_random_engine rng(seed()); - - /* Generate uniform integer distribution, to transform a random number into integer - in the closed interval of [0, charSet.size()-1] */ - std::uniform_int_distribution<> dist(0, (int)charSet.size()-1); - - /* Create a non-deterministic uniform distribution of the YoDa ID character set. */ - auto randChar = [charSet, &dist, &rng](){return charSet[dist(rng)];}; - - /* Set the length of the random string. */ - int length = parseMspForPosInt(lengthIn); - std::string randomStr(length, 0); - - /* Generate the random string. */ - std::generate_n(randomStr.begin(), length, randChar); - - fillStrInMsParam(randomIdOut, randomStr.c_str()); - - return 0; - } - - irods::ms_table_entry* plugin_factory() { - irods::ms_table_entry *msvc = new irods::ms_table_entry(2); - - msvc->add_operation< - msParam_t*, - msParam_t*, - ruleExecInfo_t*>("msiGenerateRandomID", - std::function<int( - msParam_t*, - msParam_t*, - ruleExecInfo_t*)>(msiGenerateRandomID)); - - return msvc; - } -} diff --git a/src/msiGenerateUUID.cc b/src/msiGenerateUUID.cc deleted file mode 100644 index ce0f8c506733f585e129e04e3fa9cd11613f2740..0000000000000000000000000000000000000000 --- a/src/msiGenerateUUID.cc +++ /dev/null @@ -1,57 +0,0 @@ -/** - * \file - * \brief iRODS microservice to generate a UUID. - * \author Felix Croes - * \copyright Copyright (c) 2018, Utrecht University - * - * This file is part of irods-uu-microservices. - * - * irods-uu-microservices is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the License, - * or (at your option) any later version. - * - * irods-uu-microservices is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with irods-uu-microservices. - * If not, see <http://www.gnu.org/licenses/>. - */ - -#include "irods_includes.hh" - -//#include <fstream> -//#include <streambuf> -#include <uuid/uuid.h> - -extern "C" { - - int msiGenerateUUID(msParam_t* UUIDOut, - ruleExecInfo_t *rei) - { - /* generate UUID. */ - uuid_t uuid; - char buffer[37]; - uuid_generate(uuid); - uuid_unparse_upper(uuid, buffer); - fillStrInMsParam(UUIDOut, buffer); - - return 0; - } - - irods::ms_table_entry* plugin_factory() { - irods::ms_table_entry *msvc = new irods::ms_table_entry(1); - - msvc->add_operation< - msParam_t*, - ruleExecInfo_t*>("msiGenerateEpicPID", - std::function<int( - msParam_t*, - ruleExecInfo_t*)>(msiGenerateUUID)); - - return msvc; - } -} diff --git a/src/msiLoadMetadataFromXml.cc b/src/msiLoadMetadataFromXml.cc deleted file mode 100644 index f80bc93266a624bda4cdd2207a7932ed5d725c9b..0000000000000000000000000000000000000000 --- a/src/msiLoadMetadataFromXml.cc +++ /dev/null @@ -1,398 +0,0 @@ -/** - * @file msiLoadMetadataFromXml.cc - * - */ - -/*** Copyright (c), The Regents of the University of California *** - *** For more information please refer to files in the COPYRIGHT directory ***/ - -#include <libxml/tree.h> -#include <libxml/parser.h> -#include <libxml/xpath.h> -#include <libxml/xpathInternals.h> -#include <libxml/xmlschemas.h> -#include <libxml/uri.h> -#include "irods_ms_plugin.hpp" -#include "objMetaOpr.hpp" -#include "miscUtil.h" -#include "rcMisc.h" -#include "rsObjStat.hpp" -#include "rsDataObjOpen.hpp" -#include "rsDataObjRead.hpp" -#include "rsDataObjClose.hpp" -#include "rsModAVUMetadata.hpp" - -#include "irods_error.hpp" -#include "irods_ms_plugin.hpp" - - - - - -/* get the first child node with a given name */ -static xmlNodePtr -getChildNodeByName(xmlNodePtr cur, char *name) -{ - if (cur == NULL || name == NULL) - { - return NULL; - } - - for(cur=cur->children; cur != NULL; cur=cur->next) - { - if(cur->name && (strcmp((char*)cur->name, name) == 0)) - { - return cur; - } - } - - return NULL; -} - - - -/** - * \fn msiLoadMetadataFromXml (msParam_t *targetObj, msParam_t *xmlObj, ruleExecInfo_t *rei) - * - * \brief This microservice parses an XML iRODS file to extract metadata tags. - * - * \module XML - * - * \since pre-2.1 - * - * \author Antoine de Torcy - * \date 2008/05/29 - * - * \usage See clients/icommands/test/rules3.0/ - * - * \param[in] targetObj - Optional - a msParam of type DataObjInp_MS_T or STR_MS_T - * \param[in] xmlObj - a msParam of type DataObjInp_MS_T or STR_MS_T - * \param[in,out] rei - The RuleExecInfo structure that is automatically - * handled by the rule engine. The user does not include rei as a - * parameter in the rule invocation. - * - * \DolVarDependence None - * \DolVarModified None - * \iCatAttrDependence None - * \iCatAttrModified None - * \sideeffect None - * - * \return integer - * \retval 0 on success - * \pre None - * \post None - * \sa None -**/ - -extern "C" { -#if defined(LIBXML_XPATH_ENABLED) && \ - defined(LIBXML_SAX1_ENABLED) && \ - defined(LIBXML_OUTPUT_ENABLED) - -int -msiLoadMetadataFromXml(msParam_t *targetObj, msParam_t *xmlParam, ruleExecInfo_t *rei) -{ - /* for parsing msParams and to open iRODS objects */ - dataObjInp_t xmlDataObjInp, *myXmlDataObjInp; - dataObjInp_t targetObjInp, *myTargetObjInp; - int xmlObjID; - bytesBuf_t * xmlBuf; - - /* for getting size of objects to read from */ - rodsObjStat_t *rodsObjStatOut = NULL; - - /* for reading from iRODS objects */ - openedDataObjInp_t openedDataObjInp; - - /* misc. to avoid repeating rei->rsComm */ - rsComm_t *rsComm; - - /* for xml parsing */ - xmlDocPtr doc; - xmlChar* xmlXmlChar; - - /* for XPath evaluation */ - xmlXPathContextPtr xpathCtx; - xmlXPathObjectPtr xpathObj; - xmlChar xpathExpr[] = "//AVU"; - xmlNodeSetPtr nodes; - int avuNbr, i; - - /* for new AVU creation */ - modAVUMetadataInp_t modAVUMetadataInp; - char attribute[] = "Attribute"; - char value[] = "Value"; - char unit[] = "Unit"; - char target[] = "Target"; - char add[] = "add"; - char collection[] = "-C"; - char dataObject[] = "-d"; - const size_t MAX_ATTR_NAME_LEN = 2700; - const size_t MAX_ATTR_VALUE_LEN = 2700; - const size_t MAX_ATTR_UNIT_LEN = 250; - char* attrName; - char* attrValue; - char* attrUnit; - size_t attrNameLen, attrValueLen, attrUnitLen; - rodsLong_t coll_id; - - - - /********************************* USUAL INIT PROCEDURE **********************************/ - - /* For testing mode when used with irule --test */ - RE_TEST_MACRO (" Calling msiLoadMetadataFromXml") - - - /* Sanity checks */ - if (rei == NULL || rei->rsComm == NULL) - { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: input rei or rsComm is NULL."); - return (SYS_INTERNAL_NULL_INPUT_ERR); - } - - rsComm = rei->rsComm; - - - - /********************************** RETRIEVE INPUT PARAMS **************************************/ - - /* Get path of target object */ - rei->status = parseMspForDataObjInp (targetObj, &targetObjInp, &myTargetObjInp, 0); - if (rei->status < 0) - { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: input targetObj error. status = %d", rei->status); - return (rei->status); - } - - - - - - if ( strcmp( xmlParam->type, BUF_LEN_MS_T) == 0 && xmlParam->inpOutBuf != NULL) { - - xmlBuf = xmlParam->inpOutBuf; - xmlXmlChar = xmlCharStrndup((char*)xmlBuf->buf, xmlBuf->len); - - } else if ( strcmp( xmlParam->type, STR_MS_T) == 0 || strcmp( xmlParam->type, DataObjInp_MS_T) == 0) { - - /* Get path of XML document */ - rei->status = parseMspForDataObjInp (xmlParam, &xmlDataObjInp, &myXmlDataObjInp, 0); - if (rei->status < 0) - { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: input xmlObj error. status = %d", rei->status); - return (rei->status); - } - - /******************************** OPEN AND READ FROM XML OBJECT ********************************/ - - /* Open XML file */ - if ((xmlObjID = rsDataObjOpen(rsComm, &xmlDataObjInp)) < 0) - { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: Cannot open XML data object. status = %d", xmlObjID); - return (xmlObjID); - } - - /* Get size of XML file */ - rei->status = rsObjStat (rsComm, &xmlDataObjInp, &rodsObjStatOut); - if (rei->status < 0 || !rodsObjStatOut) - { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: Cannot stat XML data object. status = %d", rei->status); - return (rei->status); - } - - /* xmlBuf init */ - /* memory for xmlBuf->buf is allocated in rsFileRead() */ - xmlBuf = (bytesBuf_t *) malloc (sizeof (bytesBuf_t)); - memset (xmlBuf, 0, sizeof (bytesBuf_t)); - - /* Read XML file */ - memset (&openedDataObjInp, 0, sizeof (openedDataObjInp_t)); - openedDataObjInp.l1descInx = xmlObjID; - openedDataObjInp.len = (int)rodsObjStatOut->objSize; - - rei->status = rsDataObjRead (rsComm, &openedDataObjInp, xmlBuf); - - xmlXmlChar = xmlCharStrndup((char*)xmlBuf->buf, xmlBuf->len); - - /* Close XML file */ - rei->status = rsDataObjClose (rsComm, &openedDataObjInp); - /* cleanup */ - freeRodsObjStat (rodsObjStatOut); - - } else { - rei->status = USER_PARAM_TYPE_ERR; - return (rei->status); - } - /******************************** PARSE XML DOCUMENT ********************************/ - - xmlSubstituteEntitiesDefault(1); - xmlLoadExtDtdDefaultValue = 1; - - - /* Parse xmlBuf.buf into an xmlDocPtr */ - doc = xmlParseDoc(xmlXmlChar); - free(xmlXmlChar); - - /* Create xpath evaluation context */ - xpathCtx = xmlXPathNewContext(doc); - if(xpathCtx == NULL) - { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: Unable to create new XPath context."); - xmlFreeDoc(doc); - return(-1); - } - - - /* Evaluate xpath expression */ - xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); - if(xpathObj == NULL) - { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: Unable to evaluate XPath expression \"%s\".", xpathExpr); - xmlXPathFreeContext(xpathCtx); - xmlFreeDoc(doc); - return(-1); - } - - /* How many AVU nodes did we get? */ - if ((nodes = xpathObj->nodesetval) != NULL) - { - avuNbr = nodes->nodeNr; - } - else - { - avuNbr = 0; - } - - - - /******************************** CREATE AVU TRIPLETS ********************************/ - - /* Add a new AVU for each node. It's ok to process the nodes in forward order since we're not modifying them */ - for(i = 0; i < avuNbr; i++) - { - if (nodes->nodeTab[i]) - { - - attrName = (char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], attribute)); - if (!attrName) { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: AVU does not contain an <Attribute> element"); - continue; - } - attrNameLen = strlen(attrName); - if (attrNameLen > MAX_ATTR_NAME_LEN) { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: attribute name for AVU #%d is too large (%d>%d)", - i + 1, attrNameLen, MAX_ATTR_NAME_LEN, attrName); - continue; - } else if (attrNameLen == 0) { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: attribute name for AVU #%d is empty", - i + 1); - continue; - } - - attrValue = (char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], value)); - if (!attrValue) { - rodsLog(LOG_ERROR, "msiLoadMetadataFromXml: AVU #%d does not contain a <Value> element", - i + 1); - continue; - } - attrValueLen = strlen(attrValue); - if (attrValueLen > MAX_ATTR_VALUE_LEN) { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: attribute value in AVU #%d is too large (%d>%d)", - i + 1, attrValueLen, MAX_ATTR_VALUE_LEN); - continue; - } else if (attrValueLen == 0) { - rodsLog(LOG_ERROR, "msiLoadMetadataFromXml: attribute value in AVU #%d is empty", - i + 1); - continue; - } - - attrUnit = (char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], unit)); - /* attrUnit can be null */ - if (attrUnit) { - attrUnitLen = strlen(attrUnit); - if (attrUnitLen > MAX_ATTR_UNIT_LEN) { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: attribute unit in AVU #%d is too large (%d>%d)", - i + 1, attrUnitLen, MAX_ATTR_UNIT_LEN, attrUnit); - continue; - } - } - - /* init modAVU input */ - memset (&modAVUMetadataInp, 0, sizeof(modAVUMetadataInp_t)); - modAVUMetadataInp.arg0 = add; - - /* Use target object if one was provided, otherwise look for it in the XML doc */ - if (strlen(myTargetObjInp->objPath) > 0) - { - modAVUMetadataInp.arg2 = myTargetObjInp->objPath; - } - else - { - modAVUMetadataInp.arg2 = xmlURIUnescapeString((char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], target)), - MAX_NAME_LEN, NULL); - } - - /* check if data or collection */ - if (isColl(rsComm, modAVUMetadataInp.arg2, &coll_id) < 0) { - modAVUMetadataInp.arg1 = dataObject; - } else { - modAVUMetadataInp.arg1 = collection; - } - - modAVUMetadataInp.arg3 = attrName; - - modAVUMetadataInp.arg4 = attrValue; - modAVUMetadataInp.arg5 = attrUnit; - /* invoke rsModAVUMetadata() */ - rei->status = rsModAVUMetadata (rsComm, &modAVUMetadataInp); - if(rei->status < 0) - { - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: rsModAVUMetadata error for %s, status=%d", - modAVUMetadataInp.arg2, rei->status); - } - } - } - - - - /************************************** WE'RE DONE **************************************/ - - /* cleanup of all xml doc */ - xmlFreeDoc(doc); - /* Don't call xmlCleanupParser when libxml2 is used again. - xmlCleanupParser(); - */ - - return (rei->status); -} - - -/* Default stub if no XPath support */ -#else -/** - * \fn msiLoadMetadataFromXml (msParam_t *targetObj, msParam_t *xmlObj, ruleExecInfo_t *rei) -**/ -int -msiLoadMetadataFromXml(msParam_t *targetObj, msParam_t *xmlObj, ruleExecInfo_t *rei) -{ - rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: XPath support not compiled in."); - return (SYS_NOT_SUPPORTED); -} -#endif - -irods::ms_table_entry * plugin_factory() { - irods::ms_table_entry* msvc = new irods::ms_table_entry(2); - msvc->add_operation< - msParam_t*, - msParam_t*, - ruleExecInfo_t*>("msiLoadMetadataFromXml", - std::function<int( - msParam_t*, - msParam_t*, - ruleExecInfo_t*)>(msiLoadMetadataFromXml)); - - return msvc; -} - -} diff --git a/src/msiXmlDocSchemaValidate.cc b/src/msiXmlDocSchemaValidate.cc deleted file mode 100644 index 501b72cac14a27f5ff2c6a6f3d888f6bcb489a5c..0000000000000000000000000000000000000000 --- a/src/msiXmlDocSchemaValidate.cc +++ /dev/null @@ -1,378 +0,0 @@ -/** - * @file msiXmlDocSchemaValidate.cpp - * - */ - -/*** Copyright (c), The Regents of the University of California *** - *** For more information please refer to files in the COPYRIGHT directory ***/ - -#include <libxml/tree.h> -#include <libxml/parser.h> -#include <libxml/xmlschemas.h> -#include <libxml/uri.h> - -#include "irods_error.hpp" -#include "irods_ms_plugin.hpp" - -#include "rsDataObjOpen.hpp" -#include "rsDataObjRead.hpp" -#include "rsDataObjClose.hpp" -#include "rsObjStat.hpp" -#include "rcMisc.h" - - -extern "C" { - - - /* custom handler to catch XML validation errors and print them to a buffer */ - static int - myErrorCallback(bytesBuf_t *errBuf, const char* errMsg, ...) - { - va_list ap; - char tmpStr[MAX_NAME_LEN]; - int written; - - va_start(ap, errMsg); - written = vsnprintf(tmpStr, MAX_NAME_LEN, errMsg, ap); - va_end(ap); - - appendToByteBuf(errBuf, tmpStr); - return (written); - } - - -/** - * \fn msiXmlDocSchemaValidate(msParam_t *xmlObj, msParam_t *xsdObj, msParam_t *status, ruleExecInfo_t *rei) - * - * \brief This microservice validates an XML file against an XSD schema, both iRODS objects. - * - * \module xml - * - * \since pre-2.1 - * - * \author Antoine de Torcy - * \date 2008/05/29 - * - * \usage See clients/icommands/test/rules3.0/ - * - * \param[in] xmlObj - a msParam of type DataObjInp_MS_T or STR_MS_T which is irods path of the XML object. - * \param[in] xsdObj - a msParam of type DataObjInp_MS_T or STR_MS_T which is irods path of the XSD object. - * \param[out] status - a msParam of type INT_MS_T which is a validation result. - * \param[in,out] rei - The RuleExecInfo structure that is automatically - * handled by the rule engine. The user does not include rei as a - * parameter in the rule invocation. - * - * \DolVarDependence None - * \DolVarModified None - * \iCatAttrDependence None - * \iCatAttrModified None - * \sideeffect None - * - * \return integer - * \retval 0 on success - * \pre None - * \post None - * \sa None -**/ -int -msiXmlDocSchemaValidate(msParam_t *xmlObj, msParam_t *xsdObj, msParam_t *status, ruleExecInfo_t *rei) -{ - /* for parsing msParams and to open iRODS objects */ - dataObjInp_t xmlObjInp, *myXmlObjInp; - dataObjInp_t xsdObjInp, *myXsdObjInp; - int xmlObjID, xsdObjID; - - /* for getting size of objects to read from */ - rodsObjStat_t *rodsObjStatOut = NULL; - - /* for reading from iRODS objects */ - openedDataObjInp_t openedDataObjInp; - bytesBuf_t *xmlBuf = NULL; - xmlChar* xmlXmlChar; - xmlChar* xsdXmlChar; - - /* for xml parsing and validating */ - xmlDocPtr doc, xsd_doc; - xmlSchemaParserCtxtPtr parser_ctxt; - xmlSchemaPtr schema; - xmlSchemaValidCtxtPtr valid_ctxt; - bytesBuf_t *errBuf; - - /* misc. to avoid repeating rei->rsComm */ - rsComm_t *rsComm; - - - - /************************************* USUAL INIT PROCEDURE **********************************/ - - /* For testing mode when used with irule --test */ - RE_TEST_MACRO (" Calling msiXmlDocSchemaValidate") - - - /* Sanity checks */ - if (rei == NULL || rei->rsComm == NULL) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: input rei or rsComm is NULL."); - return (SYS_INTERNAL_NULL_INPUT_ERR); - } - - rsComm = rei->rsComm; - - - - /************************************ ADDITIONAL INIT SETTINGS *********************************/ - - /* XML constants */ - xmlSubstituteEntitiesDefault(1); - xmlLoadExtDtdDefaultValue = 1; - - - /* allocate memory for output error buffer */ - errBuf = (bytesBuf_t *)malloc(sizeof(bytesBuf_t)); - errBuf->buf = strdup(""); - errBuf->len = strlen((char*)errBuf->buf); - - /* Default status is failure, overwrite if success */ - fillBufLenInMsParam (status, -1, NULL); - - - /********************************** RETRIEVE INPUT PARAMS **************************************/ - - /* Get path of XML document */ - rei->status = parseMspForDataObjInp (xmlObj, &xmlObjInp, &myXmlObjInp, 0); - if (rei->status < 0) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: input xmlObj error. status = %d", rei->status); - free(errBuf); - return (rei->status); - } - - - /* Get path of schema */ - rei->status = parseMspForDataObjInp (xsdObj, &xsdObjInp, &myXsdObjInp, 0); - if (rei->status < 0) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: input xsdObj error. status = %d", rei->status); - free(errBuf); - return (rei->status); - } - - - /******************************** OPEN AND READ FROM XML OBJECT ********************************/ - - /* Open XML file */ - if ((xmlObjID = rsDataObjOpen(rsComm, &xmlObjInp)) < 0) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Cannot open XML data object. status = %d", xmlObjID); - free(errBuf); - return (xmlObjID); - } - - - /* Get size of XML file */ - rei->status = rsObjStat (rsComm, &xmlObjInp, &rodsObjStatOut); - if (rei->status < 0 || !rodsObjStatOut) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Cannot stat XML data object. status = %d", rei->status); - free(errBuf); - return (rei->status); - } - - - /* xmlBuf init */ - /* memory for xmlBuf->buf is allocated in rsFileRead() */ - xmlBuf = (bytesBuf_t *) malloc (sizeof (bytesBuf_t)); - memset (xmlBuf, 0, sizeof (bytesBuf_t)); - - - /* Read content of XML file */ - memset (&openedDataObjInp, 0, sizeof (openedDataObjInp_t)); - openedDataObjInp.l1descInx = xmlObjID; - openedDataObjInp.len = (int)rodsObjStatOut->objSize; - - rei->status = rsDataObjRead (rsComm, &openedDataObjInp, xmlBuf); - - xmlXmlChar = xmlCharStrndup((char*)xmlBuf->buf, xmlBuf->len); - - /* Close XML file */ - rei->status = rsDataObjClose (rsComm, &openedDataObjInp); - - /* cleanup */ - freeRodsObjStat (rodsObjStatOut); - - /* content of xmlBuf can be discarded */ - clearBBuf(xmlBuf); - - - /*************************************** PARSE XML DOCUMENT **************************************/ - - /* Parse xmlBuf.buf into an xmlDocPtr */ - doc = xmlParseDoc(xmlXmlChar); - - if (doc == NULL) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: XML document cannot be loaded or is not well-formed."); - free(errBuf); - /* Don't call xmlCleanupParser when libxml2 will be used in other microservice calls - xmlCleanupParser(); - */ - - return (USER_INPUT_FORMAT_ERR); - } - - - - /******************************** OPEN AND READ FROM XSD OBJECT ********************************/ - - /* Open schema file */ - if ((xsdObjID = rsDataObjOpen(rsComm, &xsdObjInp)) < 0) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Cannot open XSD data object. status = %d", xsdObjID); - free(errBuf); - xmlFreeDoc(doc); - /* Don't call xmlCleanupParser when libxml2 will be used in other microservice calls - xmlCleanupParser(); - */ - return (xsdObjID); - } - - - /* Get size of schema file */ - rei->status = rsObjStat (rsComm, &xsdObjInp, &rodsObjStatOut); - - - /* Read entire schema file */ - memset (&openedDataObjInp, 0, sizeof (openedDataObjInp_t)); - openedDataObjInp.l1descInx = xsdObjID; - openedDataObjInp.len = (int)rodsObjStatOut->objSize; - - rei->status = rsDataObjRead (rsComm, &openedDataObjInp, xmlBuf); - - xsdXmlChar = xmlCharStrndup((char*)xmlBuf->buf, xmlBuf->len); - - /* Close schema file */ - rei->status = rsDataObjClose (rsComm, &openedDataObjInp); - - /* cleanup */ - freeRodsObjStat (rodsObjStatOut); - - /* xmlBuf is no longer needed */ - freeBBuf(xmlBuf); - - /*************************************** PARSE XSD DOCUMENT **************************************/ - - xsd_doc = xmlParseDoc(xsdXmlChar); - - if (xsd_doc == NULL) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: XML Schema cannot be loaded or is not well-formed."); - free(errBuf); - xmlFreeDoc(doc); - /* Don't call xmlCleanupParser when libxml2 will be used in other microservice calls - xmlCleanupParser(); - */ - return (USER_INPUT_FORMAT_ERR); - } - - - - /**************************************** VALIDATE DOCUMENT **************************************/ - - /* Create a parser context */ - parser_ctxt = xmlSchemaNewDocParserCtxt(xsd_doc); - if (parser_ctxt == NULL) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Unable to create a parser context for the schema."); - free(errBuf); - xmlFreeDoc(xsd_doc); - xmlFreeDoc(doc); - /* Don't call xmlCleanupParser when libxml2 will be used in other microservice calls - xmlCleanupParser(); - */ - return (USER_INPUT_FORMAT_ERR); - } - - - /* Parse the XML schema */ - schema = xmlSchemaParse(parser_ctxt); - if (schema == NULL) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Invalid schema."); - free(errBuf); - xmlSchemaFreeParserCtxt(parser_ctxt); - xmlFreeDoc(doc); - xmlFreeDoc(xsd_doc); - - /* Don't call xmlCleanupParser when libxml2 will be used in other microservice calls - xmlCleanupParser(); - */ - - return (USER_INPUT_FORMAT_ERR); - } - - - /* Create a validation context */ - valid_ctxt = xmlSchemaNewValidCtxt(schema); - if (valid_ctxt == NULL) - { - rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Unable to create a validation context for the schema."); - free(errBuf); - xmlSchemaFree(schema); - xmlSchemaFreeParserCtxt(parser_ctxt); - xmlFreeDoc(xsd_doc); - xmlFreeDoc(doc); - /* Don't call when libxml2 is used by other microservice calls - xmlCleanupParser(); - */ - return (USER_INPUT_FORMAT_ERR); - } - - - /* Set myErrorCallback() as the default handler for error messages and warnings */ - xmlSchemaSetValidErrors(valid_ctxt, (xmlSchemaValidityErrorFunc)myErrorCallback, (xmlSchemaValidityWarningFunc)myErrorCallback, errBuf); - - - /* Validate XML doc */ - rei->status = xmlSchemaValidateDoc(valid_ctxt, doc); - - - - /******************************************* WE'RE DONE ******************************************/ - - /* return both error code and messages through status */ - resetMsParam (status); - fillBufLenInMsParam (status, rei->status, errBuf); - - - /* cleanup of all xml parsing stuff */ - xmlSchemaFreeValidCtxt(valid_ctxt); - xmlSchemaFree(schema); - xmlSchemaFreeParserCtxt(parser_ctxt); - xmlFreeDoc(doc); - xmlFreeDoc(xsd_doc); - - /* Don't call when libxml2 is used by other microservice calls - xmlCleanupParser(); - */ - - return (rei->status); -} - - - irods::ms_table_entry * plugin_factory() { - irods::ms_table_entry* msvc = new irods::ms_table_entry(3); - msvc->add_operation< - msParam_t*, - msParam_t*, - msParam_t*, - ruleExecInfo_t*>("msiXmlDocSchemaValidate", - std::function<int( - msParam_t*, - msParam_t*, - msParam_t*, - ruleExecInfo_t*)>(msiXmlDocSchemaValidate)); - return msvc; - } - -} // extern "C" - diff --git a/src/msiXsltApply.cc b/src/msiXsltApply.cc deleted file mode 100644 index 2d9d6eb407a92d94348dfb87e48fb8232e21db17..0000000000000000000000000000000000000000 --- a/src/msiXsltApply.cc +++ /dev/null @@ -1,278 +0,0 @@ -/** - * @file xsltMS.c - * - */ - -/*** Copyright (c), The Regents of the University of California *** - *** For more information please refer to files in the COPYRIGHT directory ***/ -#include <libxslt/transform.h> -#include <libxslt/xsltutils.h> -#include <libxslt/xsltInternals.h> -#include <libexslt/exslt.h> -#include <libexslt/exsltconfig.h> -#include <iostream> - -#include "rcMisc.h" -#include "rsObjStat.hpp" -#include "rsDataObjOpen.hpp" -#include "rsDataObjRead.hpp" -#include "rsDataObjClose.hpp" -#include "irods_error.hpp" -#include "irods_ms_plugin.hpp" - -extern int xmlLoadExtDtdDefaultValue; - -extern "C" { - - /** - * \fn msiXsltApply (msParam_t *xsltObj, msParam_t *xmlObj, msParam_t *msParamOut, ruleExecInfo_t *rei) - * - * \brief This function applies an XSL stylesheet to an XML file, both existing iRODS objects. - * - * \module XML - * - * \since pre-2.1 - * - * \author Antoine de Torcy - * \date 2008/05/29 - * - * \usage See clients/icommands/test/rules3.0/ - * - * \param[in] xsltObj - a msParam of type DataObjInp_MS_T or STR_MS_T - * \param[in] xmlObj - a msParam of type DataObjInp_MS_T or STR_MS_T - * \param[out] msParamOut - a msParam of operation status BUF_LEN_MS_T - * \param[in,out] rei - The RuleExecInfo structure that is automatically - * handled by the rule engine. The user does not include rei as a - * parameter in the rule invocation. - * - * \DolVarDependence None - * \DolVarModified None - * \iCatAttrDependence None - * \iCatAttrModified None - * \sideeffect None - * - * \return integer - * \retval 0 on success - * \pre None - * \post None - * \sa None - **/ - int - msiXsltApply(msParam_t *xsltObj, msParam_t *xmlObj, msParam_t *msParamOut, ruleExecInfo_t *rei) - { - /* for parsing msParams and to open iRODS objects */ - dataObjInp_t xmlDataObjInp, *myXmlDataObjInp; - dataObjInp_t xsltDataObjInp, *myXsltDataObjInp; - int xmlObjID, xsltObjID; - - /* for getting size of objects to read from */ - rodsObjStat_t *rodsObjStatOut = NULL; - - /* for reading from iRODS objects */ - openedDataObjInp_t openedDataObjInp; - bytesBuf_t *xmlBuf = NULL, *xsltBuf = NULL; - - /* misc. to avoid repeating rei->rsComm */ - rsComm_t *rsComm; - - /* for xml parsing */ - char *outStr; - int outLen; - xsltStylesheetPtr style = NULL; - xmlDocPtr xslSheet, doc, res; - - /* for output buffer */ - bytesBuf_t *mybuf; - - - /********************************* USUAL INIT PROCEDURE **********************************/ - - /* For testing mode when used with irule --test */ - RE_TEST_MACRO (" Calling msiXsltApply") - - - /* Sanity checks */ - if (rei == NULL || rei->rsComm == NULL) - { - rodsLog (LOG_ERROR, "msiXsltApply: input rei or rsComm is NULL."); - return (SYS_INTERNAL_NULL_INPUT_ERR); - } - - rsComm = rei->rsComm; - - - - /********************************** RETRIEVE INPUT PARAMS **********************************/ - - /* Get xsltObj: the XSLT stylesheet */ - rei->status = parseMspForDataObjInp (xsltObj, &xsltDataObjInp, &myXsltDataObjInp, 0); - if (rei->status < 0) - { - rodsLog (LOG_ERROR, "msiXsltApply: input xsltObj error. status = %d", rei->status); - return (rei->status); - } - - - /* Get xmlObj: the XML document */ - rei->status = parseMspForDataObjInp (xmlObj, &xmlDataObjInp, &myXmlDataObjInp, 0); - if (rei->status < 0) - { - rodsLog (LOG_ERROR, "msiXsltApply: input xmlObj error. status = %d", rei->status); - return (rei->status); - } - - - - /******************************** GET CONTENTS OF IRODS OBJS ********************************/ - - /* Open XSLT file */ - if ((xsltObjID = rsDataObjOpen(rsComm, &xsltDataObjInp)) < 0) - { - rodsLog (LOG_ERROR, "msiXsltApply: Cannot open XSLT data object. status = %d", xsltObjID); - return (xsltObjID); - } - - - /* Get size of XSLT file */ - rei->status = rsObjStat (rsComm, &xsltDataObjInp, &rodsObjStatOut); - if( NULL == rodsObjStatOut ) { // JMC cppcheck nullptr ref - rodsLog( LOG_ERROR, "msiXsltApply:: null &rodsObjStatOut" ); - return ( rei->status ); - } - - /* xsltBuf init */ - /* memory for xsltBuf->buf is allocated in rsFileRead() */ - xsltBuf = (bytesBuf_t *) malloc (sizeof (bytesBuf_t)); - memset (xsltBuf, 0, sizeof (bytesBuf_t)); - - - /* Read XSLT file */ - memset (&openedDataObjInp, 0, sizeof (openedDataObjInp_t)); - openedDataObjInp.l1descInx = xsltObjID; - openedDataObjInp.len = (int)rodsObjStatOut->objSize; - - rei->status = rsDataObjRead (rsComm, &openedDataObjInp, xsltBuf); - - /* Convert buffer to xmlChar (null-terminated) */ - - xmlChar* xsltXmlChar = xmlCharStrndup((char*)xsltBuf->buf, openedDataObjInp.len); - - /* Close XSLT file */ - rei->status = rsDataObjClose (rsComm, &openedDataObjInp); - - - /* Cleanup. Needed before using rodsObjStatOut for a new rsObjStat() call */ - freeRodsObjStat (rodsObjStatOut); - - /* xsltBuf is no longer needed */ - freeBBuf(xsltBuf); - - - /* Open XML file */ - if ((xmlObjID = rsDataObjOpen(rsComm, &xmlDataObjInp)) < 0) - { - rodsLog (LOG_ERROR, "msiXsltApply: Cannot open XML data object. status = %d", xmlObjID); - return (xmlObjID); - } - - - /* Get size of XML file */ - rei->status = rsObjStat (rsComm, &xmlDataObjInp, &rodsObjStatOut); - - - /* xmlBuf init */ - /* memory for xmlBuf->buf is allocated in rsFileRead() */ - xmlBuf = (bytesBuf_t *) malloc (sizeof (bytesBuf_t)); - memset (xmlBuf, 0, sizeof (bytesBuf_t)); - - - /* Read XML file */ - memset (&openedDataObjInp, 0, sizeof (openedDataObjInp_t)); - openedDataObjInp.l1descInx = xmlObjID; - openedDataObjInp.len = (int)rodsObjStatOut->objSize; - - rei->status = rsDataObjRead (rsComm, &openedDataObjInp, xmlBuf); - - /* copy buffer into null terminated xmlChar */ - xmlChar* xmlXmlChar = xmlCharStrndup((char*)xmlBuf->buf, openedDataObjInp.len); - - /* Close XML file */ - rei->status = rsDataObjClose (rsComm, &openedDataObjInp); - - /* cleanup */ - freeRodsObjStat (rodsObjStatOut); - /* xmlBuf is no longer needed */ - freeBBuf(xmlBuf); - - - /******************************** PARSE XML DOCS AND APPLY XSL ********************************/ - - xmlSubstituteEntitiesDefault(1); - xmlLoadExtDtdDefaultValue = 1; - - /* register all available exslt extensions. This includes str:encode-uri */ - exsltRegisterAll(); - - /* Parse xsltXmlChar into an xmlDocPtr, and the xmlDocPtr into an xsltStylesheetPtr */ - xslSheet = xmlParseDoc(xsltXmlChar); - style = xsltParseStylesheetDoc(xslSheet); - - doc = xmlParseDoc(xmlXmlChar); - - /* And the magic happens */ - res = xsltApplyStylesheet(style, doc, NULL); - - if (res == NULL) { - rei->status = XML_PARSING_ERR; - } else { - /* Save result XML document to a string */ - rei->status = xsltSaveResultToString((xmlChar**)&outStr, &outLen, res, style); - } - - - /* cleanup of all xml parsing stuff */ - xsltFreeStylesheet(style); - xmlFreeDoc(res); - xmlFreeDoc(doc); - - /* don't call if libxslt or libxml2 are called in other microservices - xsltCleanupGlobals(); - xmlCleanupParser(); - */ - - /************************************** WE'RE DONE **************************************/ - - if (rei->status != XML_PARSING_ERR) { - /* copy the result string into an output buffer */ - mybuf = (bytesBuf_t *)malloc(sizeof(bytesBuf_t)); - mybuf->buf = (void *)outStr; - mybuf->len = (int) strlen(outStr); - - - /* send results out to msParamOut */ - fillBufLenInMsParam (msParamOut, mybuf->len, mybuf); - } - - return (rei->status); - } - - - irods::ms_table_entry* plugin_factory() { - irods::ms_table_entry* msvc = new irods::ms_table_entry(3); - - msvc->add_operation< - msParam_t*, - msParam_t*, - msParam_t*, - ruleExecInfo_t*>("msiXsltApply", - std::function<int( - msParam_t*, - msParam_t*, - msParam_t*, - ruleExecInfo_t*)>(msiXsltApply)); - - return msvc; - } - -} // extern "C" -