18#include <libxml/parser.h>
19#include <libxml/xmlIO.h>
20#include <libxml/xpath.h>
21#include <libxml/xpathInternals.h>
22#include <libxml/xmlstring.h>
23#include <libxslt/transform.h>
24#include <libxslt/xsltutils.h>
25#include <libxslt/variables.h>
26#include <libxslt/extensions.h>
27#include <libexslt/exslt.h>
32#include <osl/file.hxx>
33#include <com/sun/star/uno/Any.hxx>
34#include <com/sun/star/beans/NamedValue.hpp>
35#include <com/sun/star/io/XInputStream.hpp>
36#include <com/sun/star/io/XOutputStream.hpp>
37#include <com/sun/star/io/XStreamListener.hpp>
42using namespace ::
cppu;
70 struct ParserInputBufferCallback
73 on_read(
void * context,
char * buffer,
int len)
76 return tmp->
read(buffer, len);
87 struct ParserOutputBufferCallback
90 on_write(
void * context,
const char * buffer,
int len)
93 return tmp->
write(buffer, len);
96 on_close(
void * context)
114 init(xsltTransformContextPtr,
const xmlChar*)
119 insertByName(xmlXPathParserContextPtr ctxt,
int nargs)
121 xsltTransformContextPtr tctxt;
124 xsltGenericError(xsltGenericErrorContext,
125 "insertByName: requires exactly 2 arguments\n");
128 tctxt = xsltXPathGetTransformContext(ctxt);
129 if (tctxt ==
nullptr) {
130 xsltGenericError(xsltGenericErrorContext,
131 "xsltExtFunctionTest: failed to get the transformation context\n");
137 data = tctxt->_private;
138 if (data ==
nullptr) {
139 xsltGenericError(xsltGenericErrorContext,
140 "xsltExtFunctionTest: failed to get module data\n");
145 xmlXPathObjectPtr
value = valuePop(ctxt);
147 xmlXPathObjectPtr streamName = valuePop(ctxt);
148 streamName = ensureStringValue(streamName, ctxt);
150 oh->
insertByName(OStringToOUString(
reinterpret_cast<char*
>(streamName->stringval), RTL_TEXTENCODING_UTF8),
151 std::string_view(
reinterpret_cast<char*
>(
value->stringval)));
152 valuePush(ctxt, xmlXPathNewCString(
""));
155 static xmlXPathObjectPtr ensureStringValue(xmlXPathObjectPtr obj,
const xmlXPathParserContextPtr ctxt)
157 if (obj->type != XPATH_STRING) {
158 valuePush(ctxt, obj);
159 xmlXPathStringFunction(ctxt, 1);
160 obj = valuePop(ctxt);
165 static void getByName(xmlXPathParserContextPtr ctxt,
int nargs)
167 xsltTransformContextPtr tctxt;
170 xsltGenericError(xsltGenericErrorContext,
171 "getByName: requires exactly 1 argument\n");
175 tctxt = xsltXPathGetTransformContext(ctxt);
176 if (tctxt ==
nullptr) {
177 xsltGenericError(xsltGenericErrorContext,
178 "xsltExtFunctionTest: failed to get the transformation context\n");
183 data = tctxt->_private;
184 if (data ==
nullptr) {
185 xsltGenericError(xsltGenericErrorContext,
186 "xsltExtFunctionTest: failed to get module data\n");
190 xmlXPathObjectPtr streamName = valuePop(ctxt);
191 streamName = ensureStringValue(streamName, ctxt);
192 const OString content = oh->
getByName(OStringToOUString(
reinterpret_cast<char*
>(streamName->stringval), RTL_TEXTENCODING_UTF8));
193 valuePush(ctxt, xmlXPathNewCString(content.getStr()));
194 xmlXPathFreeObject(streamName);
201 Thread(
"LibXSLTTransformer"), m_transformer(transformer),
213 if (buffer ==
nullptr || len < 0)
216 css::uno::Reference<XInputStream> xis =
m_transformer->getInputStream();
228 if (buffer ==
nullptr || len < 0)
232 css::uno::Reference<XOutputStream> xos =
m_transformer->getOutputStream();
233 sal_Int32 writeLen = len;
236 reinterpret_cast<const sal_uInt8*
> (buffer);
239 sal_Int32
n = ::std::min(writeLen, bufLen);
242 static_cast<size_t> (
n));
254 css::uno::Reference<XOutputStream> xos =
m_transformer->getOutputStream();
270 ::std::map<const char*, OString> pmap =
m_transformer->getParameters();
271 ::std::vector< const char* > params( pmap.size() * 2 + 1 );
273 for (
auto const& elem : pmap)
275 params[paramIndex++] = elem.first;
276 params[paramIndex++] = elem.second.getStr();
278 params[paramIndex] =
nullptr;
279 xmlDocPtr doc = xmlReadIO(&ParserInputBufferCallback::on_read,
280 &ParserInputBufferCallback::on_close,
281 static_cast<void*
> (
this),
nullptr,
nullptr, 0);
282 xsltStylesheetPtr styleSheet =
nullptr;
284 styleSheet = xsltParseStylesheetFile(
285 reinterpret_cast<const xmlChar *
>(
m_transformer->getStyleSheetURL().getStr()));
288 xmlDocPtr styleSheetDoc = xmlReadMemory(
291 "noname.xml",
nullptr, 0);
293 styleSheet = xsltParseStylesheetDoc(styleSheetDoc);
301 xmlDocPtr
result =
nullptr;
304#ifdef DEBUG_FILTER_LIBXSLTTRANSFORMER
305 xsltSetGenericDebugFunc(stderr,
NULL);
306 xsltDebugDumpExtensions(
NULL);
308 std::optional<OleHandler> oh(std::in_place,
m_transformer->getComponentContext());
311 xsltTransformContextPtr tcontext = xsltNewTransformContext(
314 std::scoped_lock<std::mutex> g(
m_mutex);
318 xsltQuoteUserParams(
m_tcontext, params.data());
319 result = xsltApplyStylesheetUser(styleSheet, doc,
nullptr,
nullptr,
nullptr,
325 xmlCharEncodingHandlerPtr encoder = xmlGetCharEncodingHandler(
326 XML_CHAR_ENCODING_UTF8);
327 xmlOutputBufferPtr outBuf = xmlAllocOutputBuffer(encoder);
328 outBuf->context =
static_cast<void *
> (
this);
329 outBuf->writecallback = &ParserOutputBufferCallback::on_write;
330 outBuf->closecallback = &ParserOutputBufferCallback::on_close;
331 xsltSaveResultTo(outBuf,
result, styleSheet);
332 (void)xmlOutputBufferClose(outBuf);
336 xmlErrorPtr lastErr = xmlGetLastError();
339 msg = OStringToOUString(lastErr->message, RTL_TEXTENCODING_UTF8);
341 msg =
"Unknown XSLT transformation error";
346 xsltFreeStylesheet(styleSheet);
347 xsltTransformContextPtr tcontext =
nullptr;
349 std::scoped_lock<std::mutex> g(
m_mutex);
352 xsltFreeTransformContext(tcontext);
361 xsltRegisterExtModule(oleModuleURI, &ExtFuncOleCB::init,
nullptr);
362 xsltRegisterExtModuleFunction(
363 reinterpret_cast<const xmlChar*
>(
"insertByName"),
365 &ExtFuncOleCB::insertByName);
366 xsltRegisterExtModuleFunction(
367 reinterpret_cast<const xmlChar*
>(
"getByName"),
369 &ExtFuncOleCB::getByName);
375 std::scoped_lock<std::mutex> g(
m_mutex);
389 css::uno::Reference<XComponentContext> xContext) :
401 return "com.sun.star.comp.documentconversion.XSLTFilter";
405 return {
"com.sun.star.documentconversion.XSLTFilter" };
410 const css::uno::Reference<XInputStream>& inputStream)
415 css::uno::Reference<XInputStream>
423 const css::uno::Reference<XOutputStream>& outputStream)
428 css::uno::Reference<XOutputStream>
442 const css::uno::Reference<XStreamListener>& listener)
450 for (
const css::uno::Reference<XStreamListener>& xl :
m_listeners)
454 OSL_ENSURE(!
m_Reader.is(),
"Somebody forgot to call terminate *and* holds a reference to this LibXSLTTransformer instance");
464 for (
const css::uno::Reference<XStreamListener>& xl :
m_listeners)
476 for (
const css::uno::Reference<XStreamListener>& xl :
m_listeners)
501 Sequence<Any> params;
502 if (!(
args[0] >>= params))
506 xmlSubstituteEntitiesDefault(0);
508 for (
const Any&
p : std::as_const(params))
513 RTL_TEXTENCODING_UTF8);
516 if (nv.Value >>=
value)
519 RTL_TEXTENCODING_UTF8);
526 if (nameUTF8 ==
"StylesheetURL")
530 if (nameUTF8 ==
"StylesheetText")
534 else if (nameUTF8 ==
"SourceURL")
539 else if (nameUTF8 ==
"SourceBaseURL")
544 else if (nameUTF8 ==
"TargetURL")
549 else if (nameUTF8 ==
"TargetBaseURL")
554 else if (nameUTF8 ==
"DoctypePublic")
563extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
565 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any>
const&)
Reference< XComponentContext > m_xContext
#define OUTPUT_BUFFER_SIZE
#define INPUT_BUFFER_SIZE
constexpr OUStringLiteral sServiceName
FILE * init(int, char **)
OString getByName(const OUString &streamName)
void insertByName(const OUString &streamName, std::string_view content)
int read(char *buffer, int len)
static void registerExtensionModule()
virtual void execute() override
virtual ~Reader() override
xsltTransformContextPtr m_tcontext
Sequence< sal_Int8 > m_readBuf
int write(const char *buffer, int len)
Sequence< sal_Int8 > m_writeBuf
Reader(LibXSLTTransformer *transformer)
rtl::Reference< LibXSLTTransformer > m_transformer
static const sal_Int32 OUTPUT_BUFFER_SIZE
static const sal_Int32 INPUT_BUFFER_SIZE
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)