[pan2: 37/268] first version of upload utility
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2: 37/268] first version of upload utility
- Date: Mon, 2 Jan 2012 15:41:06 +0000 (UTC)
commit 68b555bf3d7a45ebc04a932383f31c832335f59a
Author: Heinrich Mueller <sphemuel stud informatik uni-erlangen de>
Date: Thu May 26 22:23:52 2011 +0200
first version of upload utility
pan/data/file-queue.cc | 4 +-
pan/data/file-queue.h | 4 +-
pan/general/file-util.cc | 2 +-
pan/general/file-util.h | 2 +-
pan/gui/post-ui.cc | 9 +-
pan/tasks/encoder.cc | 232 ++++++++++++++++++++++++++++++++++
pan/tasks/encoder.h | 101 +++++++++++++++
pan/tasks/task-upload.cc | 274 ++++++++++++++++++++++++++++++++++++++++
pan/tasks/task-upload.h | 156 +++++++++++++++++++++++
pan/tasks/task-weak-ordering.h | 5 +-
pan/usenet-utils/mime-utils.cc | 6 +-
pan/usenet-utils/mime-utils.h | 2 +-
12 files changed, 782 insertions(+), 15 deletions(-)
---
diff --git a/pan/data/file-queue.cc b/pan/data/file-queue.cc
index 8225cc5..faf09ca 100644
--- a/pan/data/file-queue.cc
+++ b/pan/data/file-queue.cc
@@ -47,10 +47,12 @@ FileQueue :: add (const char* filename,
static FileData a;
struct stat sb;
a.filename = filename;
+ a.basename = g_path_get_basename(filename);
stat(filename,&sb);
a.byte_count = sb.st_size;
+ a.part_in_queue = type == END ? _articles_v.size() : 1;
- type == FileQueue::END ?
+ type == END ?
_articles_v.push_back(a) :
_articles_v.push_front(a);
}
diff --git a/pan/data/file-queue.h b/pan/data/file-queue.h
index 87c1ae7..2c37dbc 100644
--- a/pan/data/file-queue.h
+++ b/pan/data/file-queue.h
@@ -47,14 +47,16 @@ namespace pan {
{
const char * filename;
+ const char * basename;
unsigned long byte_count;
+ unsigned long part_in_queue;
FileData() {}
};
typedef std::list<FileData>::iterator articles_it;
typedef std::list<FileData> articles_v;
-
+ size_t size() { return _articles_v.size(); }
articles_it end() { return _articles_v.end(); }
articles_it begin() { return _articles_v.begin(); }
bool empty() { return _articles_v.empty(); }
diff --git a/pan/general/file-util.cc b/pan/general/file-util.cc
index a38367e..1a90d89 100644
--- a/pan/general/file-util.cc
+++ b/pan/general/file-util.cc
@@ -49,7 +49,7 @@ using namespace pan;
***/
std::string
-file :: get_pan_uulib_dir()
+file :: get_uulib_path()
{
char * pch (g_build_filename (file::get_pan_home().c_str(), "uulib-encode-cache", NULL));
file :: ensure_dir_exists (pch);
diff --git a/pan/general/file-util.h b/pan/general/file-util.h
index 7928ce5..25bde1c 100644
--- a/pan/general/file-util.h
+++ b/pan/general/file-util.h
@@ -58,7 +58,7 @@ namespace pan
*/
std::string get_pan_home ();
- std::string get_pan_uulib_dir();
+ std::string get_uulib_path();
/**
* If the specified directory doesn't exist, Pan tries to create it.
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 2c408e2..b569129 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -727,12 +727,9 @@ PostUI :: maybe_post_message (GMimeMessage * message)
for (; it != _file_queue.end(); it, ++it, ++i) {
GMimeMessage* msg = new_message_from_ui(POSTING);
- _queue.add_task (new TaskUpload (*it,profile.posting_server,msg
- ,0,TaskUpload::YENC),
- Queue::BOTTOM);
+ _queue.add_task (new TaskUpload (*it,profile.posting_server,msg), Queue::BOTTOM);
}
- //dbg
-// close_window(true); // dont wait for the upload queue
+ close_window(true); // dont wait for the upload queue
}
@@ -1090,7 +1087,9 @@ PostUI :: new_message_from_ui (Mode mode)
GMimeDataWrapper * content_object = g_mime_data_wrapper_new_with_stream (stream, GMIME_CONTENT_ENCODING_DEFAULT);
g_object_unref (stream);
GMimePart * part = g_mime_part_new ();
+ //todo ??
pch = g_strdup_printf ("text/plain; charset=%s", charset.c_str());
+
GMimeContentType * type = g_mime_content_type_new_from_string (pch);
g_free (pch);
g_mime_object_set_content_type ((GMimeObject *) part, type); // part owns type now. type isn't refcounted.
diff --git a/pan/tasks/encoder.cc b/pan/tasks/encoder.cc
new file mode 100644
index 0000000..01db2f4
--- /dev/null
+++ b/pan/tasks/encoder.cc
@@ -0,0 +1,232 @@
+/* -*- 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 <algorithm>
+#include <cerrno>
+#include <ostream>
+#include <fstream>
+extern "C" {
+# define PROTOTYPES
+# include <uulib/uudeview.h>
+# include <glib/gi18n.h>
+};
+#include <pan/general/debug.h>
+#include <pan/general/file-util.h>
+#include <pan/general/macros.h>
+#include <pan/general/utf8-utils.h>
+#include "encoder.h"
+
+using namespace pan;
+
+Encoder :: Encoder (WorkerPool& pool):
+ _worker_pool (pool),
+ _gsourceid (-1)
+{
+}
+
+Encoder :: ~Encoder()
+{
+ disable_progress_update();
+}
+
+/***
+****
+***/
+
+void
+Encoder :: enqueue (TaskUpload * task,
+ const FileQueue::FileData & file_data,
+ TaskUpload::EncodeMode enc)
+
+{
+ disable_progress_update ();
+
+ this->task = task;
+ this->file_data = file_data;
+ this->encode_mode = encode_mode;
+
+ mark_read = false;
+ percent = 0;
+ current_file.clear ();
+ log_infos.clear();
+ log_errors.clear();
+
+ // gentlemen, start your saving...
+ _worker_pool.push_work (this, task, false);
+}
+
+// save article IN A WORKER THREAD to avoid network stalls
+void
+Encoder :: do_work()
+{
+ const int bufsz = 4096;
+ char buf[bufsz], buf2[bufsz];
+ unsigned long cnt(1);
+ crc32_t crcptr;
+
+ FILE* outfile, * infile ;
+
+ std::string uulib(file :: get_uulib_path());
+
+ std::cerr<<"encoder starting...\n";
+
+ enable_progress_update();
+
+ int res;
+ if (((res = UUInitialize())) != UURET_OK)
+ {
+ log_errors.push_back(_("Error initializing uulib")); // log error
+ this->cancel();
+ } else {
+ UUSetMsgCallback (this, uu_log);
+ UUSetBusyCallback (this, uu_busy_poll, 100);
+
+ char* basename = g_path_get_basename(file_data.filename);
+ g_snprintf(buf,bufsz,"%s/%s.%d", uulib.c_str(), basename, cnt);
+ outfile = fopen(buf,"wb");
+ while (1) {
+ res = UUEncodePartial (outfile, NULL, (char*)file_data.filename, YENC_ENCODED,
+ buf, NULL, 0, cnt, 4000, &crcptr);
+ if (outfile) fclose(outfile);
+ if (res == UURET_OK || res != UURET_CONT) break;
+ g_snprintf(buf,bufsz,"%s/%s.%d", uulib.c_str(), basename, ++cnt);
+ outfile = fopen(buf,"wb");
+ }
+
+ if (res != UURET_OK)
+ {
+ g_snprintf(buf, bufsz,
+ _("Error encoding %s: %s"),
+ basename,
+ (res==UURET_IOERR)
+ ? file::pan_strerror (UUGetOption (UUOPT_ERRNO, NULL,
+ NULL, 0))
+ : UUstrerror(res));
+ log_errors.push_back(buf); // log error
+ }
+ UUCleanUp ();
+ }
+ disable_progress_update();
+}
+
+/***
+****
+***/
+
+void
+Encoder :: uu_log (void* data, char* message, int severity)
+{
+ Encoder *self = static_cast<Encoder *>(data);
+ char * pch (g_locale_to_utf8 (message, -1, 0, 0, 0));
+
+ if (severity >= UUMSG_WARNING)
+ self->file_errors.push_back (pch ? pch : message);
+
+ if (severity >= UUMSG_ERROR)
+ self->log_errors.push_back (pch ? pch : message);
+ else if (severity >= UUMSG_NOTE)
+ self->log_infos.push_back (pch ? pch : message);
+
+ g_free (pch);
+}
+
+double
+Encoder :: get_percentage (const uuprogress& p) const
+{
+ static const double WEIGHT_SCANNING = 30;
+ static const double WEIGHT_ENCODING = 70;
+
+ double base = 0;
+
+ if (p.action != UUACT_SCANNING)
+ base += WEIGHT_SCANNING;
+ else {
+ const double percent = (100.0 + p.percent);
+ return base + (percent / (100.0/WEIGHT_SCANNING));
+ }
+
+ if (p.action != UUACT_ENCODING)
+ base += WEIGHT_ENCODING;
+ else {
+ // uudeview's documentation is wrong:
+ // the total percentage isn't (100*partno-percent)/numparts,
+ // it's (100*(partno-1) + percent)/numparts
+ const double percent = ((100.0 * (p.partno-1)) + p.percent) / p.numparts;
+ return base + (percent / (100.0/WEIGHT_ENCODING));
+ }
+
+ return 0;
+}
+
+int
+Encoder :: uu_busy_poll (void * d, uuprogress *p)
+{
+ Encoder * self (static_cast<Encoder*>(d));
+ self->mut.lock();
+ self->percent = self->get_percentage(*p);
+ self->current_file = p->curfile;
+ self->parts = (int)p->numparts;
+ self->mut.unlock();
+
+ return self->was_cancelled(); // returning true tells uulib to abort
+}
+
+// this is called in the main thread
+gboolean
+Encoder :: progress_update_timer_func (gpointer decoder)
+{
+ Encoder *self = static_cast<Encoder *>(decoder);
+ Task *task = self->task;
+ if (!task || self->was_cancelled()) return false;
+
+ self->mut.lock();
+ const double percent (self->percent);
+ const std::string f (content_to_utf8 (self->current_file));
+ self->mut.unlock();
+
+ task->set_step(int(percent));
+ task->set_status_va (_("Encoding %s"), f.c_str());
+
+ return true; // keep timer func running
+}
+
+/***
+****
+***/
+
+void
+Encoder :: enable_progress_update ()
+{
+ if (_gsourceid == -1)
+ _gsourceid = g_timeout_add(500, progress_update_timer_func, this);
+}
+
+void
+Encoder :: disable_progress_update ()
+{
+ if (_gsourceid > -1) {
+ g_source_remove (_gsourceid);
+ _gsourceid = -1;
+ }
+}
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
new file mode 100644
index 0000000..7a73893
--- /dev/null
+++ b/pan/tasks/encoder.h
@@ -0,0 +1,101 @@
+/* -*- 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 _Encoder_H_
+#define _Encoder_H_
+
+#include <list>
+#include <string>
+#include <vector>
+#include <pan/general/locking.h>
+#include <pan/general/worker-pool.h>
+#include <pan/tasks/task-upload.h>
+extern "C" {
+# define PROTOTYPES
+# include <uulib/uudeview.h>
+# include <uulib/crc32.h>
+};
+
+namespace pan
+{
+ /**
+ * Encodes attachments (YEnc) for posting to usenet groups.
+ *
+ * @author Heinrich Mueller <eddie_v gmx de>
+ * @author Calin Culianu <calin ajvar org>
+ * @author Charles Kerr <charles rebelbase com>
+ * @ingroup tasks
+ * @see Queue
+ * @see TaskArticle
+ */
+ class Encoder: public WorkerPool::Worker
+ {
+ public:
+
+ Encoder (WorkerPool&);
+
+ ~Encoder ();
+
+ typedef std::vector<std::string> strings_t;
+
+ void enqueue (TaskUpload * task,
+ const FileQueue::FileData & file_data,
+ TaskUpload::EncodeMode enc = TaskUpload::YENC);
+
+ public:
+
+ typedef std::list<std::string> log_t;
+ log_t log_severe, log_errors, log_infos, file_errors;
+ bool mark_read;
+
+ protected: // inherited from WorkerPool::Worker
+
+ void do_work();
+
+ private:
+
+ friend class TaskUpload;
+ TaskUpload * task;
+ TaskUpload::EncodeMode encode_mode;
+ FileQueue::FileData file_data;
+
+ // These are set in the worker thread and polled in the main thread.
+ Mutex mut;
+ volatile double percent;
+ std::string current_file; // the current file we are decoding, with path
+ int parts;
+
+ static void uu_log(void *thiz, char *message, int severity);
+ double get_percentage (const uuprogress& p) const;
+ static int uu_busy_poll(void * self, uuprogress *p);
+ /** tell our task about the decode's progress */
+ static gboolean progress_update_timer_func(gpointer decoder);
+
+ WorkerPool& _worker_pool;
+ int _gsourceid;
+ void disable_progress_update();
+ void enable_progress_update();
+ };
+}
+
+#endif
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
new file mode 100644
index 0000000..8d2f7f8
--- /dev/null
+++ b/pan/tasks/task-upload.cc
@@ -0,0 +1,274 @@
+/* -*- 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 Charles Kerr <charles rebelbase com>
+ * Copyright (C) 2007 Calin Culianu <calin ajvar org>
+ *
+ * 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 of the License.
+ *
+ * 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 <algorithm>
+#include <cassert>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+
+extern "C" {
+#include <glib/gi18n.h>
+}
+#include <pan/general/debug.h>
+#include <pan/general/file-util.h>
+#include <pan/general/log.h>
+#include <pan/general/macros.h>
+#include <pan/usenet-utils/mime-utils.h>
+#include <pan/data/article-cache.h>
+#include "encoder.h"
+#include "task-upload.h"
+
+using namespace pan;
+
+namespace
+{
+ std::string get_description (const char* name, bool enc)
+ {
+ char buf[1024];
+ if (!enc)
+ snprintf (buf, sizeof(buf), _("Uploading %s"), name);
+ else
+ snprintf (buf, sizeof(buf), _("Encoding %s"), name);
+ return std::string (buf);
+ }
+}
+
+/***
+****
+***/
+
+TaskUpload :: TaskUpload ( const FileQueue::FileData & file_data,
+ const Quark & server,
+ GMimeMessage * msg,
+ Progress::Listener * listener,
+ const TaskUpload::EncodeMode enc):
+ Task ("UPLOAD", get_description(file_data.filename, true)),
+ _file_data(file_data),
+ _basename(g_path_get_basename(file_data.filename)),
+ _server(server),
+ _msg(msg),
+ _encoder(0),
+ _encoder_has_run (false),
+ _encode_mode(enc)
+{
+ if (listener != 0)
+ add_listener (listener);
+
+ update_work ();
+}
+
+void
+TaskUpload :: update_work (void)
+{
+ if (!_encoder && !_encoder_has_run)
+ {
+ _state.set_need_encoder();
+ } else if (_encoder_has_run && !_needed.empty())
+ {
+ std::cout<<"need "<<_needed.size()<<std::endl;
+ mut.lock();
+ _cur = *_needed.begin();
+ if (!_needed.empty()) _needed.pop_front();
+ mut.unlock();
+ _state.set_need_nntp(_server);
+ set_status_va (_("Uploading %s"), _file_data.basename);
+ } else if (_needed.empty())
+ {
+ _state.set_completed();
+ set_finished(OK);
+ }
+}
+
+/***
+****
+***/
+
+std::string
+TaskUpload :: generate_yenc_headers(const Needed& n)
+{
+ std::stringstream res;
+ const int bufsz = 2048;
+ char buf[bufsz];
+ //modify msg to our needs
+ const char* subject = g_mime_object_get_header ((GMimeObject*)_msg, "Subject");
+ g_snprintf(buf,bufsz, "%s -- \"%s\" (%d/%d) YEnc",
+ subject, _file_data.basename, //_file_data.part_in_queue, _file_data.size(),
+ n.partno, _parts);
+ g_mime_object_set_header((GMimeObject*)_msg,"Subject", buf);
+
+ //append msg to result
+ res << g_mime_object_to_string((GMimeObject *)_msg);
+
+ //append yenc data to result
+ res<<"\r\n";
+
+ std::ifstream in(const_cast<char*>(n.filename.c_str()), std::ifstream::in);
+ std::string line;
+ if (in.good())
+ std::getline(in, line);
+ int filesize = __yenc_extract_tag_val_int_base( line.c_str(), " size=", 0 );
+ g_snprintf(buf,bufsz,"=ybegin line=128 size=%s name=%s\r\n",
+ filesize, _basename);
+ res<<buf;
+ while (in.good())
+ res << (char) in.get();
+ res<<"\r\n.\r\n";
+ return res.str();
+}
+
+void
+TaskUpload :: use_nntp (NNTP * nntp)
+{
+ std::cerr<<"use nntp\n";
+ if (_needed.empty())
+ update_work();
+
+ std::string res(generate_yenc_headers(_cur));
+ nntp->post(StringView(res), this);
+ update_work ();
+}
+
+/***
+****
+***/
+
+void
+TaskUpload :: on_nntp_line (NNTP * nntp,
+ const StringView & line_in)
+{}
+
+void
+TaskUpload :: on_nntp_done (NNTP * nntp,
+ Health health,
+ const StringView & response)
+{
+ std::cerr<<"nntp done\n";
+ check_in (nntp, health);
+ increment_step(1);
+ update_work();
+}
+
+/***
+****
+***/
+
+//todo
+unsigned long
+TaskUpload :: get_bytes_remaining () const
+{
+ unsigned long bytes (0);
+ foreach_const (needed_t, _needed, it) // parts not fetched yet...
+ bytes += it->bytes;
+ return bytes;
+}
+
+
+void
+TaskUpload :: use_encoder (Encoder* encoder)
+{
+ if (_state._work != NEED_ENCODER)
+ check_in (encoder);
+
+ _encoder = encoder;
+ init_steps(100);
+ _state.set_working();
+ _encoder->enqueue (this, _file_data, YENC);
+ debug ("encoder thread was free, enqueued work");
+}
+
+void
+TaskUpload :: stop ()
+{
+ if (_encoder)
+ _encoder->cancel();
+}
+
+// called in the main thread by WorkerPool
+void
+TaskUpload :: on_worker_done (bool cancelled)
+{
+ assert(_encoder);
+ if (!_encoder) return;
+
+ if (!cancelled)
+ {
+ // the encoder is done... catch up on all housekeeping
+ // now that we're back in the main thread.
+
+ foreach_const(Encoder::log_t, _encoder->log_severe, it)
+ Log :: add_err(it->c_str());
+ foreach_const(Encoder::log_t, _encoder->log_errors, it)
+ Log :: add_err(it->c_str());
+ foreach_const(Encoder::log_t, _encoder->log_infos, it)
+ Log :: add_info(it->c_str());
+
+ if (!_encoder->log_errors.empty())
+ set_error (_encoder->log_errors.front());
+
+ if (!_encoder->log_severe.empty())
+ _state.set_health (ERR_LOCAL);
+ else {
+ // get parts number from encoder
+ _parts = _encoder->parts;
+ set_step (100);
+ _encoder_has_run = true;
+ /*enqueue all parts into needed_t list.
+ update_work will then assign a pointer to the begin
+ which will be used for an nntp upload.
+ on nntp_done, the list is decreased by one member
+ */
+ static Needed n;
+ const int bufsz(2048);
+ char buf[bufsz];
+ struct stat sb;
+
+ for (int i=1;i<=_parts;i++)
+ {
+ n.partno = i;
+ g_snprintf(buf,bufsz,"%s/%s.%d",
+ file::get_uulib_path().c_str(),
+ _file_data.basename, i);
+ n.filename = buf;
+ stat(buf, &sb);
+ n.bytes = sb.st_size;
+ _needed.push_back (n);
+ }
+ init_steps (_parts);
+ set_step (0);
+ }
+ }
+
+ Encoder * d (_encoder);
+ _encoder = 0;
+ update_work ();
+ check_in (d);
+}
+
+TaskUpload :: ~TaskUpload ()
+{
+ // ensure our on_worker_done() doesn't get called after we're dead
+ if (_encoder)
+ _encoder->cancel_silently();
+}
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
new file mode 100644
index 0000000..139af7b
--- /dev/null
+++ b/pan/tasks/task-upload.h
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2006 Charles Kerr <charles rebelbase com>
+ *
+ * This file
+ * Copyright (C) 2007 Charles Kerr <charles rebelbase com>
+ * Copyright (C) 2007 Calin Culianu <calin ajvar org>
+ *
+ * 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 of the License.
+ *
+ * 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 _TaskUpload_h_
+#define _TaskUpload_h_
+
+#include <pan/general/worker-pool.h>
+#include <pan/data/article.h>
+#include <pan/data/article-cache.h>
+#include <pan/data/data.h>
+#include <pan/data/file-queue.h>
+#include <pan/data/xref.h>
+#include <pan/tasks/nntp.h>
+#include <pan/tasks/task.h>
+#include <deque>
+
+namespace pan
+{
+ struct Encoder;
+
+ /**
+ * Task for uploading binary data to usenet
+ * @ingroup tasks
+ */
+ class TaskUpload: public Task,
+ private NNTP::Listener,
+ private WorkerPool::Worker::Listener
+ {
+ public: // life cycle
+
+ enum EncodeMode
+ {
+ YENC = 0,
+ BASE64,
+ PLAIN
+ };
+
+ TaskUpload ( const FileQueue::FileData & file_data,
+ const Quark & server,
+ GMimeMessage * msg,
+ Progress::Listener * listener=0,
+ TaskUpload::EncodeMode enc = YENC);
+ virtual ~TaskUpload ();
+
+ public: // Task subclass
+ unsigned long get_bytes_remaining () const;
+ void stop ();
+
+ /** only call this for tasks in the NEED_DECODE state
+ * attempts to acquire the saver thread and start saving
+ * returns false if failed or true if the save process started
+ * (intended to be used with the Queue class). If true is returned,
+ * a side-effect is that the task is now in the DECODING state.
+ */
+ virtual void use_encoder (Encoder*);
+
+ private: // Task subclass
+ virtual void use_nntp (NNTP * nntp);
+
+ private: // NNTP::Listener subclass
+ virtual void on_nntp_line (NNTP*, const StringView&);
+ virtual void on_nntp_done (NNTP*, Health, const StringView&);
+
+ private: // WorkerPool::Listener interface
+ void on_worker_done (bool cancelled);
+
+ protected:
+ const Quark _server;
+
+ private: // implementation
+ friend class Encoder;
+ Encoder * _encoder;
+ bool _encoder_has_run;
+ FileQueue::FileData _file_data;
+ const char* _basename;
+ TaskUpload::EncodeMode _encode_mode;
+ GMimeMessage * _msg;
+ int _parts; // filled in by encoder
+ Mutex mut;
+
+ private:
+ struct Needed {
+ std::string filename;
+ unsigned long bytes;
+ int partno;
+ Needed (): partno(0) {}
+ };
+ typedef std::deque<Needed> needed_t;
+ needed_t _needed;
+ Needed _cur;
+
+ virtual std::string generate_yenc_headers(const Needed& n);
+
+ void update_work (void);
+ };
+
+namespace
+{
+
+ const char*
+ __yenc_extract_tag_val_char (const char * line, const char *tag)
+ {
+ const char * retval = NULL;
+
+ const char * tmp = strstr (line, tag);
+ if (tmp != NULL) {
+ tmp += strlen (tag);
+ if (*tmp != '\0')
+ retval = tmp;
+ }
+
+ return retval;
+ }
+
+ guint
+ __yenc_extract_tag_val_int_base (const char * line,
+ const char * tag,
+ int base)
+ {
+ guint retval = 0;
+
+ const char * tmp = __yenc_extract_tag_val_char (line, tag);
+ if (tmp != NULL) {
+ char * tail = NULL;
+ retval = strtoul (tmp, &tail, base);
+ if (tmp == tail)
+ retval = 0;
+ }
+
+ return retval;
+ }
+}
+
+}
+
+#endif
diff --git a/pan/tasks/task-weak-ordering.h b/pan/tasks/task-weak-ordering.h
index 6f6d2fd..dad898f 100644
--- a/pan/tasks/task-weak-ordering.h
+++ b/pan/tasks/task-weak-ordering.h
@@ -42,7 +42,8 @@ namespace pan
POST ("POST"),
SAVE ("SAVE"),
XOVER ("XOVER"),
- XZVER_TEST ("XZVER_TEST") {}
+ XZVER_TEST ("XZVER_TEST")
+ {}
int get_rank_for_type (const Quark& type) const
{
@@ -55,7 +56,7 @@ namespace pan
else if (type==SAVE)
rank = 2;
else
- assert (0 && "what is this type?");
+ rank = 2;
return rank;
}
diff --git a/pan/usenet-utils/mime-utils.cc b/pan/usenet-utils/mime-utils.cc
index 52de825..c2d7d17 100644
--- a/pan/usenet-utils/mime-utils.cc
+++ b/pan/usenet-utils/mime-utils.cc
@@ -155,7 +155,7 @@ namespace
* @param filename if parse is successful, is set with the
* starting character of the filename.
* @param line_len if parse is successful, is set with the line length
- * @param part is parse is successful & set to the cuurent attachements
+ * @param part if parse is successful this is set to the current attachement's
* part number
* @return 0 on success, -1 on failure
*/
@@ -171,10 +171,10 @@ namespace
// part is optional
int part_num = __yenc_extract_tag_val_int (b, YENC_TAG_PART);
-
+
int a_sz = __yenc_extract_tag_val_int( b, YENC_TAG_SIZE );
pan_return_val_if_fail( a_sz != 0, -1 );
-
+
const char * fname = __yenc_extract_tag_val_char (b, YENC_TAG_NAME);
pan_return_val_if_fail( fname, -1 );
diff --git a/pan/usenet-utils/mime-utils.h b/pan/usenet-utils/mime-utils.h
index fbfa71c..e4e9714 100644
--- a/pan/usenet-utils/mime-utils.h
+++ b/pan/usenet-utils/mime-utils.h
@@ -31,7 +31,7 @@ namespace pan
{
/**
* Utilities to build and parse GMimeMesasges.
- *
+ *
* Most of nastiness this is to handle Usenet's use of chainging together
* multiple articles as parts of a whole. This code tries to build
* a multipart GMimeMessage from multiple posts when necessary, and to
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]