[pan2/merge_xzver_mt] two files added
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2/merge_xzver_mt] two files added
- Date: Tue, 17 Jul 2012 18:17:15 +0000 (UTC)
commit c1dd87dde67a1a1436a0ff5b287cd6db3754b050
Author: Heinrich MÃller <henmull src gnome org>
Date: Tue Jul 17 20:16:44 2012 +0200
two files added
pan/tasks/xzver-decoder.cc | 325 ++++++++++++++++++++++++++++++++++++++++++++
pan/tasks/xzver-decoder.h | 102 ++++++++++++++
2 files changed, 427 insertions(+), 0 deletions(-)
---
diff --git a/pan/tasks/xzver-decoder.cc b/pan/tasks/xzver-decoder.cc
new file mode 100644
index 0000000..9271501
--- /dev/null
+++ b/pan/tasks/xzver-decoder.cc
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2007 Charles Kerr <charles rebelbase com>
+ *
+ * This file
+ * Copyright (C) 2007 Calin Culianu <calin ajvar org>
+ * Copyright (C) 2007 Charles Kerr <charles rebelbase com>
+ *
+ * This file 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 2 of the License, or (at your option) any later version.
+ *
+ * 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
+ */
+#include <config.h>
+#include <cerrno>
+#include <ostream>
+#include <fstream>
+extern "C" {
+# define PROTOTYPES
+# include <uulib/uudeview.h>
+# include <glib/gi18n.h>
+};
+#include <pan/general/worker-pool.h>
+#include <pan/general/debug.h>
+#include <pan/general/file-util.h>
+#include <pan/general/macros.h>
+#include <pan/general/utf8-utils.h>
+#include "xzver-decoder.h"
+
+using namespace pan;
+
+/***
+****
+***/
+
+using namespace pan;
+
+XZVERDecoder :: XZVERDecoder (WorkerPool& pool) :
+ Decoder(pool)
+{
+ _cnt = 0;
+}
+
+XZVERDecoder :: ~XZVERDecoder()
+{
+ disable_progress_update();
+}
+
+void
+XZVERDecoder :: enqueue (TaskXOver * task, TaskXOver::DataStream* stream, Data* data)
+{
+
+ _cnt = 0;
+
+ disable_progress_update ();
+
+ this->xtask = task;
+ this->stream = stream;
+ this->data = data;
+ this->nntp = new NNTP(stream->server, "", "", 0);
+ this->nntp->_group = stream->group;
+
+ log_infos.clear();
+ log_errors.clear();
+
+ // gentlemen, start your saving...
+ _worker_pool.push_work (this, task, false);
+}
+
+namespace
+{
+ char* build_cachename (char* buf, size_t len, const char* name)
+ {
+ const char * home(file::get_pan_home().c_str());
+ g_snprintf(buf,len,"%s%c%s%c%s",home, G_DIR_SEPARATOR, "encode-cache", G_DIR_SEPARATOR, name);
+ return buf;
+ }
+}
+
+namespace
+{
+ unsigned long view_to_ul (const StringView& view)
+ {
+ unsigned long ul = 0ul;
+
+ if (!view.empty()) {
+ errno = 0;
+ ul = strtoul (view.str, 0, 10);
+ if (errno)
+ ul = 0ul;
+ }
+
+ return ul;
+ }
+ uint64_t view_to_ull (const StringView& view)
+ {
+ uint64_t ul = 0ul;
+
+ if (!view.empty()) {
+ errno = 0;
+ ul = g_ascii_strtoull (view.str, 0, 10);
+ if (errno)
+ ul = 0ul;
+ }
+
+ return ul;
+ }
+
+ bool header_is_nonencoded_utf8 (const StringView& in)
+ {
+ const bool is_nonencoded (!in.strstr("=?"));
+ const bool is_utf8 (g_utf8_validate (in.str, in.len, 0));
+ return is_nonencoded && is_utf8;
+ }
+}
+
+void
+XZVERDecoder :: on_nntp_batch_process (StringView & line)
+{
+ unsigned int lines=0u;
+ unsigned long bytes=0ul;
+ uint64_t number=0;
+
+ StringView subj, author, date, mid, tmp, xref;
+ StringView& l = line;
+ std::string ref;
+
+ bool ok = !l.empty();
+ ok = ok && l.pop_token (tmp, '\t'); if (ok) number = view_to_ull (tmp); tmp.clear();
+ ok = ok && l.pop_token (subj, '\t'); if (ok) subj.trim ();
+ ok = ok && l.pop_token (author, '\t'); if (ok) author.trim ();
+ ok = ok && l.pop_token (date, '\t'); if (ok) date.trim ();
+ ok = ok && l.pop_token (mid, '\t'); if (ok) mid.trim ();
+
+ //handle multiple "References:"-message-ids correctly.
+ ok = ok && l.pop_token (tmp, '\t');
+ do
+ {
+ if (tmp.empty()) continue;
+ if (tmp.front() == '<')
+ {
+ tmp.trim();
+ ref += tmp;
+ tmp.clear();
+ } else break;
+ } while ((ok = ok && l.pop_token (tmp, '\t'))) ;
+
+ if (ok) bytes = view_to_ul (tmp); tmp.clear();
+ ok = ok && l.pop_token (tmp, '\t'); if (ok) lines = view_to_ul (tmp);
+ ok = ok && l.pop_token (xref, '\t'); if (ok) xref.trim ();
+
+ if (xref.len>6 && !strncmp(xref.str,"Xref: ", 6)) {
+ xref = xref.substr (xref.str+6, 0);
+ xref.trim ();
+ }
+
+ // is this header corrupt?
+ if (!number // missing number
+ || subj.empty() // missing subject
+ || author.empty() // missing author
+ || date.empty() // missing date
+ || mid.empty() // missing mid
+ || mid.front()!='<') // corrupt mid
+ /// Concerning bug : https://bugzilla.gnome.org/show_bug.cgi?id=650042
+ /// Even if we didn't get a proper reference here, continue.
+ //|| (!ref.empty() && ref.front()!='<'))
+ return;
+
+ // if news server doesn't provide an xref, fake one
+ char * buf (0);
+ if (xref.empty())
+ xref = buf = g_strdup_printf ("%s %s:%"G_GUINT64_FORMAT,
+ nntp->_server.c_str(),
+ nntp->_group.c_str(),
+ number);
+
+ const char * fallback_charset = NULL; // FIXME
+ const time_t time_posted = g_mime_utils_header_decode_date (date.str, NULL);
+
+ data->xover_add (
+ nntp->_server, nntp->_group,
+ (header_is_nonencoded_utf8(subj) ? subj : header_to_utf8(subj,fallback_charset).c_str()),
+ (header_is_nonencoded_utf8(author) ? author : header_to_utf8(author,fallback_charset).c_str()),
+ time_posted, mid, StringView(ref), bytes, lines, xref);
+
+ high = std::max (high, number);
+
+ g_free (buf);
+}
+
+void
+XZVERDecoder :: find_lines()
+{
+ StringView ret;
+
+ while(!s_stream.eof())
+ {
+ std::string out;
+ getline(s_stream, out);
+ ret.assign(out);
+ xtask->on_nntp_line_process(nntp, ret);
+ _cnt++;
+ }
+
+}
+
+
+// save article IN A WORKER THREAD to avoid network stalls
+void
+XZVERDecoder :: do_work()
+{
+
+ const int bufsz = 4096;
+ char buf[bufsz];
+
+ disable_progress_update();
+
+ int res;
+ if (((res = UUInitialize())) != UURET_OK)
+ log_errors.push_back(_("Error initializing uulib")); // log error
+ else
+ {
+ build_cachename(buf,sizeof(buf), "xzver_test");
+ std::ofstream test (buf);
+ test << stream->stream->str();
+ test.close();
+
+ // TODO mod uulib to use streams!
+
+ UUSetOption (UUOPT_DESPERATE, 0, NULL);
+ UUSetOption (UUOPT_IGNMODE, 1, NULL); // don't save file as executable
+ UULoadFile (buf, 0, 0);
+ UUDecodeFile (UUGetFileListItem (0), build_cachename(buf,sizeof(buf), "xzver_decoded"));
+ UUCleanUp ();
+ }
+
+// disable_progress_update();
+
+ _strm.zalloc = Z_NULL;
+ _strm.zfree = Z_NULL;
+ _strm.opaque = Z_NULL;
+ _strm.avail_in = 0;
+ _strm.next_in = Z_NULL;
+
+ _zret = inflateInit2(&_strm,-MAX_WBITS); //raw inflate
+ if (_zret != Z_OK)
+ {
+ log_errors.push_back(_("Error initializing zlib deflate"));
+ return;
+ }
+
+ std::ifstream headers;
+ FILE * in = fopen(build_cachename(buf,sizeof(buf), "xzver_decoded"), "rb");
+
+ if (!in)
+ {
+ char tmpbuf[2048];
+ g_snprintf(tmpbuf, sizeof(tmpbuf), _("Error opening header file %s"), buf);
+ log_errors.push_back(tmpbuf);
+ return;
+ }
+
+ int ret;
+ char fbuf[CHUNK];
+ StringView line;
+
+ do
+ {
+ size_t len = fread(fbuf, sizeof(char), CHUNK, in);
+ if (len==0 || ferror(in)) break;
+ ret = inflate_xzver (len, fbuf);
+ } while (!feof(in) && _zret == Z_OK);
+
+ find_lines();
+
+ if (in) fclose(in);
+ (void)inflateEnd(&_strm);
+
+ xtask->setHigh(nntp->_server, high);
+
+}
+
+int
+XZVERDecoder :: inflate_xzver (size_t len, char* buf)
+{
+
+ InflateChunk ret;
+
+ _strm.avail_in = len;
+ _strm.next_in = (unsigned char*)buf;
+
+ /* run inflate() on input until output buffer not full */
+ do {
+ _strm.avail_out = CHUNK;
+ _strm.next_out = ret.tmpbuf;
+ _zret = inflate(&_strm, Z_NO_FLUSH);
+ assert(_zret != Z_STREAM_ERROR); /* state not clobbered */
+ switch (_zret) {
+ case Z_NEED_DICT:
+ _zret = Z_DATA_ERROR; /* and fall through */
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ (void)inflateEnd(&_strm);
+ return _zret;
+ }
+
+ s_stream<<ret.tmpbuf;
+
+ } while (_strm.avail_out == 0);
+
+ return _zret == Z_STREAM_END ? Z_OK : Z_STREAM_ERROR;
+
+}
+
+
diff --git a/pan/tasks/xzver-decoder.h b/pan/tasks/xzver-decoder.h
new file mode 100644
index 0000000..4515f0f
--- /dev/null
+++ b/pan/tasks/xzver-decoder.h
@@ -0,0 +1,102 @@
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2007 Charles Kerr <charles rebelbase com>
+ *
+ * This file
+ * Copyright (C) 2007 Calin Culianu <calin ajvar org>
+ * Copyright (C) 2007 Charles Kerr <charles rebelbase com>
+ *
+ * This file 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 2 of the License, or (at your option) any later version.
+ *
+ * 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
+ */
+#ifndef _XZVERDecoder_H_
+#define _XZVERDecoder_H_
+
+#include <list>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <fstream>
+
+#include <pan/general/locking.h>
+#include <pan/general/worker-pool.h>
+#include <pan/tasks/task-xover.h>
+#include <pan/tasks/decoder.h>
+extern "C" {
+# define PROTOTYPES
+# include <uulib/uudeview.h>
+};
+
+namespace pan
+{
+ #define CHUNK 16384
+
+ class Decoder;
+
+ /**
+ * Decodes XZVER yenc-encoded and zlib-deflated
+ * headers to process with TaskXOver
+ * @author Heinrich Mueller <heinrich mueller82 gmail com>
+ * @author Calin Culianu <calin ajvar org>
+ * @author Charles Kerr <charles rebelbase com>
+ * @ingroup tasks
+ * @see Queue
+ * @see TaskXOver
+ */
+ class XZVERDecoder: public Decoder
+ {
+ public:
+
+ struct InflateChunk
+ {
+ int ret;
+ unsigned char tmpbuf[CHUNK]; // dbg
+ };
+
+ XZVERDecoder (WorkerPool&);
+
+ ~XZVERDecoder ();
+
+ typedef std::vector<std::string> strings_t;
+
+ void enqueue (TaskXOver * task, TaskXOver::DataStream*, Data*);
+
+ protected: // inherited from WorkerPool::Worker
+
+ void do_work();
+ TaskXOver * xtask;
+ TaskXOver::DataStream* stream;
+
+ z_stream _strm;
+ int _zret;
+ NNTP* nntp;
+ int _cnt;
+ Data* data;
+ uint64_t high;
+ GString * out;
+ unsigned char outbuf[4096];
+
+ int inflate_xzver (size_t len, char* buf);
+ void on_nntp_batch_process (StringView&);
+ void find_lines();
+
+ std::stringstream s_stream; // output for inflate
+
+ };
+}
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]