[pan2: 60/268] * upload works * xzver still broken --> upload debugging



commit a5aa39e7a40a862d9dd44a8c9c7c60819b7134b5
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Sun Jun 12 17:05:20 2011 +0200

    * upload works
    * xzver still broken
    --> upload debugging

 pan.cbp                           |  305 +++++++++++++++++++++++++++++
 pan/data-impl/data-impl.h         |    7 +-
 pan/data-impl/server.cc           |   33 +---
 pan/data/data.h                   |    4 -
 pan/data/encode-cache.cc          |    8 +-
 pan/data/encode-cache.h           |    2 +-
 pan/data/encode-cache.o           |  Bin 763224 -> 837816 bytes
 pan/data/server-info.h            |    4 -
 pan/gui/dl-headers-ui.cc          |    2 +-
 pan/gui/pan.cc                    |    5 +-
 pan/gui/post-ui.cc                |  385 +++++++++++++++++++++++--------------
 pan/gui/post-ui.h                 |   38 ++--
 pan/gui/post.ui.h                 |    4 +-
 pan/gui/prefs-ui.cc               |    6 +-
 pan/gui/server-ui.cc              |   40 +----
 pan/tasks/Makefile.am             |    5 +-
 pan/tasks/decoder.cc              |    6 +-
 pan/tasks/encoder.cc              |   13 +-
 pan/tasks/encoder.h               |    2 +-
 pan/tasks/nntp.cc                 |   15 +-
 pan/tasks/nntp.h                  |   28 ++-
 pan/tasks/nzb.cc                  |    8 +-
 pan/tasks/task-upload.cc          |   41 ++---
 pan/tasks/task-upload.h           |   13 +-
 pan/tasks/task-weak-ordering.h    |    7 +-
 pan/tasks/task-xover.cc           |   71 +++++++-
 pan/tasks/task-xover.h            |    8 +
 pan/tasks/task-xzver-test.cc      |  114 -----------
 pan/tasks/task-xzver-test.h       |   61 ------
 pan/tasks/upload-queue.cc         |  188 ++++++++++++++++++
 pan/tasks/upload-queue.h          |  111 +++++++++++
 pan/usenet-utils/Makefile.am      |    6 +-
 pan/usenet-utils/message-check.cc |    6 +-
 uulib/uuencode.c                  |    2 +-
 34 files changed, 1040 insertions(+), 508 deletions(-)
---
diff --git a/pan.cbp b/pan.cbp
new file mode 100644
index 0000000..dda6be6
--- /dev/null
+++ b/pan.cbp
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="pan" />
+		<Option makefile_is_custom="1" />
+		<Option pch_mode="2" />
+		<Option compiler="gcc" />
+		<MakeCommands>
+			<Build command="$make -j8 -f $makefile $target" />
+			<CompileFile command="$make -j8 -f $makefile $file" />
+			<Clean command="$make v-f $makefile clean$target" />
+			<DistClean command="$make -f $makefile distclean$target" />
+			<AskRebuildNeeded command="$make -j8 -q -f $makefile $target" />
+			<SilentBuild command="$make -j8 -s -f $makefile $target" />
+		</MakeCommands>
+		<Build>
+			<Target title="all">
+				<Option output="pan/gui/pan" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Release/" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-O2" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+				<MakeCommands>
+					<Build command="$make -j8 -f $makefile $target" />
+					<CompileFile command="$make -j8 -f $makefile $file" />
+					<Clean command="$make -j8 f $makefile clean$target" />
+					<DistClean command="$make -f $makefile distclean$target" />
+					<AskRebuildNeeded command="$make -j8 -q -f $makefile $target" />
+					<SilentBuild command="$make -j8 -s -f $makefile $target" />
+				</MakeCommands>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="-Wall" />
+		</Compiler>
+		<Unit filename="config.h" />
+		<Unit filename="pan/data-impl/add-server.cc" />
+		<Unit filename="pan/data-impl/article-filter.cc" />
+		<Unit filename="pan/data-impl/article-filter.h" />
+		<Unit filename="pan/data-impl/data-impl.cc" />
+		<Unit filename="pan/data-impl/data-impl.h" />
+		<Unit filename="pan/data-impl/data-io.cc" />
+		<Unit filename="pan/data-impl/data-io.h" />
+		<Unit filename="pan/data-impl/defgroup.h" />
+		<Unit filename="pan/data-impl/groups.cc" />
+		<Unit filename="pan/data-impl/headers-test.cc" />
+		<Unit filename="pan/data-impl/headers.cc" />
+		<Unit filename="pan/data-impl/memchunk.h" />
+		<Unit filename="pan/data-impl/my-tree.cc" />
+		<Unit filename="pan/data-impl/profiles.cc" />
+		<Unit filename="pan/data-impl/profiles.h" />
+		<Unit filename="pan/data-impl/server.cc" />
+		<Unit filename="pan/data-impl/speed-test-load-group.cc" />
+		<Unit filename="pan/data-impl/task-archive.cc" />
+		<Unit filename="pan/data-impl/xover.cc" />
+		<Unit filename="pan/data/article-cache.cc" />
+		<Unit filename="pan/data/article-cache.h" />
+		<Unit filename="pan/data/article-test.cc" />
+		<Unit filename="pan/data/article.cc" />
+		<Unit filename="pan/data/article.h" />
+		<Unit filename="pan/data/data.cc" />
+		<Unit filename="pan/data/data.h" />
+		<Unit filename="pan/data/defgroup.h" />
+		<Unit filename="pan/data/encode-cache.cc" />
+		<Unit filename="pan/data/encode-cache.h" />
+		<Unit filename="pan/data/parts.cc" />
+		<Unit filename="pan/data/parts.h" />
+		<Unit filename="pan/data/server-info.h" />
+		<Unit filename="pan/data/xover-cache.cc" />
+		<Unit filename="pan/data/xover-cache.h" />
+		<Unit filename="pan/data/xref-test.cc" />
+		<Unit filename="pan/data/xref.cc" />
+		<Unit filename="pan/data/xref.h" />
+		<Unit filename="pan/general/debug.cc" />
+		<Unit filename="pan/general/debug.h" />
+		<Unit filename="pan/general/defgroup.h" />
+		<Unit filename="pan/general/e-util.cc" />
+		<Unit filename="pan/general/e-util.h" />
+		<Unit filename="pan/general/file-util.cc" />
+		<Unit filename="pan/general/file-util.h" />
+		<Unit filename="pan/general/line-reader.cc" />
+		<Unit filename="pan/general/line-reader.h" />
+		<Unit filename="pan/general/locking.h" />
+		<Unit filename="pan/general/log.cc" />
+		<Unit filename="pan/general/log.h" />
+		<Unit filename="pan/general/macros.h" />
+		<Unit filename="pan/general/map-vector.h" />
+		<Unit filename="pan/general/messages.h" />
+		<Unit filename="pan/general/progress-test.cc" />
+		<Unit filename="pan/general/progress.cc" />
+		<Unit filename="pan/general/progress.h" />
+		<Unit filename="pan/general/quark-test.cc" />
+		<Unit filename="pan/general/quark.cc" />
+		<Unit filename="pan/general/quark.h" />
+		<Unit filename="pan/general/sorted-vector.h" />
+		<Unit filename="pan/general/string-view-test.cc" />
+		<Unit filename="pan/general/string-view.cc" />
+		<Unit filename="pan/general/string-view.h" />
+		<Unit filename="pan/general/test.h" />
+		<Unit filename="pan/general/text-match-test.cc" />
+		<Unit filename="pan/general/text-match.cc" />
+		<Unit filename="pan/general/text-match.h" />
+		<Unit filename="pan/general/time-elapsed.h" />
+		<Unit filename="pan/general/utf8-utils.cc" />
+		<Unit filename="pan/general/utf8-utils.h" />
+		<Unit filename="pan/general/worker-pool.cc" />
+		<Unit filename="pan/general/worker-pool.h" />
+		<Unit filename="pan/gui/action-manager.h" />
+		<Unit filename="pan/gui/actions.cc" />
+		<Unit filename="pan/gui/actions.h" />
+		<Unit filename="pan/gui/body-pane.cc" />
+		<Unit filename="pan/gui/body-pane.h" />
+		<Unit filename="pan/gui/defgroup.h" />
+		<Unit filename="pan/gui/dl-headers-ui.cc" />
+		<Unit filename="pan/gui/dl-headers-ui.h" />
+		<Unit filename="pan/gui/e-action-combo-box.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="pan/gui/e-action-combo-box.h" />
+		<Unit filename="pan/gui/e-charset-combo-box.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="pan/gui/e-charset-combo-box.h" />
+		<Unit filename="pan/gui/e-charset-dialog.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="pan/gui/e-charset-dialog.h" />
+		<Unit filename="pan/gui/e-charset.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="pan/gui/e-charset.h" />
+		<Unit filename="pan/gui/group-pane.cc" />
+		<Unit filename="pan/gui/group-pane.h" />
+		<Unit filename="pan/gui/group-prefs-dialog.cc" />
+		<Unit filename="pan/gui/group-prefs-dialog.h" />
+		<Unit filename="pan/gui/group-prefs.cc" />
+		<Unit filename="pan/gui/group-prefs.h" />
+		<Unit filename="pan/gui/gtk_compat.h" />
+		<Unit filename="pan/gui/gui.cc" />
+		<Unit filename="pan/gui/gui.h" />
+		<Unit filename="pan/gui/header-pane.cc" />
+		<Unit filename="pan/gui/header-pane.h" />
+		<Unit filename="pan/gui/hig.cc" />
+		<Unit filename="pan/gui/hig.h" />
+		<Unit filename="pan/gui/license.h" />
+		<Unit filename="pan/gui/log-ui.cc" />
+		<Unit filename="pan/gui/log-ui.h" />
+		<Unit filename="pan/gui/pad.h" />
+		<Unit filename="pan/gui/pan-file-entry.cc" />
+		<Unit filename="pan/gui/pan-file-entry.h" />
+		<Unit filename="pan/gui/pan-pixbufs.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="pan/gui/pan-tree.cc" />
+		<Unit filename="pan/gui/pan-tree.h" />
+		<Unit filename="pan/gui/pan-ui.h" />
+		<Unit filename="pan/gui/pan.cc" />
+		<Unit filename="pan/gui/pan.ui.h" />
+		<Unit filename="pan/gui/panrc.rc" />
+		<Unit filename="pan/gui/post-ui.cc" />
+		<Unit filename="pan/gui/post-ui.h" />
+		<Unit filename="pan/gui/post.ui.h" />
+		<Unit filename="pan/gui/prefs-file.cc" />
+		<Unit filename="pan/gui/prefs-file.h" />
+		<Unit filename="pan/gui/prefs-ui.cc" />
+		<Unit filename="pan/gui/prefs-ui.h" />
+		<Unit filename="pan/gui/prefs.cc" />
+		<Unit filename="pan/gui/prefs.h" />
+		<Unit filename="pan/gui/profiles-dialog.cc" />
+		<Unit filename="pan/gui/profiles-dialog.h" />
+		<Unit filename="pan/gui/progress-view.cc" />
+		<Unit filename="pan/gui/progress-view.h" />
+		<Unit filename="pan/gui/render-bytes.cc" />
+		<Unit filename="pan/gui/render-bytes.h" />
+		<Unit filename="pan/gui/save-ui.cc" />
+		<Unit filename="pan/gui/save-ui.h" />
+		<Unit filename="pan/gui/score-add-ui.cc" />
+		<Unit filename="pan/gui/score-add-ui.h" />
+		<Unit filename="pan/gui/score-view-ui.cc" />
+		<Unit filename="pan/gui/score-view-ui.h" />
+		<Unit filename="pan/gui/server-ui.cc" />
+		<Unit filename="pan/gui/server-ui.h" />
+		<Unit filename="pan/gui/tango-colors.h" />
+		<Unit filename="pan/gui/task-pane.cc" />
+		<Unit filename="pan/gui/task-pane.h" />
+		<Unit filename="pan/gui/url.cc" />
+		<Unit filename="pan/gui/url.h" />
+		<Unit filename="pan/gui/wait.h" />
+		<Unit filename="pan/gui/xface.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="pan/gui/xface.h" />
+		<Unit filename="pan/icons/pan-pixbufs-internal.h" />
+		<Unit filename="pan/icons/pan-pixbufs.h" />
+		<Unit filename="pan/tasks/adaptable-set-test.cc" />
+		<Unit filename="pan/tasks/adaptable-set.cc" />
+		<Unit filename="pan/tasks/adaptable-set.h" />
+		<Unit filename="pan/tasks/decoder.cc" />
+		<Unit filename="pan/tasks/decoder.h" />
+		<Unit filename="pan/tasks/defgroup.h" />
+		<Unit filename="pan/tasks/encoder.cc" />
+		<Unit filename="pan/tasks/encoder.h" />
+		<Unit filename="pan/tasks/health.h" />
+		<Unit filename="pan/tasks/nntp-pool.cc" />
+		<Unit filename="pan/tasks/nntp-pool.h" />
+		<Unit filename="pan/tasks/nntp.cc" />
+		<Unit filename="pan/tasks/nntp.h" />
+		<Unit filename="pan/tasks/nzb-test.cc" />
+		<Unit filename="pan/tasks/nzb.cc" />
+		<Unit filename="pan/tasks/nzb.h" />
+		<Unit filename="pan/tasks/queue.cc" />
+		<Unit filename="pan/tasks/queue.h" />
+		<Unit filename="pan/tasks/socket-impl-gio.cc" />
+		<Unit filename="pan/tasks/socket-impl-gio.h" />
+		<Unit filename="pan/tasks/socket-impl-scripted.cc" />
+		<Unit filename="pan/tasks/socket-impl-scripted.h" />
+		<Unit filename="pan/tasks/socket.cc" />
+		<Unit filename="pan/tasks/socket.h" />
+		<Unit filename="pan/tasks/task-article.cc" />
+		<Unit filename="pan/tasks/task-article.h" />
+		<Unit filename="pan/tasks/task-groups.cc" />
+		<Unit filename="pan/tasks/task-groups.h" />
+		<Unit filename="pan/tasks/task-post.cc" />
+		<Unit filename="pan/tasks/task-post.h" />
+		<Unit filename="pan/tasks/task-upload.cc" />
+		<Unit filename="pan/tasks/task-upload.h" />
+		<Unit filename="pan/tasks/task-weak-ordering.h" />
+		<Unit filename="pan/tasks/task-xover.cc" />
+		<Unit filename="pan/tasks/task-xover.h" />
+		<Unit filename="pan/tasks/task-xzver-test.cc" />
+		<Unit filename="pan/tasks/task-xzver-test.h" />
+		<Unit filename="pan/tasks/task.cc" />
+		<Unit filename="pan/tasks/task.h" />
+		<Unit filename="pan/tasks/upload-queue.cc" />
+		<Unit filename="pan/tasks/upload-queue.h" />
+		<Unit filename="pan/usenet-utils/MersenneTwister.h" />
+		<Unit filename="pan/usenet-utils/defgroup.h" />
+		<Unit filename="pan/usenet-utils/filter-info.cc" />
+		<Unit filename="pan/usenet-utils/filter-info.h" />
+		<Unit filename="pan/usenet-utils/gnksa-test.cc" />
+		<Unit filename="pan/usenet-utils/gnksa.cc" />
+		<Unit filename="pan/usenet-utils/gnksa.h" />
+		<Unit filename="pan/usenet-utils/message-check-test.cc" />
+		<Unit filename="pan/usenet-utils/message-check.cc" />
+		<Unit filename="pan/usenet-utils/message-check.h" />
+		<Unit filename="pan/usenet-utils/mime-utils.cc" />
+		<Unit filename="pan/usenet-utils/mime-utils.h" />
+		<Unit filename="pan/usenet-utils/numbers-test.cc" />
+		<Unit filename="pan/usenet-utils/numbers.cc" />
+		<Unit filename="pan/usenet-utils/numbers.h" />
+		<Unit filename="pan/usenet-utils/scorefile-test.cc" />
+		<Unit filename="pan/usenet-utils/scorefile.cc" />
+		<Unit filename="pan/usenet-utils/scorefile.h" />
+		<Unit filename="pan/usenet-utils/text-massager-test.cc" />
+		<Unit filename="pan/usenet-utils/text-massager.cc" />
+		<Unit filename="pan/usenet-utils/text-massager.h" />
+		<Unit filename="pan/usenet-utils/url-find-test.cc" />
+		<Unit filename="pan/usenet-utils/url-find.cc" />
+		<Unit filename="pan/usenet-utils/url-find.h" />
+		<Unit filename="uulib/crc32.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="uulib/crc32.h" />
+		<Unit filename="uulib/fptools.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="uulib/fptools.h" />
+		<Unit filename="uulib/uucheck.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="uulib/uudeview.h" />
+		<Unit filename="uulib/uuencode.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="uulib/uuint.h" />
+		<Unit filename="uulib/uulib.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="uulib/uunconc.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="uulib/uuscan.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="uulib/uustring.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="uulib/uustring.h" />
+		<Unit filename="uulib/uuutil.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Extensions>
+			<envvars />
+			<code_completion />
+			<lib_finder disable_auto="1" />
+			<debugger />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>
diff --git a/pan/data-impl/data-impl.h b/pan/data-impl/data-impl.h
index 669fafe..b5b1ad6 100644
--- a/pan/data-impl/data-impl.h
+++ b/pan/data-impl/data-impl.h
@@ -105,11 +105,10 @@ namespace pan
          int article_expiration_age;
          int max_connections;
          int rank;
-         int xzver;
          typedef sorted_vector<Quark,true,AlphabeticalQuarkOrdering> groups_t;
          groups_t groups;
 
-         Server(): port(119), article_expiration_age(31), max_connections(2), rank(1), xzver(0) {}
+         Server(): port(119), article_expiration_age(31), max_connections(2), rank(1) {}
       };
 
       typedef Loki::AssocVector<Quark,Server> servers_t;
@@ -144,8 +143,6 @@ namespace pan
 
       virtual void save_server_info (const Quark& server);
 
-      virtual void set_server_xzver_support (const Quark& server, const int val);
-
     public: // accessors
 
       virtual quarks_t get_servers () const {
@@ -171,8 +168,6 @@ namespace pan
 
       virtual int get_server_article_expiration_age  (const Quark  & server) const;
 
-      virtual int get_server_xzver_support (const Quark& server) const;
-
     /**
     *** GROUPS
     **/
diff --git a/pan/data-impl/server.cc b/pan/data-impl/server.cc
index a5da24f..2dd509c 100644
--- a/pan/data-impl/server.cc
+++ b/pan/data-impl/server.cc
@@ -107,17 +107,6 @@ DataImpl :: set_server_article_expiration_age  (const Quark  & server,
 
   s->article_expiration_age = std::max (0, days);
 
-//  save_server_properties (*_data_io);
-}
-
-void
-DataImpl :: set_server_xzver_support (const Quark& server, const int val)
-{
-  if (val<0 || val>1) return;
-  Server * s (find_server (server));
-  assert (s != 0);
-
-  s->xzver = val;
 
 }
 
@@ -132,7 +121,7 @@ DataImpl :: set_server_auth (const Quark       & server,
   s->username = username;
   s->password = password;
 
-//  save_server_properties (*_data_io);
+
 }
 
 void
@@ -144,7 +133,7 @@ DataImpl :: set_server_addr (const Quark       & server,
   assert (s != 0);
   s->host = host;
   s->port = port;
-//  save_server_properties (*_data_io);
+
 }
 
 
@@ -155,7 +144,7 @@ DataImpl :: set_server_limits (const Quark   & server,
   Server * s (find_server (server));
   assert (s != 0);
   s->max_connections = max_connections;
-//  save_server_properties (*_data_io);
+
 }
 
 void
@@ -165,7 +154,7 @@ DataImpl :: set_server_rank (const Quark   & server,
   Server * s (find_server (server));
   assert (s != 0);
   s->rank = rank;
-//  save_server_properties (*_data_io);
+
 }
 
 void
@@ -247,16 +236,6 @@ DataImpl :: get_server_article_expiration_age  (const Quark  & server) const
   return retval;
 }
 
-int
-DataImpl :: get_server_xzver_support  (const Quark  & server) const
-{
-  int ret(0);
-  const Server * s (find_server (server));
-  if (s != 0)
-    ret = s->xzver;
-  return ret;
-}
-
 /***
 ****
 ***/
@@ -352,7 +331,6 @@ DataImpl :: load_server_properties (const DataIO& source)
     s.article_expiration_age = to_int(kv["expire-articles-n-days-old"], 31);
     s.rank = to_int(kv["rank"], 1);
     s.newsrc_filename = kv["newsrc"];
-    s.xzver = to_int(kv["xzver"],1);
     if (s.newsrc_filename.empty()) { // set a default filename
       std::ostringstream o;
       o << file::get_pan_home() << G_DIR_SEPARATOR << "newsrc-" << it->first;
@@ -404,8 +382,7 @@ DataImpl :: save_server_properties (DataIO& data_io) const
          << indent(depth) << "<expire-articles-n-days-old>" << s->article_expiration_age << "</expire-articles-n-days-old>\n"
          << indent(depth) << "<connection-limit>" << s->max_connections << "</connection-limit>\n"
          << indent(depth) << "<newsrc>" << s->newsrc_filename << "</newsrc>\n"
-         << indent(depth) << "<rank>" << s->rank << "</rank>\n"
-         << indent(depth) << "<xzver>" << s->xzver << "</xzver>\n";
+         << indent(depth) << "<rank>" << s->rank << "</rank>\n";
 
     *out << indent(--depth) << "</server>\n";
   }
diff --git a/pan/data/data.h b/pan/data/data.h
index cea4604..28c16e1 100644
--- a/pan/data/data.h
+++ b/pan/data/data.h
@@ -192,8 +192,6 @@ namespace pan
       virtual void set_server_limits (const Quark     & server,
                                       int               max_connections) = 0;
 
-      virtual void set_server_xzver_support (const Quark& server, int setme) = 0;
-
       virtual bool get_server_addr (const Quark   & server,
                                     std::string   & setme_address,
                                     int           & setme_port) const = 0;
@@ -204,8 +202,6 @@ namespace pan
 
       virtual int get_server_limits (const Quark & server) const = 0;
 
-      virtual int get_server_xzver_support (const Quark& server) const = 0;
-
     /*****************************************************************
     ***
     ***  OBSERVERS
diff --git a/pan/data/encode-cache.cc b/pan/data/encode-cache.cc
index 9083f2c..77c1682 100644
--- a/pan/data/encode-cache.cc
+++ b/pan/data/encode-cache.cc
@@ -140,10 +140,10 @@ EncodeCache :: add (const Quark& message_id)
 ****
 ***/
 
-void EncodeCache :: finalize (const Quark& message_id)
+void EncodeCache :: finalize (std::string& message_id)
 {
   struct stat sb;
-  stat (message_id, &sb);
+  stat (message_id.c_str(), &sb);
   _mid_to_info[message_id]._size = sb.st_size;
   fire_added (message_id);
   _current_bytes += sb.st_size;
@@ -226,9 +226,9 @@ EncodeCache :: resize (guint64 max_bytes)
     }
   }
 
-  std::cerr<<"cache expired " << removed.size() << " articles, "
+  debug("cache expired " << removed.size() << " articles, "
         "has " << _mid_to_info.size() << " active "
-        "and " << _locks.size() << " locked.\n";
+        "and " << _locks.size() << " locked.\n");
 
   if (!removed.empty())
     fire_removed (removed);
diff --git a/pan/data/encode-cache.h b/pan/data/encode-cache.h
index 98e4681..cd0a225 100644
--- a/pan/data/encode-cache.h
+++ b/pan/data/encode-cache.h
@@ -62,7 +62,7 @@ namespace pan
 
       bool contains (const Quark& message_id) const;
       void add (const Quark& message_id);
-      void finalize (const Quark& message_id);
+      void finalize (std::string& message_id);
       void get_data(std::string& data, const Quark& where);
       void reserve (const mid_sequence_t& mids);
       void release (const mid_sequence_t& mids);
diff --git a/pan/data/encode-cache.o b/pan/data/encode-cache.o
index 4290839..49ec3e6 100644
Binary files a/pan/data/encode-cache.o and b/pan/data/encode-cache.o differ
diff --git a/pan/data/server-info.h b/pan/data/server-info.h
index 694f781..0bae055 100644
--- a/pan/data/server-info.h
+++ b/pan/data/server-info.h
@@ -61,8 +61,6 @@ namespace pan
       virtual void set_server_rank (const Quark& server,
                                     int          rank) = 0;
 
-      virtual void set_server_xzver_support (const Quark& server, const int val) = 0;
-
       virtual void save_server_info (const Quark& server) = 0;
 
     public: // accessors
@@ -82,8 +80,6 @@ namespace pan
       virtual int get_server_limits (const Quark & server) const = 0;
 
       virtual int get_server_article_expiration_age  (const Quark  & server) const = 0;
-
-      virtual int get_server_xzver_support (const Quark& server) const = 0;
   };
 }
 
diff --git a/pan/gui/dl-headers-ui.cc b/pan/gui/dl-headers-ui.cc
index 689c0e5..8934c23 100644
--- a/pan/gui/dl-headers-ui.cc
+++ b/pan/gui/dl-headers-ui.cc
@@ -66,7 +66,7 @@ namespace
     if (response == GTK_RESPONSE_ACCEPT)
     {
       const bool mark_read (state->prefs.get_flag ("mark-group-read-before-xover", false));
-        // xzver
+
       foreach_const (quarks_t, state->groups, it) {
         Task * task;
         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(state->all_headers_rb)))
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index da07709..fe48e47 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -36,7 +36,6 @@ extern "C" {
 #include <pan/tasks/socket-impl-gio.h>
 #include <pan/tasks/task-groups.h>
 #include <pan/tasks/task-xover.h>
-#include <pan/tasks/task-xzver-test.h>
 #include <pan/tasks/nzb.h>
 #include <pan/data-impl/data-impl.h>
 #include <pan/icons/pan-pixbufs.h>
@@ -114,10 +113,8 @@ namespace
     DataAndQueue * foo (static_cast<DataAndQueue*>(user_data));
     const quarks_t new_servers (foo->data->get_servers());
     foreach_const (quarks_t, new_servers, it)
-      if (foo->data->get_server_limits(*it)) {
-        foo->queue->add_task (new TaskXZVerTest(*foo->data, *it));
+      if (foo->data->get_server_limits(*it))
         foo->queue->add_task (new TaskGroups (*foo->data, *it));
-      }
     g_free (foo);
   }
 
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 8dbe774..bc27c49 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -82,6 +82,83 @@ inline int close(int fd) {return _close(fd);}
   }
 }
 
+namespace
+{
+  int
+  find_task_index (GtkListStore * list, TaskUpload * task)
+  {
+    GtkTreeIter iter;
+    int index (0);
+
+    if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(list), &iter)) do
+    {
+      TaskUpload * test;
+      gtk_tree_model_get (GTK_TREE_MODEL(list), &iter, 2, &test, -1);
+      if (test == task)
+        return index;
+      ++index;
+    }
+    while (gtk_tree_model_iter_next (GTK_TREE_MODEL(list), &iter));
+
+    // not found
+    return -1;
+  }
+}
+
+void
+PostUI :: on_queue_tasks_added (UploadQueue& queue, int index, int count)
+{
+
+  GtkListStore *store = GTK_LIST_STORE(
+                      gtk_tree_view_get_model(GTK_TREE_VIEW(_filequeue_store)));
+
+  for (int i=0; i<count; ++i)
+  {
+    const int pos (index + i);
+    TaskUpload * task (_upload_queue[pos]);
+    if (!task) continue;
+    GtkTreeIter iter;
+    gtk_list_store_insert (store, &iter, pos);
+    gtk_list_store_set (store, &iter,
+                      0, pos+1,
+                      1, task->subject().c_str(),
+                      2, task,
+                      3, task->get_byte_count()/1024,
+                      -1);
+  }
+}
+
+void
+PostUI :: on_queue_task_removed (UploadQueue&, TaskUpload& task, int index)
+{
+  GtkListStore *store = GTK_LIST_STORE(
+                      gtk_tree_view_get_model(GTK_TREE_VIEW(_filequeue_store)));
+
+  const int list_index (find_task_index (store, &task));
+  assert (list_index == index);
+  GtkTreeIter iter;
+  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(store), &iter, NULL, index);
+  gtk_list_store_remove (store, &iter);
+}
+
+void
+PostUI :: on_queue_task_moved (UploadQueue&, TaskUpload&, int new_index, int old_index)
+{
+  GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(_filequeue_store));
+  GtkListStore* store = GTK_LIST_STORE(model);
+  const int count (gtk_tree_model_iter_n_children (model, NULL));
+  std::vector<int> v (count);
+  for (int i=0; i<count; ++i) v[i] = i;
+  if (new_index < old_index) {
+    v.erase (v.begin()+old_index);
+    v.insert (v.begin()+new_index, old_index);
+  } else {
+    v.erase (v.begin()+old_index);
+    v.insert (v.begin()+new_index, old_index);
+  }
+  gtk_list_store_reorder (store, &v.front());
+}
+
 void
 PostUI :: set_spellcheck_enabled (bool enabled)
 {
@@ -194,6 +271,7 @@ namespace
   void do_edit     (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->spawn_editor (); }
   void do_profiles (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->manage_profiles (); }
   void do_send     (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->send_now (); }
+  void do_send_and_save (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->send_and_save_now (); }
   void do_save     (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->save_draft (); }
   void do_open     (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->open_draft (); }
   void do_charset  (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->prompt_for_charset (); }
@@ -211,6 +289,7 @@ namespace
     { "editors-menu", 0, N_("Set Editor"), 0, 0, 0 },
     { "post-toolbar", 0, "post", 0, 0, 0 },
     { "post-article", GTK_STOCK_EXECUTE, N_("_Send Article"), "<control>Return", N_("Send Article Now"), G_CALLBACK(do_send) },
+    { "post-and-save-articles", GTK_STOCK_FLOPPY, N_("_Send and Save Articles to NZB"), 0, N_("Send and Save Articles to NZB"), G_CALLBACK(do_send_and_save) },
     { "set-charset", 0, N_("Set Character _Encoding..."), 0, 0, G_CALLBACK(do_charset) },
     { "save-draft", GTK_STOCK_SAVE, N_("Sa_ve Draft"), "<control>s", N_("Save as a Draft for Future Posting"), G_CALLBACK(do_save) },
     { "open-draft", GTK_STOCK_OPEN, N_("_Open Draft..."), "<control>o", N_("Open an Article Draft"), G_CALLBACK(do_open) },
@@ -494,7 +573,7 @@ PostUI :: close_window (bool flag)
 }
 
 bool
-PostUI :: check_message (const Quark& server, GMimeMessage * msg)
+PostUI :: check_message (const Quark& server, GMimeMessage * msg, bool binpost)
 {
 
   MessageCheck :: unique_strings_t errors;
@@ -502,7 +581,9 @@ PostUI :: check_message (const Quark& server, GMimeMessage * msg)
 
   quarks_t groups_this_server_has;
   _gs.server_get_groups (server, groups_this_server_has);
-  MessageCheck :: message_check (msg, _hidden_headers["X-Draft-Attribution"], groups_this_server_has, errors, goodness, !_file_queue_empty);
+  /* skip some checks if the file queue is not empty or if the binpost flag is set, i.e. we want to upload binary data */
+  MessageCheck :: message_check (msg, _hidden_headers["X-Draft-Attribution"],
+                                 groups_this_server_has, errors, goodness, !_file_queue_empty || binpost);
 
   if (goodness.is_ok())
     return true;
@@ -604,12 +685,19 @@ PostUI :: add_files ()
 {
   if (!check_charset())
     return;
-  prompt_user_for_queueable_files (_file_queue_tasks, GTK_WINDOW (gtk_widget_get_toplevel(_root)), _prefs);
+  prompt_user_for_queueable_files (GTK_WINDOW (gtk_widget_get_toplevel(_root)), _prefs);
 }
 
 void
 PostUI :: send_now ()
 {
+  /* check for "always save" flag */
+  if (_prefs.get_flag("upload-queue-save-enabled", false) && !_file_queue_empty)
+  {
+    send_and_save_now();
+    return;
+  }
+
   if (!check_charset())
     return;
   GMimeMessage * message (new_message_from_ui (POSTING));
@@ -617,6 +705,78 @@ PostUI :: send_now ()
     g_object_unref (G_OBJECT(message));
 }
 
+namespace
+{
+  std::string
+  get_domain(const StringView& mid)
+  {
+    const char * pch = mid.strchr ('@');
+    StringView domain;
+    if (pch) domain = mid.substr (pch+1, NULL);
+    if (pch) pch = domain.strchr ('>');
+    if (pch) domain = domain.substr (NULL, pch);
+    domain.trim ();
+
+    return domain.to_string();
+  }
+}
+
+void
+PostUI :: send_and_save_now ()
+{
+
+  PostUI::tasks_t tasks;
+  _upload_queue.get_all_tasks(tasks);
+
+  if (!check_charset())
+    return;
+
+  if (_file_queue_empty || !_prefs.get_flag(MESSAGE_ID_PREFS_KEY,false))
+  {
+    GtkWidget * d = gtk_message_dialog_new (GTK_WINDOW(_root),
+                                            GTK_DIALOG_DESTROY_WITH_PARENT,
+                                            GTK_MESSAGE_ERROR, GTK_BUTTONS_NONE, NULL);
+    if (_file_queue_empty)
+    {
+      HIG :: message_dialog_set_text (GTK_MESSAGE_DIALOG(d),
+      _("The file queue is empty, so no files can be saved."),"");
+      gtk_dialog_add_button (GTK_DIALOG(d), _("Go Back"), GTK_RESPONSE_CANCEL);
+    }
+    else
+    {
+      HIG :: message_dialog_set_text (GTK_MESSAGE_DIALOG(d),
+      _("You wanted to save the queue, but the option for custom Message-IDs is disabled. \nCan`t continue because I need this data for the NZB file. \nEnable this option ?"),"");
+      gtk_dialog_add_button (GTK_DIALOG(d), _("Go Back"), GTK_RESPONSE_CANCEL);
+      gtk_dialog_add_button (GTK_DIALOG(d), _("Enable"), GTK_RESPONSE_APPLY);
+    }
+    const int response = gtk_dialog_run (GTK_DIALOG(d));
+    gtk_widget_destroy (d);
+    if (response == GTK_RESPONSE_APPLY)
+      _prefs.set_flag(MESSAGE_ID_PREFS_KEY, true);
+    else
+      return;
+
+    const Profile profile (get_current_profile ());
+    const std::string message_id = !profile.fqdn.empty()
+    ? GNKSA::generate_message_id (profile.fqdn)
+    : GNKSA::generate_message_id_from_email_address (profile.address);
+
+    std::string domain(get_domain(StringView(message_id)));
+    foreach (tasks_t, tasks, it)
+      (*it)->set_domain(domain);
+  }
+
+  _save_file.clear();
+  _save_file = prompt_user_for_upload_nzb_dir (GTK_WINDOW (gtk_widget_get_toplevel(_root)), _prefs);
+  // update all tasks in queue with save file
+  foreach (tasks_t, tasks, it)
+    (*it)->_save_file = _save_file;
+
+  GMimeMessage * message (new_message_from_ui (POSTING));
+  if (!maybe_post_message (message))
+    g_object_unref (G_OBJECT(message));
+}
+
 void
 PostUI :: done_sending_message (GMimeMessage * message, bool ok)
 {
@@ -818,7 +978,9 @@ PostUI :: maybe_post_message (GMimeMessage * message)
     _post_task->add_listener (this);
     _queue.add_task (_post_task, Queue::TOP);
   } else {
-     foreach_const (tasks_v, _file_queue_tasks, it)
+    PostUI::tasks_t tasks;
+    _upload_queue.get_all_tasks(tasks);
+    foreach (PostUI::tasks_t, tasks, it)
       _queue.add_task (*it, Queue::BOTTOM);
      close_window(true); // dont wait for the upload queue
   }
@@ -1636,14 +1798,6 @@ namespace
     static_cast<PostUI*>(user_data)->apply_profile ();
   }
 
-  void on_lines_spin_changed_cb (GtkComboBox* box, gpointer user_data)
-  {
-    const int res (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(box)));
-
-    static_cast<PostUI*>(user_data)->upload_ptr()->set_lpf(res);
-  }
-
-
   typedef std::map <std::string, std::string> str2str_t;
 
   struct SetMessageForeachHeaderData
@@ -1961,21 +2115,16 @@ namespace
 {
   void message_id_toggled_cb (GtkToggleButton * tb, gpointer prefs_gpointer)
   {
-    static_cast<Prefs*>(prefs_gpointer)->set_flag (MESSAGE_ID_PREFS_KEY, gtk_toggle_button_get_active(tb));
+    // disable toggle if the user chose to always use a custom message id
+    Prefs* prefs = static_cast<Prefs*>(prefs_gpointer);
+    prefs->set_flag (MESSAGE_ID_PREFS_KEY, (gtk_toggle_button_get_active(tb) ||
+                                            prefs->get_flag("upload-enable-custom-mid",false)));
   }
   void user_agent_toggled_cb (GtkToggleButton * tb, gpointer prefs_gpointer)
   {
     static_cast<Prefs*>(prefs_gpointer)->set_flag (USER_AGENT_PREFS_KEY, gtk_toggle_button_get_active(tb));
   }
 
-
-}
-
-void
-PostUI :: queue_save_toggled_cb (GtkToggleButton * tb, gpointer gp)
-{
-  PostUI* self = static_cast<PostUI*>(gp);
-  self->check_file_save(gtk_toggle_button_get_active(tb));
 }
 
 namespace
@@ -2002,11 +2151,27 @@ namespace
   {
 
     TaskUpload* fd(0);
-    gtk_tree_model_get (model, iter, 1, &fd, -1);
+    gtk_tree_model_get (model, iter, 2, &fd, -1);
     if (fd)
       g_object_set (renderer, "text", fd->basename().c_str(), NULL);
   }
 
+  void
+  render_row_number (GtkTreeViewColumn * ,
+                   GtkCellRenderer   * renderer,
+                   GtkTreeModel      * model,
+                   GtkTreeIter       * iter,
+                   gpointer)
+  {
+
+    GtkTreePath * path = gtk_tree_model_get_path ( model , iter ) ;
+    int cnt = gtk_tree_path_get_indices ( path )[0]+1 ;
+    std::string tmp;
+    char buf[256];
+    g_snprintf(buf,sizeof(buf),"%d",cnt);
+    g_object_set (renderer, "text", buf, NULL);
+  }
+
 }
 
 GtkWidget*
@@ -2034,17 +2199,19 @@ PostUI :: create_filequeue_tab ()
   gtk_box_pack_start (GTK_BOX(vbox), gtk_hseparator_new(), false, false, 0);
 
   //add filestore
-  list_store = gtk_list_store_new (3, G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_UINT);
+  list_store = gtk_list_store_new (4, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_UINT);
   w = _filequeue_store = gtk_tree_view_new_with_model (GTK_TREE_MODEL(list_store));
 
   // add columns
   renderer = gtk_cell_renderer_text_new ();
   GtkTreeView * t = GTK_TREE_VIEW(w);
-  gtk_tree_view_insert_column_with_attributes (t, 0,(_("No.")),renderer,"text", 0,NULL);
+  gtk_tree_view_insert_column_with_data_func(t, 0, (_("No.")), renderer, render_row_number, 0, 0);
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (t, 1,(_("Subject")),renderer,"text", 1,NULL);
   renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_insert_column_with_data_func(t, 1, (_("Filename")), renderer, render_filename, 0, 0);
+  gtk_tree_view_insert_column_with_data_func(t, 2, (_("Filename")), renderer, render_filename, 0, 0);
   renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_insert_column_with_attributes (t, 2, (_("Size (kB)")),renderer,"text", 2,NULL);
+  gtk_tree_view_insert_column_with_attributes (t, 3, (_("Size (kB)")),renderer,"text", 3,NULL);
 
   // connect signals for popup menu
   g_signal_connect (w, "popup-menu", G_CALLBACK(on_popup_menu), this);
@@ -2093,7 +2260,7 @@ PostUI:: on_parts_box_clicked_cb (GtkCellRendererToggle *cell, gchar *path_str,
     data->upload_ptr()->_needed.insert(std::pair<int, TaskUpload::Needed>(part,tmp));
 
   }
-  gtk_list_store_set(GTK_LIST_STORE( model ), &iter, 1, false, -1);
+  gtk_list_store_set(GTK_LIST_STORE( model ), &iter, 1, enabled, -1);
   gtk_tree_path_free (path);
   data->update_parts_tab();
 }
@@ -2113,11 +2280,11 @@ PostUI :: create_parts_tab ()
   GtkWidget *t = gtk_table_new (8, 2, false);
   gtk_table_set_col_spacings (GTK_TABLE(t), PAD);
 
-  ++row;  //1
+  ++row;
   l = gtk_label_new (NULL);
   gtk_table_attach (GTK_TABLE(t), l, 0, 2, row, row+1, fe, fill, 0, 0);
 
-  ++row;  //2
+  ++row;
   g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Filename"));
   l = gtk_label_new (buf);
   gtk_label_set_use_markup (GTK_LABEL(l), true);
@@ -2129,7 +2296,7 @@ PostUI :: create_parts_tab ()
   gtk_widget_set_tooltip_text (l, _("The current filename"));
   gtk_table_attach (GTK_TABLE(t), l, 1, 2, row, row+1, fe, fill, 0, 0);
 
-  ++row;  //3
+  ++row;
   g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Subject Line"));
   l = gtk_label_new (buf);
   gtk_label_set_use_markup (GTK_LABEL(l), true);
@@ -2141,38 +2308,10 @@ PostUI :: create_parts_tab ()
   gtk_widget_set_tooltip_text (l, _("The current Subject Line"));
   gtk_table_attach (GTK_TABLE(t), l, 1, 2, row, row+1, fe, fill, 0, 0);
 
-  ++row;  //4
-  g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Lines / File"));
-  l = gtk_label_new (buf);
-  gtk_label_set_use_markup (GTK_LABEL(l), true);
-  gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
-  gtk_table_attach (GTK_TABLE(t), l, 0, 1, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
-  GtkAdjustment * a = (GtkAdjustment*)gtk_adjustment_new (5000, 1500, INT_MAX, 1.0, 1.0, 0.0);
-  w = _lines_spin = gtk_spin_button_new (a, 1.0, 0u);
-  gtk_misc_set_alignment (GTK_MISC(w), 0.5f, 0.5f);
-  gtk_widget_set_tooltip_text (w, _("The current Number of Lines per File"));
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(w), _upload_ptr->_lines_per_file);
-  gtk_table_attach (GTK_TABLE(t), w, 1, 2, row, row+1, fe, fill, 0, 0);
-  g_signal_connect (w, "changed", G_CALLBACK(on_lines_spin_changed_cb), this);
-
-  ++row;   // 5
-  g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Parts"));
-  l = gtk_label_new (buf);
-  gtk_label_set_use_markup (GTK_LABEL(l), true);
-  gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
-  gtk_table_attach (GTK_TABLE(t), l, 0, 1, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
-  g_snprintf (buf, sizeof(buf), "%d", _total_parts);
-  l = gtk_label_new_with_mnemonic (buf);
-  gtk_misc_set_alignment (GTK_MISC(l), 0.5f, 0.5f);
-  gtk_widget_set_tooltip_text (l, _("The current Number of Parts of the queued File"));
-  gtk_table_attach (GTK_TABLE(t), l, 1, 2, row, row+1, fe, fill, 0, 0);
-
-  //6
   ++row;
   l = gtk_label_new (NULL);
   gtk_table_attach (GTK_TABLE(t), l, 0, 2, row, row+1, fe, fill, 0, 0);
 
-  // 7
   //treeview for parts list
   ++row;
   w = _parts_store = gtk_tree_view_new_with_model (GTK_TREE_MODEL(gtk_list_store_new (3,  G_TYPE_UINT, G_TYPE_BOOLEAN, G_TYPE_STRING)));
@@ -2199,15 +2338,8 @@ PostUI :: create_parts_tab ()
   w = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(w), GTK_SHADOW_IN);
-  gtk_container_add (GTK_CONTAINER(w), t);
-
-  return w;
-}
-
-GtkWidget*
-PostUI :: create_log_tab ()
-{
-  GtkWidget *w;
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(w), t);
+//  gtk_container_add (GTK_CONTAINER(w), t);
 
   return w;
 }
@@ -2287,7 +2419,7 @@ gtk_widget_set_tooltip_text (w, _("The email account where mail replies to your
 
   ++row;
   w = _message_id_check = gtk_check_button_new_with_mnemonic (_("Add \"Message-_Id header"));
-  b = _prefs.get_flag (MESSAGE_ID_PREFS_KEY, false);
+  b = _prefs.get_flag (MESSAGE_ID_PREFS_KEY, false) || _prefs.get_flag("upload-enable-custom-mid",false);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(w), b);
   g_signal_connect (w, "toggled", G_CALLBACK(message_id_toggled_cb), &_prefs);
   gtk_table_attach (GTK_TABLE(t), w, 0, 2, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
@@ -2303,14 +2435,14 @@ void
 PostUI :: get_selected_files_foreach (GtkTreeModel *model, GtkTreePath *, GtkTreeIter *iter, gpointer list_g)
 {
   TaskUpload* file(0);
-  gtk_tree_model_get (model, iter, 1, &file, -1);
-  static_cast<tasks_v*>(list_g)->push_back (file);
+  gtk_tree_model_get (model, iter, 2, &file, -1);
+  static_cast<PostUI::tasks_t*>(list_g)->push_back (file);
 }
 
-tasks_v
+PostUI::tasks_t
 PostUI :: get_selected_files () const
 {
-  tasks_v tasks;
+  PostUI::tasks_t tasks;
   GtkTreeView * view (GTK_TREE_VIEW (_filequeue_store));
   GtkTreeSelection * sel (gtk_tree_view_get_selection (view));
   gtk_tree_selection_selected_foreach (sel, get_selected_files_foreach, &tasks);
@@ -2320,49 +2452,37 @@ PostUI :: get_selected_files () const
 void
 PostUI :: remove_files (void)
 {
-  tasks_v tasks = get_selected_files();
-
-  tasks_v::iterator nit;
-  for (nit = tasks.begin(); nit != tasks.end(); ++nit)
-  {
-    TaskUpload * ptr(*nit);
-    _file_queue_tasks.remove(*nit);
-    delete (ptr);
-  }
-  update_filequeue_tab();
+  _upload_queue.remove_tasks (get_selected_files());
 }
 
-
-///TODO!!
 void
 PostUI :: move_up (void)
 {
-
+  _upload_queue.move_up (get_selected_files());
 }
 
 void
 PostUI :: move_down (void)
 {
-
+  _upload_queue.move_down (get_selected_files());
 }
 
 void
 PostUI :: move_top (void)
 {
-
+  _upload_queue.move_top (get_selected_files());
 }
 
 void
 PostUI :: move_bottom (void)
 {
-
+  _upload_queue.move_bottom (get_selected_files());
 }
 
 void
 PostUI :: clear_list (void)
 {
-  _file_queue_tasks.clear();
-  update_filequeue_tab();
+  _upload_queue.clear();
 }
 
 void PostUI :: up_clicked_cb (GtkButton*, PostUI* pane)
@@ -2386,39 +2506,13 @@ void PostUI :: delete_clicked_cb (GtkButton*, PostUI* pane)
   pane->remove_files ();
 }
 
-
-void
-PostUI :: update_filequeue_tab()
-{
-  GtkWidget    * w    = _filequeue_store ;
-  GtkListStore *store = GTK_LIST_STORE(
-                        gtk_tree_view_get_model(GTK_TREE_VIEW(w)));
-  GtkTreeIter   iter;
-
-  gtk_list_store_clear(store);
-
-  tasks_v::iterator it = _file_queue_tasks.begin();
-
-  int i(1);
-  for (; it != _file_queue_tasks.end(); ++it, ++i)
-  {
-    gtk_list_store_append (store, &iter);
-    gtk_list_store_set (store, &iter,
-                      0, i,
-                      1, ((TaskUpload*)*it),
-                      2, ((TaskUpload*)*it)->get_byte_count()/1024,
-                      -1);
-  }
-  _file_queue_empty = (_file_queue_tasks.empty());
-}
-
-
 PostUI :: ~PostUI ()
 {
   if (_group_entry_changed_idle_tag)
     g_source_remove (_group_entry_changed_idle_tag);
-
   g_object_unref (G_OBJECT(_message));
+
+  _upload_queue.remove_listener (this);
 }
 
 
@@ -2427,8 +2521,8 @@ void
 PostUI :: select_parts ()
 {
 
-  tasks_v set(get_selected_files());
-  _upload_ptr = *set.begin();
+  PostUI::tasks_t set(get_selected_files());
+  _upload_ptr = set[0];
 
   if (!_upload_ptr) return;
 
@@ -2444,14 +2538,13 @@ PostUI :: select_parts ()
   int x,y;
   x = _prefs.get_int("post-ui-width", -1);
   y = _prefs.get_int("post-ui-height", 450);
-  gtk_window_set_default_size (GTK_WINDOW(_root), x, y);
+  gtk_window_set_default_size (GTK_WINDOW(w), x, y);
   // populate the window
   GtkWidget * vbox = gtk_vbox_new (false, PAD_SMALL);
   gtk_container_add (GTK_CONTAINER(w), vbox);
 
   GtkWidget * notebook = gtk_notebook_new ();
   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), create_parts_tab(), gtk_label_new_with_mnemonic(_("_Parts")));
-//  gtk_notebook_append_page (GTK_NOTEBOOK(notebook), create_log_tab(),   gtk_label_new_with_mnemonic(_("_Log")));
   pan_box_pack_start_defaults (GTK_BOX(vbox), notebook);
 
   gtk_widget_show_all (w);
@@ -2511,9 +2604,11 @@ PostUI :: PostUI (GtkWindow    * parent,
   _group_entry_changed_idle_tag (0),
   _file_queue_empty(true),
   _upload_ptr(0),
-  _total_parts(0),
-  _check_file_save(false)
+  _total_parts(0)
 {
+
+  _upload_queue.add_listener (this);
+
   g_assert (profiles.has_profiles());
   g_return_if_fail (message != 0);
 
@@ -2591,19 +2686,21 @@ PostUI :: create_window (GtkWindow    * parent,
 }
 
 void
-PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, const Prefs& prefs)
+PostUI :: prompt_user_for_queueable_files (GtkWindow * parent, const Prefs& prefs)
 {
   char buf[4096];
   struct stat sb;
 
   const Profile profile (get_current_profile ());
   GMimeMessage * message (new_message_from_ui (POSTING));
-  if (!check_message(profile.posting_server, message))
+  if (!check_message(profile.posting_server, message, true))
   {
     g_object_unref (G_OBJECT(message));
     return;
   }
 
+  PostUI::tasks_t tasks;
+
   std::string prev_path = prefs.get_string ("default-save-attachments-path", g_get_home_dir ());
 
   GtkWidget * w = gtk_file_chooser_dialog_new (_("Add files to queue"),
@@ -2619,7 +2716,7 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
 	const int response (gtk_dialog_run (GTK_DIALOG(w)));
 	if (response == GTK_RESPONSE_ACCEPT) {
 		GSList * tmp_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER (w));
-		if (_file_queue_empty) _file_queue_empty=!_file_queue_empty;
+
 
 		GSList * cur = g_slist_nth (tmp_list,0);
     GMimeMessage* msg = message;
@@ -2642,12 +2739,14 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
     }
 
     bool comment1 = _prefs.get_flag("upload-queue-append-subject-enabled",false);
-    bool counter  = _prefs.get_flag("upload-queue-append-partcounter-enabled",false);
     TaskUpload::UploadInfo ui;
     ui.comment1 = comment1;
-    ui.counter = counter;
-    const int list_length = (int)g_slist_length(cur);
-    ui.queue_length = list_length;
+    // generate domain name for upload if the flag is set
+    bool custom_mid(_prefs.get_flag(MESSAGE_ID_PREFS_KEY,false));
+    if (custom_mid)
+      ui.domain = !profile.fqdn.empty()
+      ? GNKSA::generate_message_id (profile.fqdn)
+      : GNKSA::generate_message_id_from_email_address (profile.address);
 
     int cnt(1);
     for (; cur; cur = cur->next, ++cnt)
@@ -2662,8 +2761,6 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
       TaskUpload::needed_t import;
       TaskUpload::Needed n;
       foreach_const (quarks_t, groups, git)
-         n.xref.insert (profile.posting_server, *git,0);
-      foreach_const (quarks_t, groups, git)
          a.xref.insert (profile.posting_server, *git,0);
 
       for (int i = 1; i <= total; ++i)
@@ -2678,22 +2775,19 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
       foreach_const (quarks_t, groups, git)
         a.xref.insert (profile.posting_server, *git,0);
 
-      ui.queue_pos = cnt;
-      // generate domain name for upload
-      ui.domain = !profile.fqdn.empty()
-      ? GNKSA::generate_message_id (profile.fqdn)
-      : GNKSA::generate_message_id_from_email_address (profile.address);
-
 		  TaskUpload* tmp = new TaskUpload(std::string((const char*)cur->data),
                         profile.posting_server, _cache,
-                        a, ui, &import, 0, TaskUpload::YENC);
-		  _file_queue_tasks.push_back(tmp);
+                        a, ui, import, 0, TaskUpload::YENC);
+      _upload_queue.add_task(tmp);
 		}
+
+    if (_file_queue_empty) _file_queue_empty= false;
+
     g_slist_free (tmp_list);
   } else
     gtk_widget_destroy (w);
   g_object_unref (G_OBJECT(message));
-	update_filequeue_tab();
+
 }
 
 std::string
@@ -2729,6 +2823,8 @@ PostUI :: prompt_user_for_upload_nzb_dir (GtkWindow * parent, const Prefs& prefs
     char * tmp = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w));
     path = tmp;
     g_free (tmp);
+    //remove old file
+    unlink(path.c_str());
   } else
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(_save_check), false);
 
@@ -2736,8 +2832,3 @@ PostUI :: prompt_user_for_upload_nzb_dir (GtkWindow * parent, const Prefs& prefs
   return path;
 
 }
-
-
-
-
-
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index a69599d..a771832 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -24,31 +24,36 @@
 #include <pan/gui/prefs.h>
 #include <pan/general/progress.h>
 #include <pan/tasks/queue.h>
+#include <pan/tasks/upload-queue.h>
 #include <pan/usenet-utils/text-massager.h>
 #include <pan/data/encode-cache.h>
+//#include <pan/tasks/upload-queue.h>
 #include "group-prefs.h"
 
 namespace pan
 {
   class Profiles;
   class TaskPost;
-  class FileQueue;
+  class UploadQueue;
   class Queue;
 
 
-  typedef std::list<TaskUpload*> tasks_v;
 
   /**
    * Dialog for posting new messages Pan's GTK GUI.
    * @ingroup GUI
    */
-  class PostUI: private Progress::Listener
+  class PostUI: private Progress::Listener,
+                private UploadQueue::Listener
   {
     public:
+
+      typedef std::vector<TaskUpload*> tasks_t;
+
       static PostUI* create_window (GtkWindow*, Data&, Queue&, GroupServer&, Profiles&,
                                     GMimeMessage*, Prefs&, GroupPrefs&, EncodeCache&);
 
-      void prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, const Prefs& prefs);
+      void prompt_user_for_queueable_files (GtkWindow * parent, const Prefs& prefs);
       std::string prompt_user_for_upload_nzb_dir (GtkWindow * parent, const Prefs& prefs);
 
     protected:
@@ -62,8 +67,6 @@ namespace pan
       GtkWidget * part_select() { return _part_select; }
       GtkWidget * parts_store() { return _parts_store; }
 
-      void check_file_save(bool val) { _check_file_save = val; }
-
       void rot13_selection ();
       void wrap_selection ();
       void wrap_body ();
@@ -75,11 +78,12 @@ namespace pan
       void open_draft ();
       void prompt_for_charset ();
       void send_now ();
+      void send_and_save_now ();
       void add_files ();
       void close_window (bool flag=false);
       void set_wrap_mode (bool wrap);
       void set_always_run_editor (bool);
-      void update_filequeue_tab();
+
       void update_parts_tab();
 
       //popup action entries
@@ -124,7 +128,6 @@ namespace pan
 
       GtkWidget * _filequeue_store;
       GtkWidget * _parts_store;
-      GtkWidget * _lines_spin;
 
       GtkWidget * _to_entry;
       GtkWidget * _followupto_entry;
@@ -153,11 +156,15 @@ namespace pan
 
       /* binpost */
       bool _file_queue_empty;
-      tasks_v _file_queue_tasks;
       TaskUpload* _upload_ptr;
       int _total_parts;
       std::string _save_file;
-      bool _check_file_save;
+
+    private:
+      friend class UploadQueue;
+      virtual void on_queue_tasks_added (UploadQueue&, int index, int count);
+      virtual void on_queue_task_removed (UploadQueue&, TaskUpload&, int index);
+      virtual void on_queue_task_moved (UploadQueue&, TaskUpload&, int new_index, int old_index);
 
     private:
       void add_actions (GtkWidget* box);
@@ -166,7 +173,7 @@ namespace pan
       enum Mode { DRAFTING, POSTING };
       GMimeMessage * new_message_from_ui (Mode mode);
       Profile get_current_profile ();
-      bool check_message (const Quark& server, GMimeMessage*);
+      bool check_message (const Quark& server, GMimeMessage*, bool binpost=false);
       bool check_charset ();
 
     private:
@@ -198,25 +205,22 @@ namespace pan
       void spawn_editor_dead(char *);
 
     public:
-      tasks_v  get_selected_files () const;
+      tasks_t  get_selected_files () const;
 
     private:
       static void get_selected_files_foreach (GtkTreeModel*,
                       GtkTreePath*, GtkTreeIter*, gpointer);
 
-      int get_top() ;
-      int get_bottom() ;
-
       static void up_clicked_cb      (GtkButton*, PostUI*);
       static void down_clicked_cb    (GtkButton*, PostUI*);
       static void top_clicked_cb     (GtkButton*, PostUI*);
       static void bottom_clicked_cb  (GtkButton*, PostUI*);
       static void delete_clicked_cb  (GtkButton*, PostUI*);
       static void on_parts_box_clicked_cb (GtkCellRendererToggle *cell, gchar *path_str, gpointer user_data);
-      static void queue_save_toggled_cb (GtkToggleButton * tb, gpointer gp UNUSED);
 
-    public:
+    private:
       TaskUpload* upload_ptr() { return _upload_ptr; }
+      UploadQueue _upload_queue;
 
   };
 }
diff --git a/pan/gui/post.ui.h b/pan/gui/post.ui.h
index 9e2f923..3213a12 100644
--- a/pan/gui/post.ui.h
+++ b/pan/gui/post.ui.h
@@ -1,8 +1,9 @@
-const char * fallback_post_ui = 
+const char * fallback_post_ui =
 "<ui>\n"
 "  <menubar name='post'>\n"
 "    <menu action='file-menu'>\n"
 "      <menuitem action='post-article' />\n"
+"      <menuitem action ='post-and-save-articles'  />\n"
 "      <separator />\n"
 "      <menuitem action='save-draft' />\n"
 "      <menuitem action='open-draft' />\n"
@@ -31,6 +32,7 @@ const char * fallback_post_ui =
 "\n"
 "  <toolbar name='post-toolbar'>\n"
 "    <toolitem action='post-article' />\n"
+"    <toolitem action='post-and-save-articles' />\n"
 "    <separator />\n"
 "    <toolitem action='save-draft' />\n"
 "    <toolitem action='open-draft' />\n"
diff --git a/pan/gui/prefs-ui.cc b/pan/gui/prefs-ui.cc
index 0646436..a701b73 100644
--- a/pan/gui/prefs-ui.cc
+++ b/pan/gui/prefs-ui.cc
@@ -614,10 +614,12 @@ PrefsDialog :: PrefsDialog (Prefs& prefs, GtkWindow* parent):
   t = HIG :: workarea_create ();
   HIG :: workarea_add_section_title (t, &row, _("Upload Queue Options"));
   HIG :: workarea_add_section_spacer (t, row, 4);
-  w = new_check_button (_("Always save article _information from Uploads to a file"), "upload-queue-save-enabled", false, prefs);
+  w = new_check_button (_("Always save header _information to a file"), "upload-queue-save-enabled", false, prefs);
+  HIG :: workarea_add_wide_control (t, &row, w);
+  w = new_check_button (_("Always use a custom Message-ID for posts"), "upload-enable-custom-mid", false, prefs);
   HIG :: workarea_add_wide_control (t, &row, w);
   HIG :: workarea_add_section_title (t, &row, _("Upload Subject Line Appearance"));
-  w = new_check_button (_("Append su_bject for all posts"), "upload-queue-append-subject-enabled", false, prefs);
+  w = new_check_button (_("Append su_bject to all posts"), "upload-queue-append-subject-enabled", false, prefs);
   HIG :: workarea_add_wide_control (t, &row, w);
   HIG :: workarea_finish (t, &row);
   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), t, gtk_label_new_with_mnemonic(_("_Upload options")));
diff --git a/pan/gui/server-ui.cc b/pan/gui/server-ui.cc
index 05d7f15..a118661 100644
--- a/pan/gui/server-ui.cc
+++ b/pan/gui/server-ui.cc
@@ -54,7 +54,6 @@ namespace
     GtkWidget * auth_password_entry;
     GtkWidget * connection_limit_spin;
     GtkWidget * expiration_age_combo;
-    GtkWidget * xzver_compression_combo;
     GtkWidget * rank_combo;
     ServerEditDialog (Data& d, Queue& q): data(d), queue(q) {}
   };
@@ -92,7 +91,7 @@ namespace
 
     d->server = server;
 
-    int port(119), max_conn(4), age(31*3), rank(1), xzver(0);
+    int port(119), max_conn(4), age(31*3), rank(1);
     std::string addr, user, pass;
     if (!server.empty()) {
       d->data.get_server_addr (server, addr, port);
@@ -100,7 +99,6 @@ namespace
       age = d->data.get_server_article_expiration_age (server);
       rank = d->data.get_server_rank (server);
       max_conn = d->data.get_server_limits (server);
-      xzver = d->data.get_server_xzver_support(server);
     }
 
     pan_entry_set_text (d->address_entry, addr);
@@ -133,18 +131,6 @@ namespace
         break;
       }
     } while (gtk_tree_model_iter_next(model, &iter));
-
-    // set the xzver combo
-    combo = GTK_COMBO_BOX (d->xzver_compression_combo);
-    model = gtk_combo_box_get_model (combo);
-    if (gtk_tree_model_get_iter_first(model, &iter)) do {
-      int that;
-      gtk_tree_model_get (model, &iter, 1, &that, -1);
-      if (that == xzver) {
-        gtk_combo_box_set_active_iter (combo, &iter);
-        break;
-      }
-    } while (gtk_tree_model_iter_next(model, &iter));
   }
 
   void
@@ -173,10 +159,6 @@ namespace
       combo = GTK_COMBO_BOX (d->rank_combo);
       if (gtk_combo_box_get_active_iter (combo, &iter))
         gtk_tree_model_get (gtk_combo_box_get_model(combo), &iter, 1, &rank, -1);
-      int xzver (1);
-      combo = GTK_COMBO_BOX (d->xzver_compression_combo);
-      if (gtk_combo_box_get_active_iter (combo, &iter))
-        gtk_tree_model_get (gtk_combo_box_get_model(combo), &iter, 1, &xzver, -1);
 
       const char * err_msg (0);
       if (addr.empty())
@@ -199,7 +181,6 @@ namespace
         d->data.set_server_limits (d->server, max_conn);
         d->data.set_server_article_expiration_age (d->server, age);
         d->data.set_server_rank (d->server, rank);
-        d->data.set_server_xzver_support(d->server, xzver);
         d->data.save_server_info(d->server);
         d->queue.upkeep ();
       }
@@ -323,25 +304,6 @@ pan :: server_edit_dialog_new (Data& data, Queue& queue, GtkWindow * window, con
     gtk_widget_set_tooltip_text( e, _("Fallback servers are used for articles that can't be found on the primaries.  One common approach is to use free servers as primaries and subscription servers as fallbacks."));
     HIG::workarea_add_row (t, &row, e, w);
 
-    /* xzver settings */
-    struct { int type; const char * str; } xzver_options[] = {
-      { 0,  N_("No") },
-      { 1,  N_("Yes") }
-    };
-    store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
-    for (unsigned int i(0); i<G_N_ELEMENTS(xzver_options); ++i) {
-      GtkTreeIter iter;
-      gtk_list_store_append (store,  &iter);
-      gtk_list_store_set (store, &iter, 0, _(xzver_options[i].str), 1, xzver_options[i].type, -1);
-    }
-    d->xzver_compression_combo = w = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
-    g_object_unref (G_OBJECT(store));
-    GtkCellRenderer * renderer2 (gtk_cell_renderer_text_new ());
-    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), renderer2, TRUE);
-    gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), renderer2, "text", 0, NULL);
-    gtk_combo_box_set_active (GTK_COMBO_BOX(w), 0);
-    HIG::workarea_add_row (t, &row, _("Serverside _Header-compression support:"), w, NULL);
-
   d->server = server;
   edit_dialog_populate (data, server, d);
   gtk_widget_show_all (d->dialog);
diff --git a/pan/tasks/Makefile.am b/pan/tasks/Makefile.am
index 5609f40..9f0606d 100644
--- a/pan/tasks/Makefile.am
+++ b/pan/tasks/Makefile.am
@@ -1,4 +1,5 @@
 AM_CPPFLAGS = -I top_srcdir@ @GMIME_CFLAGS@ @GLIB_CFLAGS@
+AM_LDFLAGS = ../../uulib/libuu.a -lz
 
 noinst_LIBRARIES = libtasks.a
 
@@ -10,11 +11,11 @@ libtasks_a_SOURCES = \
   task-groups.cc \
   task-post.cc \
   task-xover.cc \
-  task-xzver-test.cc \
   task-upload.cc \
   nntp.cc \
   nzb.cc \
   queue.cc \
+  upload-queue.cc \
   socket.cc \
   socket-impl-gio.cc \
   socket-impl-scripted.cc \
@@ -34,10 +35,10 @@ noinst_HEADERS = \
   task-upload.h \
   task-weak-ordering.h \
   task-xover.h \
-  task-xzver-test.h \
   nntp.h  \
   nzb.h  \
   queue.h  \
+  upload-queue.h \
   socket.h \
   socket-impl-gio.h \
   socket-impl-scripted.h \
diff --git a/pan/tasks/decoder.cc b/pan/tasks/decoder.cc
index 5e8bfa8..ece4f24 100644
--- a/pan/tasks/decoder.cc
+++ b/pan/tasks/decoder.cc
@@ -22,7 +22,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <config.h>
-#include <algorithm>
+//#include <algorithm>
 #include <cerrno>
 #include <ostream>
 #include <fstream>
@@ -171,8 +171,8 @@ Decoder :: do_work()
           file :: ensure_dir_exists (save_path.c_str());
 
         // find a unique filename...
-        char * fname = file::get_unique_fname(save_path.c_str(), 
-                                              (item->filename 
+        char * fname = file::get_unique_fname(save_path.c_str(),
+                                              (item->filename
                                                && *item->filename)
                                               ? item->filename
                                               : "pan-saved-file" );
diff --git a/pan/tasks/encoder.cc b/pan/tasks/encoder.cc
index 763673c..9447c3c 100644
--- a/pan/tasks/encoder.cc
+++ b/pan/tasks/encoder.cc
@@ -127,6 +127,7 @@ Encoder :: enqueue (TaskUpload                      * task,
 void
 Encoder :: do_work()
 {
+
   const int bufsz = 4096;
   char buf[bufsz], buf2[bufsz];
   int cnt(1);
@@ -155,7 +156,7 @@ Encoder :: do_work()
       tmp->subject = buf;
 
       char cachename[4096];
-      for (TaskUpload::needed_t::iterator it = needed->begin(); it != needed->end(); ++it, ++cnt)
+      for (TaskUpload::needed_t::iterator it = needed->begin(); it != needed->end(); ++it, it, ++cnt)
       {
         FILE * fp = cache->get_fp_from_mid(it->second.message_id);
         if (!fp)
@@ -165,13 +166,16 @@ Encoder :: do_work()
           continue;
         }
         // 4000 lines SHOULD be OK for ANY nntp server ...
-        StringView mid(global_mid);
-        generate_unique_id(mid, cnt, s);
+        if (!global_mid.empty())
+        {
+          StringView mid(global_mid);
+          generate_unique_id(mid, cnt, s);
+        }
         res = UUE_PrepPartial (fp, NULL, (char*)filename.c_str(),YENC_ENCODED,
                                (char*)basename.c_str(),0644, cnt, 4000,
                                0, (char*)groups.c_str(),
                                (char*)author.c_str(),
-                               (char*)subject.c_str(), (char*)s.c_str(), (char*)format.c_str(), 0);
+                               (char*)subject.c_str(), s.empty() ? NULL : (char*)s.c_str(), (char*)format.c_str(), 0);
 
         if (fp) fclose(fp);
         cache->finalize(it->second.message_id);
@@ -185,7 +189,6 @@ Encoder :: do_work()
 
       if (res != UURET_OK && res != UURET_CONT)
       {
-        unlink(cachename); //brute-force
         g_snprintf(buf, bufsz,
                    _("Error encoding %s: %s"),
                    basename.c_str(),
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
index 10e888b..d2fc199 100644
--- a/pan/tasks/encoder.h
+++ b/pan/tasks/encoder.h
@@ -91,7 +91,7 @@ namespace pan
       std::string   basename, filename;
       std::string subject, author, groups, mid, format;
       EncodeCache * cache;
-      TaskUpload::needed_t* needed;
+      TaskUpload::needed_t * needed;
       std::string global_mid;
       Article article;
       MTRand mtrand;
diff --git a/pan/tasks/nntp.cc b/pan/tasks/nntp.cc
index dcacbe8..b2faafd 100644
--- a/pan/tasks/nntp.cc
+++ b/pan/tasks/nntp.cc
@@ -81,11 +81,12 @@ NNTP :: on_socket_response (Socket * sock UNUSED, const StringView& line_in)
    if (line.len>=2 && line.str[line.len-2]=='\r' && line.str[line.len-1]=='\n')
       line.truncate (line.len-2);
 
-//debug ("_nntp_response_text: " << _nntp_response_text);
+//    std::cerr <<"_nntp_response_text: " << _nntp_response_text<<std::endl;
    if (_nntp_response_text)
    {
       if (line.len==1 && line.str[0]=='.') // end-of-list
       {
+        std::cerr<<"line end\n";
          state = CMD_DONE;
          _nntp_response_text = false;
       }
@@ -93,7 +94,7 @@ NNTP :: on_socket_response (Socket * sock UNUSED, const StringView& line_in)
       {
          state = CMD_MORE;
 
-         if (line.len>=2 && line.str[0]=='.' && line.str[1]=='.') // rfc 977: 2.4.1
+         if (line.len>=2 && line.str[0]=='.' && line.str[1]=='.' && !_xzver) // rfc 977: 2.4.1
             line.rtruncate (line.len-1);
 
          assert (_listener != 0);
@@ -186,6 +187,7 @@ NNTP :: on_socket_response (Socket * sock UNUSED, const StringView& line_in)
       case XOVER_FOLLOWS:
         if (_listener)
           _listener->on_xover_follows(this, line);
+        if (line.strstr("compressed")) _xzver = true;
       case ARTICLE_FOLLOWS:
       case NEWGROUPS_FOLLOWS:
       case INFORMATION_FOLLOWS:
@@ -196,8 +198,6 @@ NNTP :: on_socket_response (Socket * sock UNUSED, const StringView& line_in)
       case AUTH_REJECTED:
       case NO_GROUP_SELECTED:
       case ERROR_CMD_NOT_UNDERSTOOD:
-        if (_listener)
-          _listener->on_what(this, line);
       case ERROR_CMD_NOT_SUPPORTED:
       case NO_PERMISSION:
       case FEATURE_NOT_SUPPORTED: {
@@ -246,8 +246,8 @@ NNTP :: on_socket_response (Socket * sock UNUSED, const StringView& line_in)
 
    bool more;
    switch (state) {
-      case CMD_FAIL: std::cerr<<"firing err_cmd: "<<line.str<<std::endl; fire_done_func (ERR_COMMAND, line); more = false; break;
-      case CMD_DONE: if (_commands.empty()) fire_done_func (OK, line); more = false; break;
+      case CMD_FAIL: fire_done_func (ERR_COMMAND, line); more = false; break;
+      case CMD_DONE: _xzver = false; if (_commands.empty()) fire_done_func (OK, line); more = false; break;
       case CMD_MORE: more = true; break; // keep listining for more on this command
       case CMD_NEXT: more = false; break; // no more responses on this command; wait for next...
       case CMD_RETRY: fire_done_func (ERR_NETWORK, line); more = false; break;
@@ -313,6 +313,8 @@ NNTP :: xzver (const Quark   & group,
 {
    _listener = l;
 
+  std::cerr<<"nntp xzver\n";
+
    if (group != _group)
       _commands.push_back (build_command ("GROUP %s\r\n", group.c_str()));
 
@@ -321,7 +323,6 @@ NNTP :: xzver (const Quark   & group,
    write_next_command ();
 }
 
-
 void
 NNTP :: xover (const Quark   & group,
                uint64_t        low,
diff --git a/pan/tasks/nntp.h b/pan/tasks/nntp.h
index 3b09d81..5cd9fd0 100644
--- a/pan/tasks/nntp.h
+++ b/pan/tasks/nntp.h
@@ -135,6 +135,7 @@ namespace pan
                                     uint64_t             low           UNUSED,
                                     uint64_t             high          UNUSED) {}
 
+        // for xzver-test
         virtual void on_xover_follows  (NNTP               * nntp UNUSED,
                                         const StringView   & line UNUSED) {}
 
@@ -156,7 +157,8 @@ namespace pan
           _listener(0),
           _username(username),
           _password(password),
-          _nntp_response_text(false)
+          _nntp_response_text(false),
+          _xzver(false)
        {
        }
 
@@ -193,11 +195,23 @@ namespace pan
                              uint64_t             high,
                              Listener           * l);
 
-      /* same as above, experimental header compression (!!!) */
-      void xzver            (const Quark        & group,
-                             uint64_t             low,
-                             uint64_t             high,
-                             Listener           * l);
+      /**
+       * Executes an XZVER command: "XZVER low-high"
+       *
+       * If successful, this will invoke Listener::on_nntp_line()
+       * for each article header line we get back.
+       *
+       * Listener::on_nntp_done() will be called whether the
+       * command is successful or not.
+       *
+       * The lines are zlib-compressed and then yenc-encoded,
+       * so we decode the file on HDD and uncompress it.
+       * After that, the file is fed back to Listener::on_nntp_line()
+       */
+      void xzver            (const Quark   & group,
+                             uint64_t        low,
+                             uint64_t        high,
+                             Listener      * l);
 
       /**
        * Executes a LIST command: "LIST"
@@ -325,6 +339,8 @@ namespace pan
       virtual void on_socket_error (Socket*);
       virtual void on_socket_abort (Socket*);
 
+      bool _xzver;
+
     public:
 
       /**
diff --git a/pan/tasks/nzb.cc b/pan/tasks/nzb.cc
index 437cf9a..0ffca03 100644
--- a/pan/tasks/nzb.cc
+++ b/pan/tasks/nzb.cc
@@ -187,16 +187,12 @@ namespace
       debug("adding taskupload from nzb.\n");
       foreach_const (quarks_t, mc.groups, git)
         mc.a.xref.insert (mc.server, *git, 0);
-        ///TODO export/import missing values tp/from nzb
+      ///TODO export/import missing values to/from nzb
       TaskUpload::UploadInfo format;
       format.domain = mc.domain;
-      format.counter = true;
       format.comment1 = true;
-      format.queue_length = 0;
-      format.queue_pos = 0;
-      ///TODO format.save_file =
       TaskUpload* tmp = new TaskUpload (mc.path, mc.server, mc.encode_cache,mc.a,
-                                        format, &mc.needed_parts, 0, TaskUpload::YENC);
+                                        format, mc.needed_parts, 0, TaskUpload::YENC);
       mc.tasks.push_back (tmp);
     }
   }
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index 109699b..6ba74d9 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -64,19 +64,17 @@ namespace
   }
 }
 
-namespace
+std::string
+TaskUpload :: get_domain(const StringView& mid)
 {
-  std::string get_domain(const StringView& mid)
-  {
-    const char * pch = mid.strchr ('@');
-    StringView domain;
-    if (pch) domain = mid.substr (pch+1, NULL);
-    if (pch) pch = domain.strchr ('>');
-    if (pch) domain = domain.substr (NULL, pch);
-    domain.trim ();
-
-    return domain.to_string();
-  }
+  const char * pch = mid.strchr ('@');
+  StringView domain;
+  if (pch) domain = mid.substr (pch+1, NULL);
+  if (pch) pch = domain.strchr ('>');
+  if (pch) domain = domain.substr (NULL, pch);
+  domain.trim ();
+
+  return domain.to_string();
 }
 
 /***
@@ -88,7 +86,7 @@ TaskUpload :: TaskUpload (const std::string         & filename,
                           EncodeCache               & cache,
                           Article                     article,
                           UploadInfo                  format,
-                          needed_t                  * imported,
+                          needed_t                  & imported,
                           Progress::Listener        * listener,
                           const TaskUpload::EncodeMode  enc):
   Task ("UPLOAD", get_description(filename.c_str())),
@@ -105,23 +103,21 @@ TaskUpload :: TaskUpload (const std::string         & filename,
   _lines_per_file(4000),
   _all_bytes(0),
   _format(format),
-  _queue_pos(format.queue_pos),
-  _queue_length(format.queue_length),
-  _domain(get_domain(StringView(format.domain))),
   _save_file(format.save_file)
 {
   if (listener != 0)
     add_listener (listener);
 
-  needed_t& tmp = *imported;
-  if (imported)
-    foreach (needed_t, tmp, nit)
+  if (!format.domain.empty())  _domain = get_domain(StringView(format.domain)) ;
+
+  if (!imported.empty())
+    foreach (needed_t, imported, nit)
       _needed.insert(*nit);
 
   struct stat sb;
   stat(filename.c_str(),&sb);
   _bytes = sb.st_size;
-  build_needed_tasks(imported);
+  build_needed_tasks(!imported.empty());
 
   update_work ();
 }
@@ -144,7 +140,6 @@ TaskUpload :: build_needed_tasks(bool imported)
   }
   _cache.reserve(_mids);
   _needed_parts = _needed.size();
-
 }
 
 void
@@ -247,7 +242,6 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
       it->second.reset();
       goto _end;
     case ERR_COMMAND:
-      //std::cerr<<"err command : "<< _basename.c_str()<<" "<< it->second.partno<<" "<< _total_parts<<"\n";
       _needed.erase (it);
       break;
   }
@@ -263,7 +257,6 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
       if (health != OK)     // if we got a dupe, the health is OK, so skip that
       {
         tmp.severity = Log :: PAN_SEVERITY_ERROR;
-        //std::cerr<<"failed : "<<response<<std::endl;
         g_snprintf(buf,sizeof(buf), _("Posting of File %s (Part %d of %d) failed: %s"),
                    _basename.c_str(), it->second.partno, _total_parts, response.str);
         tmp.message = buf;
@@ -410,6 +403,7 @@ TaskUpload :: on_worker_done (bool cancelled)
 
 TaskUpload :: ~TaskUpload ()
 {
+
   // ensure our on_worker_done() doesn't get called after we're dead
   if (_encoder)
       _encoder->cancel_silently();
@@ -417,6 +411,7 @@ TaskUpload :: ~TaskUpload ()
   _cache.release(_mids);
   _cache.resize();
 
+  ///TODO properly enclose all tasks in nzb tags (listener needed ...(??) )
   if (!_save_file.empty())
   {
      std::ofstream out(_save_file.c_str(), std::fstream::out | std::fstream::app);
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
index e9712cd..4c2924d 100644
--- a/pan/tasks/task-upload.h
+++ b/pan/tasks/task-upload.h
@@ -51,15 +51,11 @@ namespace pan
 
       struct UploadInfo
       {
-        bool comment1, counter;
+        bool comment1;
         std::string    domain;
         std::string    save_file;
-        int   queue_pos;
-        int   queue_length;
       };
 
-      ///TODO SEE!
-      void set_lpf (const int& setme ) { _lines_per_file = setme; }
       const Article& get_article ()  { return _article; }
 
       typedef std::vector<Quark> mid_sequence_t;
@@ -90,7 +86,7 @@ namespace pan
                    EncodeCache               & cache,
                    Article                     article,
                    UploadInfo                  format,
-                   needed_t                  * imported=0,
+                   needed_t                  & imported,
                    Progress::Listener        * listener= 0,
                    TaskUpload::EncodeMode enc= YENC);
 
@@ -149,8 +145,6 @@ namespace pan
       unsigned long _all_bytes;
       std::vector<Article*> _upload_list;
       std::string _save_file;
-      int  _queue_pos;
-      int  _queue_length;
       Article::mid_sequence_t _mids;
 
     private:
@@ -158,6 +152,9 @@ namespace pan
       void update_work (NNTP * checkin_pending = 0);
       void build_needed_tasks(bool);
 
+      std::string get_domain(const StringView&);
+      void set_domain(std::string d) { _domain = d; }
+
   };
 }
 
diff --git a/pan/tasks/task-weak-ordering.h b/pan/tasks/task-weak-ordering.h
index dad898f..36fe5d0 100644
--- a/pan/tasks/task-weak-ordering.h
+++ b/pan/tasks/task-weak-ordering.h
@@ -34,15 +34,14 @@ namespace pan
    */
   struct TaskWeakOrdering
   {
-    const Quark BODIES, CANCEL, GROUPS, POST, SAVE, XOVER, XZVER_TEST;
+    const Quark BODIES, CANCEL, GROUPS, POST, SAVE, XOVER;
     TaskWeakOrdering ():
       BODIES ("BODIES"),
       CANCEL ("CANCEL"),
       GROUPS ("GROUPS"),
       POST ("POST"),
       SAVE ("SAVE"),
-      XOVER ("XOVER"),
-      XZVER_TEST ("XZVER_TEST")
+      XOVER ("XOVER")
       {}
 
     int get_rank_for_type (const Quark& type) const
@@ -51,7 +50,7 @@ namespace pan
 
       if (type==BODIES || type==POST || type==CANCEL)
         rank = 0;
-      else if (type==XOVER || type==GROUPS || type==XZVER_TEST)
+      else if (type==XOVER || type==GROUPS)
         rank = 1;
       else if (type==SAVE)
         rank = 2;
diff --git a/pan/tasks/task-xover.cc b/pan/tasks/task-xover.cc
index 40b292f..0b6123b 100644
--- a/pan/tasks/task-xover.cc
+++ b/pan/tasks/task-xover.cc
@@ -21,9 +21,16 @@
 #include <cassert>
 #include <cerrno>
 extern "C" {
+  #define PROTOTYPES
+  #include <stdio.h>
+  #include <uulib/uudeview.h>
   #include <glib/gi18n.h>
   #include <gmime/gmime-utils.h>
+
 }
+#include <fstream>
+#include <iostream>
+#include <pan/usenet-utils/gzstream.h>
 #include <pan/general/debug.h>
 #include <pan/general/macros.h>
 #include <pan/general/messages.h>
@@ -92,8 +99,12 @@ TaskXOver :: TaskXOver (Data         & data,
   _bytes_so_far (0),
   _parts_so_far (0ul),
   _articles_so_far (0ul),
-  _total_minitasks (0)
+  _total_minitasks (0),
+  _xzver(true)
 {
+
+  _header_file.open("/home/imhotep/headers", std::ios::out | std::ios::app | std::ios::binary);
+
   debug ("ctor for " << group);
 
   // add a ``GROUP'' MiniTask for each server that has this group
@@ -156,7 +167,10 @@ TaskXOver :: use_nntp (NNTP* nntp)
       case MiniTask::XOVER:
         debug ("XOVER " << mt._low << '-' << mt._high << " to " << server);
         _last_xover_number[nntp] = mt._low;
-        nntp->xover (_group, mt._low, mt._high, this);
+        if (_xzver)
+          nntp->xzver (_group, mt._low, mt._high, this);
+        else
+          nntp->xover (_group, mt._low, mt._high, this);
         break;
       default:
         assert (0);
@@ -264,9 +278,24 @@ namespace
 }
 
 void
-TaskXOver :: on_nntp_line (NNTP               * nntp,
-                           const StringView   & line)
+TaskXOver :: on_nntp_line         (NNTP               * nntp,
+                                   const StringView   & line)
 {
+//  if (!_xzver)
+//  {
+//    on_nntp_line_process(nntp, line);
+//    return;
+//  }
+  // feed lines into header file
+  _header_file<<line;
+
+}
+
+void
+TaskXOver :: on_nntp_line_process (NNTP               * nntp,
+                                   const StringView   & line)
+{
+
   pan_return_if_fail (nntp != 0);
   pan_return_if_fail (!nntp->_server.empty());
   pan_return_if_fail (!nntp->_group.empty());
@@ -350,7 +379,41 @@ TaskXOver :: on_nntp_done (NNTP              * nntp,
                            Health              health,
                            const StringView  & response UNUSED)
 {
+
   //std::cerr << LINE_ID << " nntp " << nntp->_server << " (" << nntp << ") done; checking in.  health==" << health << std::endl;
+
+  // step 0 : save sstream to file
+
+  _header_file.close();
+
+  // step 1 : decompress
+//  igzstream in();
+//  char c;
+//  std::ofstream out("/home/imhotep/headers_decomp", std::ifstream::out);
+//  while ( in.get(c))
+//    std::cout << c;
+
+  // step 2 : decode
+  int res = UUInitialize();
+  std::cerr<<"uulib : "<<UUstrerror(res)<<std::endl;
+  res = UULoadFileWithPartNo (const_cast<char*>("/home/imhotep/headers_decomp"), 0, 0, 1);
+  std::cerr<<"uulib : "<<UUstrerror(res)<<std::endl;
+  uulist * item = UUGetFileListItem (1);
+  if (!item)
+    std::cerr<<"uulib : failed to get list item"<<std::endl;
+  res = UUDecodeFile (item, (const_cast<char*>("/home/imhotep/headers_ready")));
+  std::cerr<<"uulib : "<<UUstrerror(res)<<std::endl;
+  UUCleanUp();
+
+
+  // step 3 : feed to on_nntp_line
+  std::ifstream ready("/home/imhotep/headers_ready", std::ifstream::in);
+  char buf[2048];
+  while (ready.good())
+  {
+    ready.getline(buf,sizeof(buf));
+    on_nntp_line_process (nntp, StringView(buf));
+  }
   update_work (true);
   check_in (nntp, health);
 }
diff --git a/pan/tasks/task-xover.h b/pan/tasks/task-xover.h
index 8701808..28dd014 100644
--- a/pan/tasks/task-xover.h
+++ b/pan/tasks/task-xover.h
@@ -22,10 +22,13 @@
 
 #include <map>
 #include <vector>
+#include <sstream>
 
 #include <pan/data/data.h>
 #include <pan/tasks/task.h>
 #include <pan/tasks/nntp.h>
+#include <fstream>
+#include <iostream>
 
 namespace pan
 {
@@ -47,6 +50,8 @@ namespace pan
       virtual void use_nntp (NNTP * nntp);
 
     private: // NNTP::Listener
+      void on_nntp_line_process (NNTP*, const StringView&);
+      void on_xover_follows (NNTP*, const StringView& line) { std::cerr<<line<<std::endl; }
       virtual void on_nntp_line (NNTP*, const StringView&);
       virtual void on_nntp_done (NNTP*, Health, const StringView&);
       virtual void on_nntp_group (NNTP*, const Quark&, unsigned long, uint64_t, uint64_t);
@@ -80,6 +85,9 @@ namespace pan
       unsigned long _parts_so_far;
       unsigned long _articles_so_far;
       unsigned long _total_minitasks;
+      bool _xzver;
+      std::stringstream _headers;
+      std::ofstream _header_file;
   };
 }
 
diff --git a/pan/tasks/upload-queue.cc b/pan/tasks/upload-queue.cc
new file mode 100644
index 0000000..5e26687
--- /dev/null
+++ b/pan/tasks/upload-queue.cc
@@ -0,0 +1,188 @@
+/* -*- 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 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 <pan/general/debug.h>
+#include <pan/general/macros.h>
+#include <pan/general/messages.h>
+#include <pan/data/server-info.h>
+#include "upload-queue.h"
+#include "task.h"
+#include "task-upload.h"
+
+/***
+****
+***/
+
+using namespace pan;
+
+UploadQueue :: UploadQueue ()
+{
+    _tasks.add_listener (this);
+}
+
+UploadQueue :: ~UploadQueue ()
+{
+
+//  const tasks_t tmp (_tasks.begin(), _tasks.end());
+//  foreach_const (tasks_t, tmp, it) {
+//    TaskUpload * task  (*it);
+//    remove_task (task);
+//  }
+
+//  foreach (TaskSet, _tasks, it)
+//    delete *it;
+}
+
+void
+UploadQueue :: get_all_tasks (tasks_t& setme)
+{
+  setme.clear();
+  setme.reserve(_tasks.size());
+
+  foreach(TaskSet, _tasks, it)
+    setme.push_back(*it);
+}
+
+void
+UploadQueue :: clear()
+{
+  const tasks_t tmp (_tasks.begin(), _tasks.end());
+  foreach_const (tasks_t, tmp, it) {
+    TaskUpload * task  (*it);
+    remove_task (task);
+  }
+
+  foreach (TaskSet, _tasks, it)
+    delete *it;
+}
+
+void
+UploadQueue :: add_task (TaskUpload * task, AddMode mode)
+{
+  tasks_t tasks;
+  tasks.push_back (task);
+  add_tasks (tasks, mode);
+}
+
+void
+UploadQueue :: add_tasks (const tasks_t& tasks, AddMode mode)
+{
+  if (mode == TOP)
+    _tasks.add_top (tasks);
+  else if (mode == BOTTOM)
+    _tasks.add_bottom (tasks);
+  else
+    _tasks.add (tasks);
+}
+
+void
+UploadQueue :: remove_tasks (const tasks_t& tasks)
+{
+  std::cerr<<"remove tasks\n";
+  foreach_const (tasks_t, tasks, it)
+    remove_task (*it);
+}
+
+void
+UploadQueue :: remove_task (TaskUpload * task)
+{
+  std::cerr<<"remove task\n";
+  const int index (_tasks.index_of (task));
+  pan_return_if_fail (index != -1);
+  _tasks.remove (index);
+  delete task;
+}
+
+void
+UploadQueue :: move_up (const tasks_t& tasks)
+{
+  foreach_const (tasks_t, tasks, it) {
+    TaskUpload * task (*it);
+    const int old_pos (_tasks.index_of (task));
+    _tasks.move_up (old_pos);
+  }
+}
+
+void
+UploadQueue :: move_down (const tasks_t& tasks)
+{
+  foreach_const_r (tasks_t, tasks, it) {
+    TaskUpload * task (*it);
+    const int old_pos (_tasks.index_of (task));
+    _tasks.move_down (old_pos);
+  }
+}
+
+void
+UploadQueue :: move_top (const tasks_t& tasks)
+{
+  foreach_const_r (tasks_t, tasks, it) {
+    TaskUpload * task (*it);
+    const int old_pos (_tasks.index_of (task));
+    _tasks.move_top (old_pos);
+  }
+}
+
+void
+UploadQueue :: move_bottom (const tasks_t& tasks)
+{
+  foreach_const (tasks_t, tasks, it) {
+    TaskUpload * task (*it);
+    const int old_pos (_tasks.index_of (task));
+    _tasks.move_bottom (old_pos);
+  }
+}
+
+void
+UploadQueue :: fire_tasks_added (int pos, int count)
+{
+  for (lit it(_listeners.begin()), end(_listeners.end()); it!=end; )
+    (*it++)->on_queue_tasks_added (*this, pos, count);
+}
+void
+UploadQueue :: fire_task_removed (TaskUpload*& task, int pos)
+{
+  for (lit it(_listeners.begin()), end(_listeners.end()); it!=end; )
+    (*it++)->on_queue_task_removed (*this, *task, pos);
+}
+void
+UploadQueue :: fire_task_moved (TaskUpload*& task, int new_pos, int old_pos)
+{
+  for (lit it(_listeners.begin()), end(_listeners.end()); it!=end; )
+    (*it++)->on_queue_task_moved (*this, *task, new_pos, old_pos);
+}
+
+void
+UploadQueue :: on_set_items_added (TaskSet& container UNUSED, TaskSet::items_t& tasks, int pos)
+{
+  fire_tasks_added (pos, tasks.size());
+}
+
+void
+UploadQueue :: on_set_item_removed (TaskSet& container UNUSED, TaskUpload*& task, int pos)
+{
+  fire_task_removed (task, pos);
+}
+
+void
+UploadQueue :: on_set_item_moved (TaskSet& container UNUSED, TaskUpload*& task, int new_pos, int old_pos)
+{
+  fire_task_moved (task, new_pos, old_pos);
+}
diff --git a/pan/tasks/upload-queue.h b/pan/tasks/upload-queue.h
new file mode 100644
index 0000000..f60e961
--- /dev/null
+++ b/pan/tasks/upload-queue.h
@@ -0,0 +1,111 @@
+/* -*- 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 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 _UploadQueue_h_
+#define _UploadQueue_h_
+
+#include <map>
+#include <set>
+#include <vector>
+#include <pan/general/macros.h> // for UNUSED
+#include <pan/general/map-vector.h>
+#include <pan/tasks/decoder.h>
+#include <pan/tasks/encoder.h>
+#include <pan/general/quark.h>
+#include <pan/tasks/nntp-pool.h>
+#include <pan/tasks/socket.h>
+#include <pan/tasks/adaptable-set.h>
+#include <pan/tasks/task-upload.h>
+#include <pan/tasks/encoder.h>
+#include <pan/tasks/task-weak-ordering.h>
+
+namespace pan
+{
+  class NNTP;
+  class ServerInfo;
+  class WorkerPool;
+  struct Encoder;
+
+  class UploadQueue:
+        private AdaptableSet<TaskUpload*, TaskWeakOrdering>::Listener
+  {
+    public:
+
+      typedef AdaptableSet<TaskUpload*, TaskWeakOrdering> TaskSet;
+
+      UploadQueue ();
+      virtual ~UploadQueue ();
+
+      typedef std::vector<TaskUpload*> tasks_t;
+      void remove_tasks  (const tasks_t&);
+      void move_up       (const tasks_t&);
+      void move_down     (const tasks_t&);
+      void move_top      (const tasks_t&);
+      void move_bottom   (const tasks_t&);
+
+      enum AddMode { TOP, BOTTOM };
+      void add_tasks     (const tasks_t&, AddMode=BOTTOM);
+
+      void add_task (TaskUpload*, AddMode=BOTTOM);
+      void remove_task (TaskUpload*);
+
+      void clear();
+
+      void get_all_tasks (tasks_t& setme);
+
+    protected:
+      virtual void fire_tasks_added  (int index, int count);
+      virtual void fire_task_removed (TaskUpload*&, int index);
+      virtual void fire_task_moved   (TaskUpload*&, int index, int old_index);
+
+    public:
+
+      struct Listener {
+        virtual ~Listener () {}
+        virtual void on_queue_task_active_changed (UploadQueue&, TaskUpload&, bool active) {}
+        virtual void on_queue_tasks_added (UploadQueue&, int index, int count) = 0;
+        virtual void on_queue_task_removed (UploadQueue&, TaskUpload&, int index) = 0;
+        virtual void on_queue_task_moved (UploadQueue&, TaskUpload&, int new_index, int old_index) = 0;
+        virtual void on_queue_connection_count_changed (UploadQueue&, int count) {}
+        virtual void on_queue_size_changed (UploadQueue&, int active, int total) {}
+        virtual void on_queue_online_changed (UploadQueue&, bool online) {}
+        virtual void on_queue_error (UploadQueue&, const StringView& message) {}
+      };
+
+      void add_listener (Listener *l) { _listeners.insert(l); }
+      void remove_listener (Listener *l) { _listeners.erase(l); }
+
+    private:
+      typedef std::set<Listener*> listeners_t;
+      typedef listeners_t::iterator lit;
+      listeners_t _listeners;
+
+    public:
+      TaskUpload* operator[](size_t i) { return _tasks[i]; }
+      const TaskUpload* operator[](size_t i) const { return _tasks[i]; }
+
+    private:
+      TaskSet _tasks;
+      virtual void on_set_items_added  (TaskSet&, TaskSet::items_t&, int index);
+      virtual void on_set_item_removed (TaskSet&, TaskUpload*&, int index);
+      virtual void on_set_item_moved   (TaskSet&, TaskUpload*&, int index, int old_index);
+  };
+}
+
+#endif
diff --git a/pan/usenet-utils/Makefile.am b/pan/usenet-utils/Makefile.am
index 32749af..c9e7acd 100644
--- a/pan/usenet-utils/Makefile.am
+++ b/pan/usenet-utils/Makefile.am
@@ -11,7 +11,8 @@ libusenetutils_a_SOURCES = \
  scorefile.cc \
  text-massager.cc \
  url-find.cc \
- MersenneTwister.h
+ MersenneTwister.h \
+ gzstream.cc
 
 noinst_HEADERS = \
  defgroup.h \
@@ -22,7 +23,8 @@ noinst_HEADERS = \
  numbers.h \
  scorefile.h \
  text-massager.h \
- url-find.h
+ url-find.h \
+ gzstream.h
 
 noinst_PROGRAMS = \
  gnksa-test \
diff --git a/pan/usenet-utils/message-check.cc b/pan/usenet-utils/message-check.cc
index 84f610f..1434013 100644
--- a/pan/usenet-utils/message-check.cc
+++ b/pan/usenet-utils/message-check.cc
@@ -311,9 +311,9 @@ namespace
   void check_body (unique_strings_t       & errors,
                    MessageCheck::Goodness & goodness,
                    const TextMassager     & tm,
-	           GMimeMessage           * message,
-	           const StringView       & body,
-	           const StringView       & attribution)
+                   GMimeMessage           * message,
+                   const StringView       & body,
+                   const StringView       & attribution)
   {
     check_empty         (errors, goodness, body);
     check_wide_body     (errors, goodness, body);
diff --git a/uulib/uuencode.c b/uulib/uuencode.c
index fd0e59c..adcf4ff 100644
--- a/uulib/uuencode.c
+++ b/uulib/uuencode.c
@@ -1547,7 +1547,7 @@ UUE_PrepSingleExt (FILE *outfile, FILE *infile,
 
   if (encoding == YENC_ENCODED) {
     if (subject)
-      sprintf (subline, "\"%s\" - %s (001/001)", oname, subject);
+      sprintf (subline, "%s - \"%s\" (001/001)", subject, oname);
     else
       sprintf (subline, "\"%s\" - (001/001)", oname);
   }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]