[pan2/testing: 94/279] bugfix'n + new logo.



commit 87249c5cfc2f985b6a5eafb7c96e4de1b5b35a51
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Wed Jun 8 14:56:46 2011 +0200

    bugfix'n + new logo.

 pan/data/encode-cache.cc   |  113 +++++++-------------------------------------
 pan/data/encode-cache.h    |    3 +-
 pan/data/encode-cache.o    |  Bin 872312 -> 763224 bytes
 pan/gui/gui.cc             |    5 ++-
 pan/gui/gui.h              |    4 +-
 pan/gui/post-ui.cc         |   57 ++++++++++++++--------
 pan/gui/post-ui.h          |    5 ++
 pan/gui/prefs-ui.cc        |    9 +++-
 pan/icons/icon_pan_new.png |  Bin 0 -> 25196 bytes
 pan/icons/icon_pan_new.xcf |  Bin 0 -> 12698618 bytes
 pan/tasks/encoder.cc       |   30 +++++++----
 pan/tasks/encoder.h        |    6 +-
 pan/tasks/nntp.cc          |    8 +++-
 pan/tasks/nntp.h           |    1 +
 pan/tasks/nzb.cc           |   16 +++++-
 pan/tasks/task-upload.cc   |   62 +++++++++++++++++-------
 pan/tasks/task-upload.h    |   16 +++++-
 uulib/uudeview.h           |    8 ++--
 uulib/uuencode.c           |   27 +++++-----
 19 files changed, 192 insertions(+), 178 deletions(-)
---
diff --git a/pan/data/encode-cache.cc b/pan/data/encode-cache.cc
index a12b86e..9083f2c 100644
--- a/pan/data/encode-cache.cc
+++ b/pan/data/encode-cache.cc
@@ -49,60 +49,8 @@ using namespace pan;
 /*****
 ******
 *****/
-namespace
-{
-   char*
-   message_id_to_filename (char * buf, const Quark& mid)
-   {
-      int partno();
-      g_snprintf (buf, sizeof(buf), "%s.%d", mid.c_str(), partno);
-      return buf;
-   }
-
-   int
-   filename_to_message_id (char * buf, int len, const char * basename)
-   {
-      const char * in;
-      char * out;
-      char * pch;
-      char tmp_basename[PATH_MAX];
-
-      // sanity clause
-      pan_return_val_if_fail (basename && *basename, 0);
-      pan_return_val_if_fail (buf!=NULL, 0);
-      pan_return_val_if_fail (len>0, 0);
-
-      // remove the trailing ".msg"
-      g_strlcpy (tmp_basename, basename, sizeof(tmp_basename));
-      if ((pch = g_strrstr (tmp_basename, ".msg")))
-         *pch = '\0';
-      g_strstrip (tmp_basename);
-
-      // transform
-      out = buf;
-      *out++ = '<';
-      for (in=tmp_basename; *in; ++in) {
-         if (in[0]!='%' || !g_ascii_isxdigit(in[1]) || !g_ascii_isxdigit(in[2]))
-            *out++ = *in;
-         else {
-            char buf[3];
-            buf[0] = *++in;
-            buf[1] = *++in;
-            buf[2] = '\0';
-            *out++ = (char) strtoul (buf, NULL, 16);
-         }
-      }
-      *out++ = '>';
-      *out = '\0';
-
-      return out - buf;
-   }
-};
-
-/*****
-******
-*****/
 
+// empty cache at construction, we don't need the old files...
 EncodeCache :: EncodeCache (const StringView& path, size_t max_megs):
    _path (path.str, path.len),
    _max_megs (max_megs),
@@ -121,20 +69,10 @@ EncodeCache :: EncodeCache (const StringView& path, size_t max_megs):
       const char * fname;
       while ((fname = g_dir_read_name (dir)))
       {
-         struct stat stat_p;
-         g_snprintf (filename, sizeof(filename), "%s%c%s", _path.c_str(), G_DIR_SEPARATOR, fname);
-         if (!stat (filename, &stat_p))
-         {
-           MsgInfo info;
-           info._message_id = filename;
-           info._size = stat_p.st_size;
-           info._date = stat_p.st_mtime;
-           _current_bytes += info._size;
-           _mid_to_info.insert (mid_to_info_t::value_type (info._message_id, info));
-         }
+        g_snprintf (filename, sizeof(filename), "%s%c%s", _path.c_str(), G_DIR_SEPARATOR, fname);
+        unlink(filename);
       }
       g_dir_close (dir);
-      if (_current_bytes>_max_megs*1024*1024) resize();
    }
 }
 
@@ -181,36 +119,21 @@ EncodeCache :: get_filename (char* buf, const Quark& mid) const
 FILE*
 EncodeCache :: get_fp_from_mid(const Quark& mid)
 {
-  return _mid_to_info[mid]._fp;
+  char buf[PATH_MAX];
+  get_filename(buf, mid);
+  return fopen(buf,"wb+");
 }
 
-FILE*
+void
 EncodeCache :: add (const Quark& message_id)
 {
 
-  pan_return_val_if_fail (!message_id.empty(), false);
-
-  FILE * fp = 0;
-  char filename[PATH_MAX];
-  get_filename (filename, message_id);
-  std::cerr<<"cache add "<<filename<<std::endl;
-  fp = fopen (filename, "wb+");
-
-  if (!fp)
-  {
-    Log::add_err_va (_("Unable to save \"%s\" %s"),
-                     filename, file::pan_strerror(errno));
-  } else
-  {
-    MsgInfo info;
-    info._fp = fp;
-    info._message_id = message_id;
-    info._size = 0;
-    info._date = time(0);
-    _mid_to_info.insert (mid_to_info_t::value_type (info._message_id, info));
-
-  }
-  return fp;
+  MsgInfo info;
+//  info._fp = fp;
+  info._message_id = message_id;
+  info._size = 0;
+  info._date = time(0);
+  _mid_to_info.insert (mid_to_info_t::value_type (info._message_id, info));
 }
 
 /***
@@ -220,13 +143,11 @@ EncodeCache :: add (const Quark& message_id)
 void EncodeCache :: finalize (const Quark& message_id)
 {
   struct stat sb;
-  FILE * fp = get_fp_from_mid(message_id);
-  if (fp) fclose(fp);
   stat (message_id, &sb);
   _mid_to_info[message_id]._size = sb.st_size;
   fire_added (message_id);
   _current_bytes += sb.st_size;
-  // resize();
+  resize();
 }
 
 void
@@ -305,9 +226,9 @@ EncodeCache :: resize (guint64 max_bytes)
     }
   }
 
-//  std::cerr<< "cache expired " << removed.size() << " articles, "
-//         "has " << _mid_to_info.size() << " active "
-//         "and " << _locks.size() << " locked.\n";
+  std::cerr<<"cache expired " << removed.size() << " articles, "
+        "has " << _mid_to_info.size() << " active "
+        "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 68ede69..98e4681 100644
--- a/pan/data/encode-cache.h
+++ b/pan/data/encode-cache.h
@@ -61,7 +61,7 @@ namespace pan
       typedef std::vector<Quark> mid_sequence_t;
 
       bool contains (const Quark& message_id) const;
-      FILE* add (const Quark& message_id);
+      void add (const Quark& message_id);
       void finalize (const Quark& message_id);
       void get_data(std::string& data, const Quark& where);
       void reserve (const mid_sequence_t& mids);
@@ -88,7 +88,6 @@ namespace pan
       std::map<Quark,int> _locks;
 
       struct MsgInfo {
-        FILE * _fp;
         Quark _message_id;
         size_t _size;
         time_t _date;
diff --git a/pan/data/encode-cache.o b/pan/data/encode-cache.o
index 80ba07b..4290839 100644
Binary files a/pan/data/encode-cache.o and b/pan/data/encode-cache.o differ
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index a242685..1ac33ea 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -183,6 +183,8 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, EncodeCache& encode_c
   _taskbar (0)
 {
 
+//  mtrand.seed(); // for mids
+
   char * filename = g_build_filename (file::get_pan_home().c_str(), "pan.ui", NULL);
   if (!gtk_ui_manager_add_ui_from_file (_ui_manager, filename, NULL))
     gtk_ui_manager_add_ui_from_string (_ui_manager, fallback_ui_file, -1, NULL);
@@ -1308,7 +1310,8 @@ void GUI :: do_tip_jar ()
 void GUI :: do_about_pan ()
 {
   const gchar * authors [] = { "Charles Kerr <charles rebelbase com>", "Calin Culianu <calin ajvar org> - Threaded Decoding", 0 };
-  GdkPixbuf * logo = gdk_pixbuf_new_from_inline(-1, icon_pan_about_logo, 0, 0);
+//////  GdkPixbuf * logo = gdk_pixbuf_new_from_inline(-1, icon_pan_about_logo, 0, 0);
+  GdkPixbuf * logo = gdk_pixbuf_new_from_inline(-1, icon_pan_about_logo_new, 0, 0);
   GtkAboutDialog * w (GTK_ABOUT_DIALOG (gtk_about_dialog_new ()));
   gtk_about_dialog_set_program_name (w, _("Pan"));
   gtk_about_dialog_set_version (w, PACKAGE_VERSION);
diff --git a/pan/gui/gui.h b/pan/gui/gui.h
index 72a6e43..d34b47f 100644
--- a/pan/gui/gui.h
+++ b/pan/gui/gui.h
@@ -31,6 +31,8 @@
 #include <pan/gui/group-prefs.h>
 #include <pan/gui/wait.h>
 
+#include <pan/usenet-utils/MersenneTwister.h>
+
 #include "gtk_compat.h"
 
 namespace pan
@@ -57,6 +59,7 @@ namespace pan
       GUI (Data& data, Queue&, ArticleCache&, EncodeCache&, Prefs&, GroupPrefs&);
       virtual ~GUI ();
       GtkWidget* root () { return _root; }
+//      MTRand mtrand;
 
     public: // ActionManager
       virtual bool is_action_active (const char * action_name) const;
@@ -214,7 +217,6 @@ namespace pan
       GtkWidget * _taskbar;
       std::vector<ProgressView*> _views;
       std::list<Task*> _active_tasks;
-
       std::string _charset;
 
       void set_charset (const StringView& v);
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 137698a..e5c778c 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -246,10 +246,10 @@ namespace
       N_("Clear List"),
       G_CALLBACK(do_clear_list) },
 
-//    { "select-parts", NULL,
-//      N_("Select needed Parts"), "",
-//      N_("Select needed Parts"),
-//      G_CALLBACK(do_select_parts) },
+    { "select-parts", NULL,
+      N_("Select needed Parts"), "",
+      N_("Select needed Parts"),
+      G_CALLBACK(do_select_parts) },
 
     { "move-up", NULL,
       N_("Move Up"), "",
@@ -613,6 +613,8 @@ PostUI :: send_now ()
 {
   if (!check_charset())
     return;
+  if (_check_file_save || _prefs.get_flag(QUEUE_SAVE_KEY, false));
+    _save_file = prompt_user_for_upload_nzb_dir(GTK_WINDOW (gtk_widget_get_toplevel(_root)), _prefs);
   GMimeMessage * message (new_message_from_ui (POSTING));
   if (!maybe_post_message (message))
     g_object_unref (G_OBJECT(message));
@@ -1968,10 +1970,15 @@ namespace
   {
     static_cast<Prefs*>(prefs_gpointer)->set_flag (USER_AGENT_PREFS_KEY, gtk_toggle_button_get_active(tb));
   }
-  void queue_save_toggled_cb (GtkToggleButton * tb, gpointer prefs_gpointer)
-  {
-    static_cast<Prefs*>(prefs_gpointer)->set_flag (QUEUE_SAVE_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
@@ -2026,9 +2033,8 @@ PostUI :: create_filequeue_tab ()
   gtk_widget_set_tooltip_text( w, _("Delete from Queue"));
   gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
   w = _save_check = gtk_check_button_new_with_mnemonic (_("Save queue to file"));
-  bool b = _prefs.get_flag (QUEUE_SAVE_KEY, true);
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(w), b);
-  g_signal_connect (w, "toggled", G_CALLBACK(queue_save_toggled_cb), &_prefs);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(w), _prefs.get_flag(QUEUE_SAVE_KEY,false));
+  g_signal_connect (w, "toggled", G_CALLBACK(queue_save_toggled_cb), this);
   gtk_box_pack_start (GTK_BOX(buttons), w, 0, 0, 0);
   pan_box_pack_start_defaults (GTK_BOX(buttons), gtk_event_box_new());
 
@@ -2513,7 +2519,8 @@ PostUI :: PostUI (GtkWindow    * parent,
   _group_entry_changed_idle_tag (0),
   _file_queue_empty(true),
   _upload_ptr(0),
-  _total_parts(0)
+  _total_parts(0),
+  _check_file_save(false)
 {
   g_assert (profiles.has_profiles());
   g_return_if_fail (message != 0);
@@ -2623,8 +2630,8 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
 		if (_file_queue_empty) _file_queue_empty=!_file_queue_empty;
 
 		GSList * cur = g_slist_nth (tmp_list,0);
+    GMimeMessage* msg = message;
     gtk_widget_destroy (w);
-    GMimeMessage* msg = new_message_from_ui(POSTING);
 
     char * tmp;
     tmp = (char*)g_mime_object_get_header ((GMimeObject*)msg, "Subject");
@@ -2642,9 +2649,14 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
         groups.insert(groupname);
     }
 
-    bool b = _prefs.get_flag (QUEUE_SAVE_KEY, true);
-    if (b)
-      _save_file = prompt_user_for_upload_nzb_dir (GTK_WINDOW (gtk_widget_get_toplevel(_root)), _prefs);
+    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;
+    ui.save_file = _save_file;
+    const int list_length = (int)g_slist_length(cur);
+    ui.queue_length = list_length;
 
     int cnt(1);
     for (; cur; cur = cur->next, ++cnt)
@@ -2675,18 +2687,20 @@ 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);
 
-      const std::string message_id = !profile.fqdn.empty()
+      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, message_id, _save_file, &import, 0, TaskUpload::YENC);
+                        a, ui, &import, 0, TaskUpload::YENC);
 		  _file_queue_tasks.push_back(tmp);
 		}
     g_slist_free (tmp_list);
-
-  }
+  } else
+    gtk_widget_destroy (w);
   g_object_unref (G_OBJECT(message));
 	update_filequeue_tab();
 }
@@ -2724,7 +2738,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);
-  }
+  } else
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(_save_check), false);
 
   gtk_widget_destroy (w);
   return path;
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index b5362bc..a69599d 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -61,6 +61,9 @@ namespace pan
       GtkWidget * root() { return _root; }
       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 ();
@@ -154,6 +157,7 @@ namespace pan
       TaskUpload* _upload_ptr;
       int _total_parts;
       std::string _save_file;
+      bool _check_file_save;
 
     private:
       void add_actions (GtkWidget* box);
@@ -209,6 +213,7 @@ namespace pan
       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:
       TaskUpload* upload_ptr() { return _upload_ptr; }
diff --git a/pan/gui/prefs-ui.cc b/pan/gui/prefs-ui.cc
index 574853d..a722db7 100644
--- a/pan/gui/prefs-ui.cc
+++ b/pan/gui/prefs-ui.cc
@@ -614,10 +614,15 @@ 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 article _information from Uploads to a file"), "upload-queue-save-enabled", 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 [_partof/total parts] style counter"), "upload-queue-append-partcounter-enabled", false, prefs);
+  HIG :: workarea_add_wide_control (t, &row, w);
+  w = new_check_button (_("Append su_bject for 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(_("O_ptions for Uploads")));
+  gtk_notebook_append_page (GTK_NOTEBOOK(notebook), t, gtk_label_new_with_mnemonic(_("_Upload options")));
 
   gtk_widget_show_all (notebook);
   gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area( GTK_DIALOG(dialog))), notebook, true, true, 0);
diff --git a/pan/icons/icon_pan_new.png b/pan/icons/icon_pan_new.png
new file mode 100644
index 0000000..4e9318f
Binary files /dev/null and b/pan/icons/icon_pan_new.png differ
diff --git a/pan/icons/icon_pan_new.xcf b/pan/icons/icon_pan_new.xcf
new file mode 100644
index 0000000..06a686e
Binary files /dev/null and b/pan/icons/icon_pan_new.xcf differ
diff --git a/pan/tasks/encoder.cc b/pan/tasks/encoder.cc
index 2c77f56..763673c 100644
--- a/pan/tasks/encoder.cc
+++ b/pan/tasks/encoder.cc
@@ -37,15 +37,13 @@ extern "C" {
 #include <pan/general/file-util.h>
 #include <pan/general/macros.h>
 #include <pan/general/utf8-utils.h>
-#include <pan/usenet-utils/MersenneTwister.h>
 #include "encoder.h"
 
 using namespace pan;
 
 
 /** generates a unique message-id for a usenet post, consisting of
- *  the Îsec since the Epoch and 2 random numbers from a Mersenne-Twister RNG + the internal part counter
- *  source for RNG: http://www.jwz.org/doc/mid.html
+ *  the current date and time (in seconds resolution) and three random numbers + part count
  */
 void
 Encoder :: generate_unique_id (StringView& mid, int cnt, std::string& s)
@@ -53,14 +51,20 @@ Encoder :: generate_unique_id (StringView& mid, int cnt, std::string& s)
   std::stringstream out;
   struct stat sb;
   struct timeval tv;
+  const time_t now (time(NULL));
+  struct tm local_now = *gmtime (&now);
+  char buf[64];
+  std::strftime (buf, sizeof(buf), "%Y%m%d%H%M%S", &local_now);
   out << "pan$";
   gettimeofday (&tv, NULL);
-  out << std::hex << tv.tv_usec << "$" << std::hex <<
-      mtrand.randInt() << "$" << std::hex << mtrand.randInt() <<std::hex << cnt;
+  out << buf << "$" << std::hex << tv.tv_usec << "$" << std::hex
+      << mtrand.randInt() << "$" << std::hex << mtrand.randInt() << "$"
+      << std::hex << mtrand.randInt() << "$" << std::hex << cnt;
   // delimit
   out<< '@';
   // add domain
   out << mid;
+  //std::cerr << "rng : "<<out.str()<<std::endl;
   s = out.str();
 }
 
@@ -88,6 +92,7 @@ Encoder :: enqueue (TaskUpload                      * task,
                     std::string                     & groups,
                     std::string                     & subject,
                     std::string                     & author,
+                    std::string                     & format,
                     std::string                       global_mid,
                     const TaskUpload::EncodeMode    & enc)
 
@@ -105,12 +110,16 @@ Encoder :: enqueue (TaskUpload                      * task,
   this->global_mid = global_mid;
   this->cache = cache;
   this->article = article;
+  this->format = format;
 
   percent = 0;
   current_file.clear ();
   log_infos.clear();
   log_errors.clear();
 
+  // I don't know if this is bad, but practically, a new seed for every encoder (e.g. task) shouldn't be too much.
+  mtrand.seed();
+
   // gentlemen, start your encod'n...
   _worker_pool.push_work (this, task, false);
 }
@@ -148,9 +157,6 @@ Encoder :: do_work()
       char cachename[4096];
       for (TaskUpload::needed_t::iterator it = needed->begin(); it != needed->end(); ++it, ++cnt)
       {
-
-        cache->get_filename(cachename, Quark(it->second.message_id));
-
         FILE * fp = cache->get_fp_from_mid(it->second.message_id);
         if (!fp)
         {
@@ -165,17 +171,19 @@ Encoder :: do_work()
                                (char*)basename.c_str(),0644, cnt, 4000,
                                0, (char*)groups.c_str(),
                                (char*)author.c_str(),
-                               (char*)subject.c_str(), (char*)s.c_str(), 0);
+                               (char*)subject.c_str(), (char*)s.c_str(), (char*)format.c_str(), 0);
 
-        if (res != UURET_CONT) break;
+        if (fp) fclose(fp);
         cache->finalize(it->second.message_id);
+        if (res != UURET_CONT) break;
+        cache->get_filename(cachename, Quark(it->second.message_id));
         stat (cachename, &sb);
         it->second.bytes  = sb.st_size;
         task->_all_bytes += sb.st_size;
         batch.add_part(cnt, StringView(s), sb.st_size);
       }
 
-      if (res != UURET_OK)
+      if (res != UURET_OK && res != UURET_CONT)
       {
         unlink(cachename); //brute-force
         g_snprintf(buf, bufsz,
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
index e027498..10e888b 100644
--- a/pan/tasks/encoder.h
+++ b/pan/tasks/encoder.h
@@ -42,7 +42,7 @@ extern "C" {
 namespace pan
 {
   /**
-   * Encodes attachments (YEnc) for posting to usenet groups.
+   * Encodes attachments (yEnc) for posting to usenet groups.
    *
    * @author Heinrich Mueller <eddie_v gmx de>
    * @author Calin Culianu <calin ajvar org>
@@ -69,6 +69,7 @@ namespace pan
                     std::string                     & groups,
                     std::string                     & subject,
                     std::string                     & author,
+                    std::string                     & format,
                     std::string                       global_mid,
                     const TaskUpload::EncodeMode    & enc = TaskUpload::YENC);
 
@@ -84,12 +85,11 @@ namespace pan
     private:
 
       friend class TaskUpload;
-      friend class PostUI;
       int parts;
       TaskUpload * task;
       TaskUpload::EncodeMode encode_mode;
       std::string   basename, filename;
-      std::string subject, author, groups, mid;
+      std::string subject, author, groups, mid, format;
       EncodeCache * cache;
       TaskUpload::needed_t* needed;
       std::string global_mid;
diff --git a/pan/tasks/nntp.cc b/pan/tasks/nntp.cc
index 7a833d9..dcacbe8 100644
--- a/pan/tasks/nntp.cc
+++ b/pan/tasks/nntp.cc
@@ -173,6 +173,12 @@ NNTP :: on_socket_response (Socket * sock UNUSED, const StringView& line_in)
 
       case NO_POSTING:
       case POSTING_FAILED:
+        // if we hit a dupe, we silently continue
+        if (line.strstr("435"))
+        {
+          state = CMD_DONE;
+          break;
+        }
       case GROUP_NONEXISTENT:
          state = CMD_FAIL;
          break;
@@ -240,7 +246,7 @@ NNTP :: on_socket_response (Socket * sock UNUSED, const StringView& line_in)
 
    bool more;
    switch (state) {
-      case CMD_FAIL: fire_done_func (ERR_COMMAND, line); more = false; break;
+      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_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...
diff --git a/pan/tasks/nntp.h b/pan/tasks/nntp.h
index 3caada9..3b09d81 100644
--- a/pan/tasks/nntp.h
+++ b/pan/tasks/nntp.h
@@ -59,6 +59,7 @@ namespace
       SEND_ARTICLE_NOW           = 340,
       NO_POSTING                 = 440,
       POSTING_FAILED             = 441,
+      DUPE_ARTICLE               = 435,  // sent additionally to 441
 
       TOO_MANY_CONNECTIONS       = 400,
 
diff --git a/pan/tasks/nzb.cc b/pan/tasks/nzb.cc
index 97ec500..437cf9a 100644
--- a/pan/tasks/nzb.cc
+++ b/pan/tasks/nzb.cc
@@ -50,6 +50,7 @@ namespace
     std::vector<std::string>  groups_str;  // TaskUpload
     TaskUpload::needed_t needed_parts;     // TaskUpload
     std::string domain;                    // TaskUpload
+    std::string queue;
     Article a;
     PartBatch parts;
     tasks_t tasks;
@@ -77,6 +78,7 @@ namespace
       number = 0;
       needed_parts.clear();   // TaskUpload
       domain.clear();         // TaskUpload
+      queue.clear();
     }
   };
 
@@ -106,6 +108,7 @@ namespace
         else if (!strcmp (*k,"subject")) mc.a.subject = *v;
         else if (!strcmp (*k,"server"))  mc.server = *v;
         else if (!strcmp (*k,"domain"))  mc.domain = *v;
+        else if (!strcmp (*k,"queue"))  mc.queue = *v;
       }
     }
 
@@ -184,9 +187,16 @@ 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
+      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,
-                                        mc.domain, std::string(""),
-                                        &mc.needed_parts, 0, TaskUpload::YENC);
+                                        format, &mc.needed_parts, 0, TaskUpload::YENC);
       mc.tasks.push_back (tmp);
     }
   }
@@ -354,6 +364,8 @@ NZB :: nzb_to_xml (std::ostream             & out,
       escaped (out, task->_subject);
       out  << "\" server=\"";
       escaped (out, task->_server.to_string());
+      out  << "\" queue=\"";
+      escaped (out, task->_save_file);
       out  << "\" domain=\"nospam@";
       escaped (out, task->_domain) << "\">\n";
       ++depth;
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index 83e2c3e..c261c2b 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -75,8 +75,6 @@ namespace
     if (pch) domain = domain.substr (NULL, pch);
     domain.trim ();
 
-    std::cerr<<"generate domain : "<<domain<<std::endl;
-
     return domain.to_string();
   }
 }
@@ -89,8 +87,7 @@ TaskUpload :: TaskUpload (const std::string         & filename,
                           const Quark               & server,
                           EncodeCache               & cache,
                           Article                     article,
-                          std::string                 domain,
-                          std::string                 save_file,
+                          UploadInfo                  format,
                           needed_t                  * imported,
                           Progress::Listener        * listener,
                           const TaskUpload::EncodeMode  enc):
@@ -100,15 +97,18 @@ TaskUpload :: TaskUpload (const std::string         & filename,
   _server(server),
   _cache(cache),
   _article(article),
-  _domain(get_domain(StringView(domain))),
-  _save_file(save_file),
   _subject (article.subject.to_string()),
   _author(article.author.to_string()),
   _encoder(0),
   _encoder_has_run (false),
   _encode_mode(enc),
   _lines_per_file(4000),
-  _all_bytes(0)
+  _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);
@@ -137,13 +137,12 @@ TaskUpload :: build_needed_tasks(bool imported)
   foreach_const (Xref, _article.xref, it)
     _groups.insert (it->group);
 
-  Article::mid_sequence_t mids;
   foreach (needed_t, _needed, it)
   {
-    mids.push_back(Quark(it->second.message_id));
+    _mids.push_back(Quark(it->second.message_id));
     _cache.add(Quark(it->second.message_id));
   }
-  _cache.reserve(mids);
+  _cache.reserve(_mids);
   _needed_parts = _needed.size();
 
 }
@@ -240,7 +239,6 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
   switch (health)
   {
     case OK:
-      // save to cache
       increment_step(it->second.bytes);
       _needed.erase (it);
       post_ok = true;
@@ -249,6 +247,7 @@ 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;
   }
@@ -261,10 +260,15 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
       this->stop();
       break;
     case POSTING_FAILED:
-      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;
-      _logfile.push_back(tmp);
+      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;
+        _logfile.push_back(tmp);
+      }
       break;
     case ARTICLE_POSTED_OK:
       tmp.severity = Log :: PAN_SEVERITY_INFO;
@@ -280,8 +284,18 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
                    _basename.c_str(), it->second.partno, _total_parts, response.str);
         tmp.message = buf;
         _logfile.push_back(tmp);
-        g_snprintf(buf,sizeof(buf), _("Posting of file %s succesful: %s"),
+
+        /* get error state for the whole upload: if one part failed, set global status to error */
+        bool error(false);
+        foreach_const (std::deque<Log::Entry>, _logfile, it)
+          error = (it->severity  == Log :: PAN_SEVERITY_ERROR);
+        if (!error)
+          g_snprintf(buf,sizeof(buf), _("Posting of file %s succesful: %s"),
                    _basename.c_str(), response.str);
+        else
+          g_snprintf(buf,sizeof(buf), _("Posting of file %s not completely successful: Check the popup log!"),
+                 _basename.c_str(), response.str);
+
         tmp.message = buf;
         _logfile.push_back(tmp);
         Log::add_entry_list (tmp, _logfile);
@@ -293,6 +307,7 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
       _state.set_need_nntp(nntp->_server);
       break;
     default:
+      this->stop();
       Log::add_entry_list (tmp, _logfile);
       _logfile.clear();
       Log :: add_err_va (_("Posting of file %s not successful: Check the popup log!"),
@@ -338,8 +353,19 @@ TaskUpload :: use_encoder (Encoder* encoder)
     if (i<_groups.size()&& i>0 && _groups.size()>1) groups += ",";
     groups += (*it).to_string();
   }
+
+  /* build format string */
+  std::stringstream format_s;
+  format_s << (_format.comment1 ? _subject : "");
+  format_s << " \"%s\" yEnc "; // will be filled in by uuencode
+  format_s << " (%d/%d) ";     // will be filled in by uuencode
+  std::stringstream counter;
+  counter <<"[" << _queue_pos << "/" << _queue_length << "]";
+  format_s << (_format.counter ? counter.str() : "");
+  std::string format(format_s.str());
+
   _encoder->enqueue (this, &_cache, _article, _filename, _basename,
-                     groups, _subject, _author, _domain, YENC);
+                     groups, _subject, _author, format, _domain, YENC);
   debug ("encoder thread was free, enqueued work");
 }
 
@@ -391,7 +417,7 @@ TaskUpload :: ~TaskUpload ()
   if (_encoder)
       _encoder->cancel_silently();
 
-  _cache.release(_article.get_part_mids());
+  _cache.release(_mids);
   _cache.resize();
 
   if (!_save_file.empty())
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
index 3b3eff8..e9712cd 100644
--- a/pan/tasks/task-upload.h
+++ b/pan/tasks/task-upload.h
@@ -49,6 +49,15 @@ namespace pan
   {
     public:
 
+      struct UploadInfo
+      {
+        bool comment1, counter;
+        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; }
@@ -80,8 +89,7 @@ namespace pan
                    const Quark               & server,
                    EncodeCache               & cache,
                    Article                     article,
-                   std::string                 domain,
-                   std::string                 save_file,
+                   UploadInfo                  format,
                    needed_t                  * imported=0,
                    Progress::Listener        * listener= 0,
                    TaskUpload::EncodeMode enc= YENC);
@@ -130,6 +138,7 @@ namespace pan
       TaskUpload::EncodeMode _encode_mode;
       quarks_t _groups;
       std::string _subject, _author;
+      UploadInfo _format;
       int _total_parts, _needed_parts;
       unsigned long _bytes;
       Mutex mut;
@@ -140,6 +149,9 @@ 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:
       needed_t       _needed;
diff --git a/uulib/uudeview.h b/uulib/uudeview.h
index 258ef37..7f56591 100644
--- a/uulib/uudeview.h
+++ b/uulib/uudeview.h
@@ -237,25 +237,25 @@ int	UUEXPORT UUEncodeToFile		_ANSI_ARGS_((FILE *, char *, int,
 int	UUEXPORT UUE_PrepSingle		_ANSI_ARGS_((FILE *, FILE *,
 						     char *, int,
 						     char *, int,
-						     char *, char *, char*,
+						     char *, char *, char*, char*,
 						     char *, int));
 int	UUEXPORT UUE_PrepPartial	_ANSI_ARGS_((FILE *, FILE *,
 						     char *, int,
 						     char *, int,
 						     int, long, long,
-						     char *, char *, char*, char*, int));
+						     char *, char *, char*, char*, char*, int));
 
 int	UUEXPORT UUE_PrepSingleExt	_ANSI_ARGS_((FILE *, FILE *,
 						     char *, int,
 						     char *, int,
 						     char *, char *,
-						     char *, char *, char*,
+						     char *, char *, char*, char*,
 						     int));
 int	UUEXPORT UUE_PrepPartialExt	_ANSI_ARGS_((FILE *, FILE *,
 						     char *, int,
 						     char *, int,
 						     int, long, long, char *, char*,
-						     char *, char *, char *,
+						     char *, char *, char *,char*,
 						     int));
 #ifdef __cplusplus
 }
diff --git a/uulib/uuencode.c b/uulib/uuencode.c
index e71f582..7053b09 100644
--- a/uulib/uuencode.c
+++ b/uulib/uuencode.c
@@ -1491,13 +1491,13 @@ UUE_PrepSingle (FILE *outfile, FILE *infile,
 		char *infname, int encoding,
 		char *outfname, int filemode,
 		char *destination, char *from,
-		char *subject, char* mid, int isemail)
+		char *subject, char* mid, char* format, int isemail)
 {
   return UUE_PrepSingleExt (outfile, infile,
 			    infname, encoding,
 			    outfname, filemode,
 			    destination, from,
-			    subject, mid, NULL,
+			    subject, mid, NULL, format,
 			    isemail);
 }
 
@@ -1506,7 +1506,7 @@ UUE_PrepSingleExt (FILE *outfile, FILE *infile,
 		   char *infname, int encoding,
 		   char *outfname, int filemode,
 		   char *destination, char *from,
-		   char *subject, char* mid, char *replyto,
+		   char *subject, char* mid, char *replyto, char* format,
 		   int isemail)
 {
   mimemap *miter=mimetable;
@@ -1603,7 +1603,7 @@ UUE_PrepPartial (FILE *outfile, FILE *infile,
 		 char *infname, int encoding,
 		 char *outfname, int filemode,
 		 int partno, long linperfile, long filesize,
-		 char *destination, char *from, char *subject, char* mid,
+		 char *destination, char *from, char *subject, char* mid, char* format,
 		 int isemail)
 {
   return UUE_PrepPartialExt (outfile, infile,
@@ -1611,7 +1611,7 @@ UUE_PrepPartial (FILE *outfile, FILE *infile,
 			     outfname, filemode,
 			     partno, linperfile, filesize,
 			     destination,
-			     from, subject, mid, NULL,
+			     from, subject, mid, NULL, format,
 			     isemail);
 }
 
@@ -1621,7 +1621,7 @@ UUE_PrepPartialExt (FILE *outfile, FILE *infile,
 		    char *outfname, int filemode,
 		    int partno, long linperfile, long filesize,
 		    char *destination,
-		    char *from, char *subject, char* mid, char *replyto,
+		    char *from, char *subject, char* mid, char *replyto, char* format,
 		    int isemail)
 {
   static int numparts, themode;
@@ -1715,7 +1715,7 @@ UUE_PrepPartialExt (FILE *outfile, FILE *infile,
       if (infile==NULL) fclose (theifile);
       return UUE_PrepSingleExt (outfile, infile, infname, encoding,
 				outfname, filemode, destination,
-				from, subject, mid, replyto, isemail);
+				from, subject, mid, replyto, format, isemail);
     }
 
     /*
@@ -1735,16 +1735,15 @@ UUE_PrepPartialExt (FILE *outfile, FILE *infile,
   }
 
 
+  // [subject] "filename" yEnc (partnum/numparts) [size] [part/of]
   if (encoding == YENC_ENCODED) {
     if (partno == 1)
       crc = crc32(0L, Z_NULL, 0);
-    crcptr = &crc;
-    if (subject)
-      sprintf (subline, "\"%s\" - %s (%03d/%03d)", oname, subject,
-	       partno, numparts);
-    else
-      sprintf (subline, "\"%s\" - (%03d/%03d)", oname,
-	       partno, numparts);
+      crcptr = &crc;
+      sprintf (subline, format, oname, partno, numparts);
+//    else
+//      sprintf (subline, "\"%s\" - (%03d/%03d)", oname,
+//	       partno, numparts);
   }
   else {
     if (subject)



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