summaryrefslogtreecommitdiffstats
path: root/lurker/render/Cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lurker/render/Cache.cpp')
-rw-r--r--lurker/render/Cache.cpp196
1 files changed, 196 insertions, 0 deletions
diff --git a/lurker/render/Cache.cpp b/lurker/render/Cache.cpp
new file mode 100644
index 0000000..f82c6f9
--- /dev/null
+++ b/lurker/render/Cache.cpp
@@ -0,0 +1,196 @@
+/* $Id: Cache.cpp 1649 2009-10-19 14:35:01Z terpstra $
+ *
+ * Cache.h - Helper which transforms xml -> html and caches files
+ *
+ * Copyright (C) 2002 - Wesley W. Terpstra
+ *
+ * License: GPL
+ *
+ * Authors: 'Wesley W. Terpstra' <wesley@terpstra.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _FILE_OFFSET_BITS 64
+
+#include "Cache.h"
+#include "commands.h"
+
+#include <cerrno>
+#include <cstring>
+#include <cassert>
+
+#include <unistd.h>
+
+class streambug : public std::streambuf
+{
+ public:
+ streambug();
+
+ void set_target(FILE* t) { target = t; }
+
+ protected:
+ int overflow(int);
+ int sync();
+
+ private:
+ FILE* target;
+ char buf[128]; //8192];
+};
+
+streambug::streambug()
+ : target(0)
+{
+ setp(&buf[0], &buf[sizeof(buf)-1]);
+ setg(0,0,0); // output only
+}
+
+int streambug::overflow(int c)
+{
+ assert (target);
+
+ // Make sure there is a put area
+ if (!pptr()) setp(&buf[0], &buf[sizeof(buf)-1]);
+
+ // Determine how many characters have been
+ // inserted but not consumed.
+ std::streamsize w = pptr() - pbase();
+
+ // If c is not EOF it is a character that must
+ // also be consumed.
+ if (c != EOF)
+ {
+ // We always leave space
+ *pptr() = c;
+ ++w;
+ }
+
+ // consume characters.
+ if ((std::streamsize)fwrite(pbase(), 1, w, target) == w)
+ { // Set up put area. Be sure that there
+ // is space at end for one extra character.
+
+ setp(&buf[0], &buf[sizeof(buf)-1]);
+
+ if (c == EOF) return 0;
+ return c;
+ }
+ else
+ { // Indicate error.
+ setp(0, 0);
+ return EOF;
+ }
+}
+
+int streambug::sync()
+{
+ if (pptr() && pptr() > pbase())
+ { // Flush waiting output
+ return overflow(EOF);
+ }
+
+ return 0;
+}
+
+Cache::Cache(const Config& cfg, const string& command, const string& parameter, const string& ext)
+ : bug(new streambug), o(bug)
+{
+ if (chdir(command.c_str()) != 0)
+ error(_("Entering command dir"), command + ":" + strerror(errno),
+ _("Perhaps the directory does not exist to which "
+ "the cache file is being written."));
+
+ if (cfg.web_cache)
+ {
+ cache = fopen(parameter.c_str(), "w+");
+ if (!cache)
+ error(_("Creating cache file"), parameter + ":" + strerror(errno),
+ _("Perhaps the user which runs lurker.cgi does not have write "
+ "permissions to this directory."));
+ }
+ else
+ {
+ cache = stdout;
+ }
+
+ if (ext == "html")
+ {
+ char buf[10] = "";
+ if (cache != stdout) sprintf(buf, " >&%d", fileno(cache));
+ string command = cfg.xslt + buf;
+
+ output = popen(command.c_str(), "w");
+ if (!output)
+ error(_("Opening xslt pipeline"), strerror(errno),
+ _("The specified xslt pipeline in your config "
+ "file, entry xslt, could not be opened. "
+ "Please ensure that the command correctly "
+ "streams xml into html for you."));
+
+ cout << "Status: 200 OK\r\n";
+ cout << "Content-Type: text/html; charset=UTF-8\r\n\r\n";
+ }
+ else if (ext == "txt")
+ {
+ cout << "Status: 200 OK\r\n";
+ cout << "Content-Type: text/plain\r\n\r\n";
+ output = cache;
+ }
+ else if (ext == "rfc822")
+ {
+ cout << "Status: 200 OK\r\n";
+ cout << "Content-Type: message/rfc822\r\n\r\n";
+ output = cache;
+ }
+ else if (ext == "xml")
+ {
+ cout << "Status: 200 OK\r\n";
+ cout << "Content-Type: text/xml; charset=UTF-8\r\n\r\n";
+ output = cache;
+ }
+ else
+ {
+ error(_("Unknown file type"), ext,
+ _("The requested extension is not supported by lurker. "
+ "Please reformulate your request."));
+ }
+
+ cout.flush(); // in case of stdout writing next (ick)
+ bug->set_target(output);
+}
+
+Cache::~Cache()
+{
+ o.flush();
+
+ if (output != cache)
+ pclose(output);
+
+ if (cache != stdout)
+ {
+ // reset to the start of the cache file
+ fflush(cache);
+ fseek(cache, 0, SEEK_SET);
+ fflush(cache);
+
+ // Begin streaming to cout
+ char buf[4096];
+ size_t got;
+
+ while ((got = fread(buf, 1, sizeof(buf), cache)) != 0)
+ cout.write(buf, got);
+ }
+
+ // All done!
+}