From 728c8746b9211a786cb7164f4927fd3321f7dd71 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 18 Feb 2018 18:41:51 +0000 Subject: Remove the irksome notifications library, build everything into the service itself --- gentoobrowse-api/service/Jamfile.jam | 32 +++++++-- gentoobrowse-api/service/mailserverimpl.cpp | 64 +++++++++++++++++ gentoobrowse-api/service/mailserverimpl.h | 20 ++++++ gentoobrowse-api/service/notifications.ice | 43 ++++++++++++ gentoobrowse-api/service/notifications/Jamfile.jam | 44 ------------ .../service/notifications/mailserverimpl.cpp | 64 ----------------- .../service/notifications/mailserverimpl.h | 20 ------ .../service/notifications/notifications.ice | 43 ------------ .../service/notifications/notificationsimpl.cpp | 59 ---------------- .../service/notifications/notificationsimpl.h | 29 -------- .../service/notifications/xsltStreamSerializer.cpp | 82 ---------------------- .../service/notifications/xsltStreamSerializer.h | 28 -------- gentoobrowse-api/service/notificationsimpl.cpp | 59 ++++++++++++++++ gentoobrowse-api/service/notificationsimpl.h | 29 ++++++++ gentoobrowse-api/service/xsltStreamSerializer.cpp | 82 ++++++++++++++++++++++ gentoobrowse-api/service/xsltStreamSerializer.h | 28 ++++++++ gentoobrowse-api/unittests/Jamfile.jam | 2 + 17 files changed, 353 insertions(+), 375 deletions(-) create mode 100644 gentoobrowse-api/service/mailserverimpl.cpp create mode 100644 gentoobrowse-api/service/mailserverimpl.h create mode 100644 gentoobrowse-api/service/notifications.ice delete mode 100644 gentoobrowse-api/service/notifications/Jamfile.jam delete mode 100644 gentoobrowse-api/service/notifications/mailserverimpl.cpp delete mode 100644 gentoobrowse-api/service/notifications/mailserverimpl.h delete mode 100644 gentoobrowse-api/service/notifications/notifications.ice delete mode 100644 gentoobrowse-api/service/notifications/notificationsimpl.cpp delete mode 100644 gentoobrowse-api/service/notifications/notificationsimpl.h delete mode 100644 gentoobrowse-api/service/notifications/xsltStreamSerializer.cpp delete mode 100644 gentoobrowse-api/service/notifications/xsltStreamSerializer.h create mode 100644 gentoobrowse-api/service/notificationsimpl.cpp create mode 100644 gentoobrowse-api/service/notificationsimpl.h create mode 100644 gentoobrowse-api/service/xsltStreamSerializer.cpp create mode 100644 gentoobrowse-api/service/xsltStreamSerializer.h diff --git a/gentoobrowse-api/service/Jamfile.jam b/gentoobrowse-api/service/Jamfile.jam index d1b4833..89b28ab 100644 --- a/gentoobrowse-api/service/Jamfile.jam +++ b/gentoobrowse-api/service/Jamfile.jam @@ -1,23 +1,45 @@ import icetray ; +import type : register ; +import generators : register-standard ; + +type.register XSLT : xslt ; + +generators.register-standard xslt.c : XSLT : C H ; + +actions xslt.c +{ + echo "extern unsigned char $(2:B)_xslt[];" > $(1[2]) + echo "extern unsigned int $(2:B)_xslt_len;" >> $(1[2]) + ( cd $(2:D) ; xxd -i $(2:B)$(2:S) ) > $(1[1]) +} + +IMPORT $(__name__) : xslt.c : : xslt.c ; lib icetray : : : : /usr/include/icetray ; lib git2 ; +lib exslt ; +lib xslt : : : : /usr/include/libxslt ; +lib slicer-xml ; +lib esmtp ; lib gentoobrowse-service : - [ glob-tree *.cpp : bin notifications ] + [ glob-tree *.cpp : bin ] + [ glob-tree *.xslt ] [ glob-tree *.sql ] + [ glob-tree *.ice ] : ..//adhocutil - notifications icetray git2 + xslt + exslt + esmtp ..//dbppcore ..//IceBox ..//slicer ..//slicer-db + slicer-xml ../api//gentoobrowse-api - notifications//gentoobrowse-service-notifications - notifications//gentoobrowse-service-notifications ../api//gentoobrowse-api ..//boost_system ..//boost_thread @@ -32,8 +54,6 @@ lib gentoobrowse-service : : : . ../api//gentoobrowse-api - notifications//gentoobrowse-service-notifications - notifications//gentoobrowse-service-notifications ../api//gentoobrowse-api ; diff --git a/gentoobrowse-api/service/mailserverimpl.cpp b/gentoobrowse-api/service/mailserverimpl.cpp new file mode 100644 index 0000000..ccc7180 --- /dev/null +++ b/gentoobrowse-api/service/mailserverimpl.cpp @@ -0,0 +1,64 @@ +#include "mailserverimpl.h" +#include +#include +#include + +namespace Gentoo { + namespace Service { + typedef std::vector Parts; + typedef std::pair PartsProgress; + + void + MailServer::sendEmail(const Gentoo::EmailPtr & msg, const Ice::Current & c) + { + auto props = c.adapter->getCommunicator()->getProperties(); + smtp_session_t session = smtp_create_session(); + smtp_message_t message = smtp_add_message(session); + auto server = props->getPropertyWithDefault("GentooBrowseAPI.MailServer", "localhost:25"); + smtp_set_server(session, server.c_str()); + smtp_set_header(message, "To", msg->to.name.c_str(), msg->to.address.c_str()); + smtp_set_header(message, "From", msg->from.name.c_str(), msg->from.address.c_str()); + smtp_set_header(message, "Subject", msg->subject.c_str()); + Parts parts; + parts.emplace_back("Content-Type: multipart/alternative; boundary=\"<>\"\r\n"); + parts.emplace_back("MIME-Version: 1.0\r\n"); + parts.emplace_back("Content-Transfer-Encoding: binary\r\n"); + smtp_add_recipient(message, msg->to.address.c_str()); + for (const auto & p : msg->body) { + parts.emplace_back("\r\n--<>\r\nContent-Type: " + p->mimetype + "; charset=\"utf-8\"\r\n\r\n"); + parts.emplace_back(p->payload); + } + parts.emplace_back("\r\n--<>--\r\n"); + PartsProgress pp { parts.begin(), parts.end() }; + smtp_set_messagecb(message, writeBody, &pp); + if (!smtp_start_session(session)) { + char buf[BUFSIZ]; + auto b = smtp_strerror(smtp_errno(), buf, sizeof(buf)); + assert(b); + SendEmailFailed e(b); + smtp_destroy_session(session); + throw e; + } + smtp_destroy_session(session); + } + + const char * + MailServer::writeBody(void **, int * len, void * arg) + { + auto parts = static_cast(arg); + if (len == NULL || parts->first == parts->second) { + return NULL; + } + const auto & p = *parts->first++; + *len = p.length(); + return p.data(); + } + } + + void + SendEmailFailed::ice_print(std::ostream & buf) const + { + buf << "Failed to send email: " << message; + } +} + diff --git a/gentoobrowse-api/service/mailserverimpl.h b/gentoobrowse-api/service/mailserverimpl.h new file mode 100644 index 0000000..23b17c2 --- /dev/null +++ b/gentoobrowse-api/service/mailserverimpl.h @@ -0,0 +1,20 @@ +#ifndef MAILSERVERIMPL_H +#define MAILSERVERIMPL_H + +#include +#include + +namespace Gentoo { + namespace Service { + class DLL_PUBLIC MailServer : public Gentoo::MailServer { + public: + void sendEmail(const Gentoo::EmailPtr & msg, const Ice::Current &) override; + + private: + static const char * writeBody(void ** buf, int * len, void * arg); + }; + } +} + +#endif + diff --git a/gentoobrowse-api/service/notifications.ice b/gentoobrowse-api/service/notifications.ice new file mode 100644 index 0000000..4a2673f --- /dev/null +++ b/gentoobrowse-api/service/notifications.ice @@ -0,0 +1,43 @@ +#ifndef GENTOO_NOTIFICATIONS +#define GENTOO_NOTIFICATIONS + +#include +#include + +module Gentoo { + class MimePart { + string mimetype; + string payload; + }; + + sequence MimeParts; + + struct Address { + string name; + string address; + }; + + class Email { + Address to; + Address from; + string subject; + MimeParts body; + }; + + ["cpp:ice_print"] + exception SendEmailFailed { + string message; + }; + + interface Notifications { + Email getSignup(NewUser user); + Email getNews(User user, NewsContent nc); + }; + + interface MailServer { + idempotent void sendEmail(Email msg) throws SendEmailFailed; + }; +}; + +#endif + diff --git a/gentoobrowse-api/service/notifications/Jamfile.jam b/gentoobrowse-api/service/notifications/Jamfile.jam deleted file mode 100644 index a168649..0000000 --- a/gentoobrowse-api/service/notifications/Jamfile.jam +++ /dev/null @@ -1,44 +0,0 @@ -import type : register ; -import generators : register-standard ; - -type.register XSLT : xslt ; - -generators.register-standard xslt.h : XSLT : H ; - -h base-xslt : xslt/base.xslt : yes ; -h signup-xslt : xslt/signup.xslt : yes ; -h news-xslt : xslt/news.xslt : yes ; - -lib exslt ; -lib xslt : : : : /usr/include/libxslt ; -lib xml2 : : : : /usr/include/libxml2 ; -lib esmtp ; -lib slicer-xml ; -lib boost_system ; - -lib gentoobrowse-service-notifications : - [ glob *.ice *.cpp ] - : - yes - xslt - xml2 - esmtp - ../../..//libxmlpp - boost_system - slicer-xml - ../../domain//gentoobrowse-domain - ../../domain//gentoobrowse-domain - base-xslt - signup-xslt - news-xslt - : : - . - ; - -actions xslt.h -{ - ( cd $(2:D) ; xxd -i $(2:B)$(2:S) ) > $(1) -} - -IMPORT $(__name__) : xslt.h : : xslt.h ; - diff --git a/gentoobrowse-api/service/notifications/mailserverimpl.cpp b/gentoobrowse-api/service/notifications/mailserverimpl.cpp deleted file mode 100644 index ccc7180..0000000 --- a/gentoobrowse-api/service/notifications/mailserverimpl.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "mailserverimpl.h" -#include -#include -#include - -namespace Gentoo { - namespace Service { - typedef std::vector Parts; - typedef std::pair PartsProgress; - - void - MailServer::sendEmail(const Gentoo::EmailPtr & msg, const Ice::Current & c) - { - auto props = c.adapter->getCommunicator()->getProperties(); - smtp_session_t session = smtp_create_session(); - smtp_message_t message = smtp_add_message(session); - auto server = props->getPropertyWithDefault("GentooBrowseAPI.MailServer", "localhost:25"); - smtp_set_server(session, server.c_str()); - smtp_set_header(message, "To", msg->to.name.c_str(), msg->to.address.c_str()); - smtp_set_header(message, "From", msg->from.name.c_str(), msg->from.address.c_str()); - smtp_set_header(message, "Subject", msg->subject.c_str()); - Parts parts; - parts.emplace_back("Content-Type: multipart/alternative; boundary=\"<>\"\r\n"); - parts.emplace_back("MIME-Version: 1.0\r\n"); - parts.emplace_back("Content-Transfer-Encoding: binary\r\n"); - smtp_add_recipient(message, msg->to.address.c_str()); - for (const auto & p : msg->body) { - parts.emplace_back("\r\n--<>\r\nContent-Type: " + p->mimetype + "; charset=\"utf-8\"\r\n\r\n"); - parts.emplace_back(p->payload); - } - parts.emplace_back("\r\n--<>--\r\n"); - PartsProgress pp { parts.begin(), parts.end() }; - smtp_set_messagecb(message, writeBody, &pp); - if (!smtp_start_session(session)) { - char buf[BUFSIZ]; - auto b = smtp_strerror(smtp_errno(), buf, sizeof(buf)); - assert(b); - SendEmailFailed e(b); - smtp_destroy_session(session); - throw e; - } - smtp_destroy_session(session); - } - - const char * - MailServer::writeBody(void **, int * len, void * arg) - { - auto parts = static_cast(arg); - if (len == NULL || parts->first == parts->second) { - return NULL; - } - const auto & p = *parts->first++; - *len = p.length(); - return p.data(); - } - } - - void - SendEmailFailed::ice_print(std::ostream & buf) const - { - buf << "Failed to send email: " << message; - } -} - diff --git a/gentoobrowse-api/service/notifications/mailserverimpl.h b/gentoobrowse-api/service/notifications/mailserverimpl.h deleted file mode 100644 index 23b17c2..0000000 --- a/gentoobrowse-api/service/notifications/mailserverimpl.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef MAILSERVERIMPL_H -#define MAILSERVERIMPL_H - -#include -#include - -namespace Gentoo { - namespace Service { - class DLL_PUBLIC MailServer : public Gentoo::MailServer { - public: - void sendEmail(const Gentoo::EmailPtr & msg, const Ice::Current &) override; - - private: - static const char * writeBody(void ** buf, int * len, void * arg); - }; - } -} - -#endif - diff --git a/gentoobrowse-api/service/notifications/notifications.ice b/gentoobrowse-api/service/notifications/notifications.ice deleted file mode 100644 index 4a2673f..0000000 --- a/gentoobrowse-api/service/notifications/notifications.ice +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef GENTOO_NOTIFICATIONS -#define GENTOO_NOTIFICATIONS - -#include -#include - -module Gentoo { - class MimePart { - string mimetype; - string payload; - }; - - sequence MimeParts; - - struct Address { - string name; - string address; - }; - - class Email { - Address to; - Address from; - string subject; - MimeParts body; - }; - - ["cpp:ice_print"] - exception SendEmailFailed { - string message; - }; - - interface Notifications { - Email getSignup(NewUser user); - Email getNews(User user, NewsContent nc); - }; - - interface MailServer { - idempotent void sendEmail(Email msg) throws SendEmailFailed; - }; -}; - -#endif - diff --git a/gentoobrowse-api/service/notifications/notificationsimpl.cpp b/gentoobrowse-api/service/notifications/notificationsimpl.cpp deleted file mode 100644 index d7dbee4..0000000 --- a/gentoobrowse-api/service/notifications/notificationsimpl.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "notificationsimpl.h" -#include -#include -#include -#include -#include -#include -#include "xsltStreamSerializer.h" - -namespace Gentoo { - namespace Service { - xmlDocPtr xsltDocLoaderFunc (const xmlChar * URI, xmlDictPtr, int, void *, xsltLoadType) - { -#define MATCH(name) \ - if (xmlStrcmp(URI, BAD_CAST #name ".xslt") == 0) { \ - return xmlParseMemory((char *)name ## _xslt, name ## _xslt_len); \ - } - MATCH(base) - MATCH(news) - MATCH(signup) - return NULL; -#undef MATCH - } - - Notifications::Notifications() - { - xsltSetLoaderFunc(&xsltDocLoaderFunc); - news = xsltSSPtr(xsltParseStylesheetFile(BAD_CAST "news.xslt"), xsltFreeStylesheet); - signup = xsltSSPtr(xsltParseStylesheetFile(BAD_CAST "signup.xslt"), xsltFreeStylesheet); - xsltSetLoaderFunc(NULL); - } - - Gentoo::EmailPtr Notifications::getSignup(const Gentoo::NewUserPtr & u, const Ice::Current &) - { - auto e = basicMail("Welcome", u); - Slicer::SerializeAny(u, e, signup.get()); - return e; - } - - Gentoo::EmailPtr Notifications::getNews(const Gentoo::UserPtr & u, const Gentoo::NewsContent & c, const Ice::Current &) - { - auto e = basicMail("Latest updates", u); - Slicer::SerializeAny(c, e, news.get()); - return e; - } - - Gentoo::EmailPtr Notifications::basicMail(const std::string & subject, Gentoo::UserPtr u) - { - Gentoo::EmailPtr e = new Gentoo::Email(); - e->subject = "Gentoo Browse: " + subject; - e->from.name = "Gentoo Browse"; - e->from.address = "noreply@gentoobrowse.randomdan.homeip.net"; - e->to.name = u->userrealname; - e->to.address = u->useremail; - return e; - } - } -} - diff --git a/gentoobrowse-api/service/notifications/notificationsimpl.h b/gentoobrowse-api/service/notifications/notificationsimpl.h deleted file mode 100644 index 1d3b1fc..0000000 --- a/gentoobrowse-api/service/notifications/notificationsimpl.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef NOTIFICATIONSIMPL_H -#define NOTIFICATIONSIMPL_H - -#include -#include -#include -#include - -namespace Gentoo { - namespace Service { - class DLL_PUBLIC Notifications : public Gentoo::Notifications { - public: - Notifications(); - - Gentoo::EmailPtr getSignup(const Gentoo::NewUserPtr &, const Ice::Current &) override; - Gentoo::EmailPtr getNews(const Gentoo::UserPtr &, const Gentoo::NewsContent &, const Ice::Current &) override; - - private: - Gentoo::EmailPtr basicMail(const std::string &, Gentoo::UserPtr u); - - typedef std::shared_ptr xsltSSPtr; - xsltSSPtr news; - xsltSSPtr signup; - }; - } -} - -#endif - diff --git a/gentoobrowse-api/service/notifications/xsltStreamSerializer.cpp b/gentoobrowse-api/service/notifications/xsltStreamSerializer.cpp deleted file mode 100644 index 5a71b35..0000000 --- a/gentoobrowse-api/service/notifications/xsltStreamSerializer.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "xsltStreamSerializer.h" -#include -#include -#include -#include -#include - -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(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(new Gentoo::MimePart("text/html", strm.str())); - } - - void XsltStreamSerializer::appendText(xmlDoc * result) const - { - std::stringstream strm; - std::vector callLynx; - callLynx.push_back("/usr/bin/lynx"); - callLynx.push_back("-dump"); - callLynx.push_back("-stdin"); - std::string widthArg = "-width=105"; - 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(new Gentoo::MimePart("text/plain", strm.str())); - } -} - diff --git a/gentoobrowse-api/service/notifications/xsltStreamSerializer.h b/gentoobrowse-api/service/notifications/xsltStreamSerializer.h deleted file mode 100644 index 492b954..0000000 --- a/gentoobrowse-api/service/notifications/xsltStreamSerializer.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef ICESPIDER_CORE_XSLTSTREAMSERIALIZER_H -#define ICESPIDER_CORE_XSLTSTREAMSERIALIZER_H - -#include -#include -#include -#include - -namespace Gentoo { - class DLL_PUBLIC XsltStreamSerializer : public Slicer::XmlDocumentSerializer { - public: - XsltStreamSerializer(Gentoo::EmailPtr, xsltStylesheet *); - ~XsltStreamSerializer(); - - void Serialize(Slicer::ModelPartForRootPtr mp) override; - - protected: - void appendHtml(xmlDoc *) const; - void appendText(xmlDoc *) const; - - Gentoo::EmailPtr mail; - xmlpp::Document * doc; - xsltStylesheet * stylesheet; - }; -} - -#endif - diff --git a/gentoobrowse-api/service/notificationsimpl.cpp b/gentoobrowse-api/service/notificationsimpl.cpp new file mode 100644 index 0000000..270e264 --- /dev/null +++ b/gentoobrowse-api/service/notificationsimpl.cpp @@ -0,0 +1,59 @@ +#include "notificationsimpl.h" +#include +#include +#include +#include +#include +#include +#include "xsltStreamSerializer.h" + +namespace Gentoo { + namespace Service { + xmlDocPtr xsltDocLoaderFunc (const xmlChar * URI, xmlDictPtr, int, void *, xsltLoadType) + { +#define MATCH(name) \ + if (xmlStrcmp(URI, BAD_CAST #name ".xslt") == 0) { \ + return xmlParseMemory((char *)name ## _xslt, name ## _xslt_len); \ + } + MATCH(base) + MATCH(news) + MATCH(signup) + return NULL; +#undef MATCH + } + + Notifications::Notifications() + { + xsltSetLoaderFunc(&xsltDocLoaderFunc); + news = xsltSSPtr(xsltParseStylesheetFile(BAD_CAST "news.xslt"), xsltFreeStylesheet); + signup = xsltSSPtr(xsltParseStylesheetFile(BAD_CAST "signup.xslt"), xsltFreeStylesheet); + xsltSetLoaderFunc(NULL); + } + + Gentoo::EmailPtr Notifications::getSignup(const Gentoo::NewUserPtr & u, const Ice::Current &) + { + auto e = basicMail("Welcome", u); + Slicer::SerializeAny(u, e, signup.get()); + return e; + } + + Gentoo::EmailPtr Notifications::getNews(const Gentoo::UserPtr & u, const Gentoo::NewsContent & c, const Ice::Current &) + { + auto e = basicMail("Latest updates", u); + Slicer::SerializeAny(c, e, news.get()); + return e; + } + + Gentoo::EmailPtr Notifications::basicMail(const std::string & subject, Gentoo::UserPtr u) + { + Gentoo::EmailPtr e = new Gentoo::Email(); + e->subject = "Gentoo Browse: " + subject; + e->from.name = "Gentoo Browse"; + e->from.address = "noreply@gentoobrowse.randomdan.homeip.net"; + e->to.name = u->userrealname; + e->to.address = u->useremail; + return e; + } + } +} + diff --git a/gentoobrowse-api/service/notificationsimpl.h b/gentoobrowse-api/service/notificationsimpl.h new file mode 100644 index 0000000..1d3b1fc --- /dev/null +++ b/gentoobrowse-api/service/notificationsimpl.h @@ -0,0 +1,29 @@ +#ifndef NOTIFICATIONSIMPL_H +#define NOTIFICATIONSIMPL_H + +#include +#include +#include +#include + +namespace Gentoo { + namespace Service { + class DLL_PUBLIC Notifications : public Gentoo::Notifications { + public: + Notifications(); + + Gentoo::EmailPtr getSignup(const Gentoo::NewUserPtr &, const Ice::Current &) override; + Gentoo::EmailPtr getNews(const Gentoo::UserPtr &, const Gentoo::NewsContent &, const Ice::Current &) override; + + private: + Gentoo::EmailPtr basicMail(const std::string &, Gentoo::UserPtr u); + + typedef std::shared_ptr xsltSSPtr; + xsltSSPtr news; + xsltSSPtr signup; + }; + } +} + +#endif + diff --git a/gentoobrowse-api/service/xsltStreamSerializer.cpp b/gentoobrowse-api/service/xsltStreamSerializer.cpp new file mode 100644 index 0000000..5a71b35 --- /dev/null +++ b/gentoobrowse-api/service/xsltStreamSerializer.cpp @@ -0,0 +1,82 @@ +#include "xsltStreamSerializer.h" +#include +#include +#include +#include +#include + +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(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(new Gentoo::MimePart("text/html", strm.str())); + } + + void XsltStreamSerializer::appendText(xmlDoc * result) const + { + std::stringstream strm; + std::vector callLynx; + callLynx.push_back("/usr/bin/lynx"); + callLynx.push_back("-dump"); + callLynx.push_back("-stdin"); + std::string widthArg = "-width=105"; + 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(new Gentoo::MimePart("text/plain", strm.str())); + } +} + diff --git a/gentoobrowse-api/service/xsltStreamSerializer.h b/gentoobrowse-api/service/xsltStreamSerializer.h new file mode 100644 index 0000000..492b954 --- /dev/null +++ b/gentoobrowse-api/service/xsltStreamSerializer.h @@ -0,0 +1,28 @@ +#ifndef ICESPIDER_CORE_XSLTSTREAMSERIALIZER_H +#define ICESPIDER_CORE_XSLTSTREAMSERIALIZER_H + +#include +#include +#include +#include + +namespace Gentoo { + class DLL_PUBLIC XsltStreamSerializer : public Slicer::XmlDocumentSerializer { + public: + XsltStreamSerializer(Gentoo::EmailPtr, xsltStylesheet *); + ~XsltStreamSerializer(); + + void Serialize(Slicer::ModelPartForRootPtr mp) override; + + protected: + void appendHtml(xmlDoc *) const; + void appendText(xmlDoc *) const; + + Gentoo::EmailPtr mail; + xmlpp::Document * doc; + xsltStylesheet * stylesheet; + }; +} + +#endif + diff --git a/gentoobrowse-api/unittests/Jamfile.jam b/gentoobrowse-api/unittests/Jamfile.jam index 9225210..a53781e 100644 --- a/gentoobrowse-api/unittests/Jamfile.jam +++ b/gentoobrowse-api/unittests/Jamfile.jam @@ -30,6 +30,7 @@ lib testCommon : ..//IceBox dryice ../service//gentoobrowse-service + ../service//gentoobrowse-service boost_utf : : dbpp-postgresql @@ -38,6 +39,7 @@ lib testCommon : ..//IceBox dryice ../service//gentoobrowse-service + ../service//gentoobrowse-service ..//IceUtil ..//Ice ..//boost_system -- cgit v1.2.3