summaryrefslogtreecommitdiff
path: root/gentoobrowse-api/service/xsltStreamSerializer.cpp
blob: abe652d4cd1a6561f3f17cf119aa549a84f458c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "xsltStreamSerializer.h"
#include <libxslt/xsltInternals.h>
#include <libxml/HTMLtree.h>
#include <factory.impl.h>
#include <processPipes.h>
#include <sys/wait.h>

namespace Gentoo {
	static int xmlstrmclosecallback(void * context)
	{
		((std::ostream*)context)->flush();
		return 0;
	}

	static int xmlstrmwritecallback(void * context, const char * buffer, int len)
	{
		((std::ostream*)context)->write(buffer, len);
		return len;
	}

	XsltStreamSerializer::XsltStreamSerializer(Gentoo::EmailPtr e, xsltStylesheet * ss) :
		Slicer::XmlDocumentSerializer(doc),
		mail(e),
		doc(nullptr),
		stylesheet(ss)
	{
	}

	XsltStreamSerializer::~XsltStreamSerializer()
	{
		delete doc;
	}

	void
	XsltStreamSerializer::Serialize(Slicer::ModelPartForRootPtr mp)
	{
		Slicer::XmlDocumentSerializer::Serialize(mp);
		auto result = std::shared_ptr<xmlDoc>(xsltApplyStylesheet(stylesheet, doc->cobj(), nullptr), xmlFreeDoc);
		if (!result) {
			throw xmlpp::exception("Failed to apply XSL transform");
		}
		appendText(result.get());
		appendHtml(result.get());
	}

	void XsltStreamSerializer::appendHtml(xmlDoc * result) const
	{
		std::stringstream strm;
		xmlOutputBufferPtr buf = xmlOutputBufferCreateIO(xmlstrmwritecallback, xmlstrmclosecallback, &strm, NULL);
		htmlDocContentDumpFormatOutput(buf, result, "utf-8", 0);
		xmlOutputBufferClose(buf);
		mail->body.push_back(std::make_shared<Gentoo::MimePart>("text/html", strm.str()));
	}

	void XsltStreamSerializer::appendText(xmlDoc * result) const
	{
		std::stringstream strm;
		std::vector<std::string> callLynx;
		callLynx.push_back("/usr/bin/lynx");
		callLynx.push_back("-dump");
		callLynx.push_back("-stdin");
		std::string widthArg = "-width=78";
		callLynx.push_back(widthArg);
		AdHoc::System::ProcessPipes fds(callLynx, true, true, false);
		FILE * lynxIn = fdopen(fds.fdIn(), "w");
		// Fixed encoding as we want the result to go back into a ustring
		htmlNodeDumpFileFormat(lynxIn, result, xmlDocGetRootElement(result), "utf-8", 0);
		fclose(lynxIn);
		char buf[1024];
		int r;
		while ((r = read(fds.fdOut(), buf, sizeof(buf))) > 0) {
			strm.write(buf, r);
		}
		int status;
		waitpid(fds.pid(), &status, 0);
		if (status != 0) {
			throw std::runtime_error("Lynx failed");
		}
		mail->body.push_back(std::make_shared<Gentoo::MimePart>("text/plain", strm.str()));
	}
}