[pan2: 42/268] bla



commit d9c273c0e4da798995ae0104f165a7f4d53d8faf
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Mon May 30 12:18:42 2011 +0200

    bla

 pan/data-impl/headers.cc  |   10 ++--
 pan/general/file-util.cc  |   49 +++++++++++++-
 pan/general/file-util.h   |    2 +
 pan/gui/gui.cc            |    6 ++
 pan/gui/post-ui.cc        |  171 ++++++++++++++++++++++++++++++++-------------
 pan/gui/post-ui.h         |   19 +++++-
 pan/tasks/decoder.cc      |    4 +-
 pan/tasks/encoder.cc      |    9 +--
 pan/tasks/encoder.h       |    1 +
 pan/tasks/nzb.cc          |   29 ++++----
 pan/tasks/task-article.cc |    4 +-
 pan/tasks/task-upload.cc  |  147 +++++++++++++++++++++++----------------
 pan/tasks/task-upload.h   |   25 ++++---
 uulib/uuencode.c          |    5 +-
 14 files changed, 324 insertions(+), 157 deletions(-)
---
diff --git a/pan/data-impl/headers.cc b/pan/data-impl/headers.cc
index b8d5127..dbe20c3 100644
--- a/pan/data-impl/headers.cc
+++ b/pan/data-impl/headers.cc
@@ -117,7 +117,7 @@ DataImpl :: GroupHeaders :: remove_articles (const quarks_t& mids)
     (*it)->_article = 0;
   _dirty = true;
 }
-  
+
 const DataImpl :: GroupHeaders*
 DataImpl :: get_group_headers (const Quark& group) const
 {
@@ -239,7 +239,7 @@ void
 DataImpl :: load_article (const Quark       & group,
                           Article           * article,
                           const StringView  & references)
-              
+
 {
 #if 0
   std::cerr << LINE_ID << " adding article "
@@ -371,7 +371,7 @@ DataImpl :: get_references (const Quark& group, const Article& a) const
     s.insert (0, v.str, v.len);
     node = node->parent;
   }
-std::cerr << "article " << a.message_id << " references " << s << std::endl;
+//  std::cerr << "article " << a.message_id << " references " << s << std::endl;
   return s;
 }
 #endif
@@ -463,7 +463,7 @@ DataImpl :: load_headers (const DataIO   & data_io,
 
       Xref::targets_t targets;
       std::vector<Xref::Target>& targets_v (targets.get_container());
-        
+
       // each article in this group...
       unsigned int expire_count (0);
       in->getline (line);
@@ -1094,7 +1094,7 @@ DataImpl :: delete_articles (const unique_articles_t& articles)
 
     // remove the articles from our lookup table...
     GroupHeaders * h (get_group_headers (group));
-    if (h) 
+    if (h)
       h->remove_articles (it->second.mids);
   }
 
diff --git a/pan/general/file-util.cc b/pan/general/file-util.cc
index 1a90d89..2d650d6 100644
--- a/pan/general/file-util.cc
+++ b/pan/general/file-util.cc
@@ -31,6 +31,8 @@ extern "C"
 
   #include <glib.h>
   #include <glib/gi18n.h>
+
+  #include <dirent.h>
 }
 
 #include "debug.h"
@@ -54,10 +56,55 @@ file :: get_uulib_path()
   char * pch (g_build_filename (file::get_pan_home().c_str(), "uulib-encode-cache", NULL));
   file :: ensure_dir_exists (pch);
   std::string path (pch);
-  g_free (pch);
+  if (pch) g_free (pch);
   return path;
 }
 
+/// TODO perhaps implement another cache for uulib files ??
+// delete cached files to avoid "disk full" problems
+void
+file :: uulib_cache_clear ()
+{
+  DIR *dp;
+  struct dirent *ep;
+  struct stat st;
+  const char * dir = get_uulib_path().c_str();
+  std::cerr<<"opening dir : "<<dir<<std::endl;
+  dp = opendir (dir);
+  if (dp != NULL)
+  {
+    while (ep = readdir (dp))
+    {
+      stat(ep->d_name, &st);
+      if (S_ISDIR(st.st_mode) == 0) {
+        std::cerr<<"deleting file :"<<ep->d_name<<"\n";
+        unlink(ep->d_name);
+      }
+    }
+    (void) closedir (dp);
+  } else
+    std::cerr<<"error clearing uulib cache!\n";
+}
+
+//  void clear_cached_range (const char* file)
+//  {
+//    DIR *dp;
+//    struct dirent *ep;
+//    struct stat st;
+//    const char * dir = file :: get_uulib_path().c_str();
+//    dp = opendir (dir);
+//    if (dp != NULL)
+//    {
+//      while (ep = readdir (dp))
+//      {
+//        stat(ep->d_name, &st);
+//        if (S_ISDIR(st.st_mode) == 0 && strstr(file,ep->d_name))
+//          unlink(ep->d_name);
+//      }
+//      (void) closedir (dp);
+//    }
+//  }
+
 std::string
 file :: get_pan_home ()
 {
diff --git a/pan/general/file-util.h b/pan/general/file-util.h
index 25bde1c..1d43bf0 100644
--- a/pan/general/file-util.h
+++ b/pan/general/file-util.h
@@ -60,6 +60,8 @@ namespace pan
 
     std::string get_uulib_path();
 
+    void uulib_cache_clear();
+
     /**
      * If the specified directory doesn't exist, Pan tries to create it.
      * @param path
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index bfce0ae..5350434 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -26,6 +26,7 @@ extern "C" {
   #include <sys/types.h> // for chmod
   #include <sys/stat.h> // for chmod
   #include <glib/gi18n.h>
+  #include <dirent.h>
 }
 #include <pan/general/debug.h>
 #include <pan/general/e-util.h>
@@ -184,6 +185,11 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, Prefs& prefs, GroupPr
   _queue_size_button (0),
   _taskbar (0)
 {
+
+  //clear uulib encode cache
+  ///TODO perhaps remember by crc32-ptr and then assign already saved parts??
+//  file :: uulib_cache_clear();
+
   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);
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 4a9300c..18a4ea2 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -2033,8 +2033,42 @@ PostUI :: create_filequeue_tab ()
   return vbox;
 }
 
+void
+PostUI:: on_parts_box_clicked_cb (GtkCellRendererToggle *cell, gchar *path_str, gpointer user_data)
+{
+  PostUI* data(static_cast<PostUI*>(user_data));
+  GtkWidget    * w    = data->parts_store() ;
+  GtkListStore *store = GTK_LIST_STORE(
+                      gtk_tree_view_get_model(GTK_TREE_VIEW(w)));
+  GtkTreeModel * model = gtk_tree_view_get_model(GTK_TREE_VIEW(w));
+  int part(42);
+  GtkTreeIter  iter;
+  GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+  gboolean enabled;
+
+  gtk_tree_model_get_iter (model, &iter, path);
+
+  gtk_tree_model_get (model, &iter, 0, &part, 1, &enabled, -1);
+
+  enabled ^= 1;
+  if (enabled==0)
+    data->upload_ptr()->needed().erase(part);
+  else
+  {
+    TaskUpload::Needed tmp;
+    tmp.partno = part;
+    tmp.partial = true;
+    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_tree_path_free (path);
+  data->update_parts_tab();
+}
+
+
 GtkWidget*
-PostUI :: create_parts_tab (TaskUpload* ptr)
+PostUI :: create_parts_tab ()
 {
 
   const GtkAttachOptions fill ((GtkAttachOptions)(GTK_FILL));
@@ -2047,69 +2081,83 @@ PostUI :: create_parts_tab (TaskUpload* ptr)
   GtkWidget *t = gtk_table_new (8, 2, false);
   gtk_table_set_col_spacings (GTK_TABLE(t), PAD);
 
-  ++row;  //empty line
+  ++row;  //1
   l = gtk_label_new (NULL);
   gtk_table_attach (GTK_TABLE(t), l, 0, 2, row, row+1, fe, fill, 0, 0);
 
-  ++row;  //1
+  ++row;  //2
   g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Filename"));
   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), "%s", ptr->basename().c_str());
+  g_snprintf (buf, sizeof(buf), "%s", _upload_ptr->basename().c_str());
   l = gtk_label_new (buf);
   gtk_misc_set_alignment (GTK_MISC(l), 0.5f, 0.5f);
   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;  //2
+  ++row;  //3
   g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Subject Line"));
   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), "%s", ptr->subject().c_str());
+  g_snprintf (buf, sizeof(buf), "%s", _upload_ptr->subject().c_str());
   l = gtk_label_new (buf);
   gtk_misc_set_alignment (GTK_MISC(l), 0.5f, 0.5f);
   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;  //3
+  ++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);
-  //todo make generic!!
+  ///TODO make generic!!
   g_snprintf (buf, sizeof(buf), "%d", 4000);
   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 Lines per File"));
   gtk_table_attach (GTK_TABLE(t), l, 1, 2, row, row+1, fe, fill, 0, 0);
 
-  //4
+  ++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);
 
 
-  //5
+  //7
   ++row;
-  gtk_table_attach (GTK_TABLE(gtk_hseparator_new()), l, 0, 2, row, row+1, fe, fill, 0, 0);
 
-
-  // 6
+  // 8
   //treeview for parts list
-  w = _parts_store = gtk_tree_view_new_with_model (GTK_TREE_MODEL(gtk_list_store_new (2, G_TYPE_BOOLEAN, G_TYPE_STRING)));
+  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)));
 
   // add columns
-  renderer = gtk_cell_renderer_toggle_new();
-  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 0,
-                          (_("Part No.")),renderer,"active", 1,NULL);
   renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 0,
+                          (_("No. ")),renderer,"text", 0,NULL);
+  renderer = gtk_cell_renderer_toggle_new();
+  g_signal_connect (G_OBJECT(renderer), "toggled", G_CALLBACK(on_parts_box_clicked_cb), this);
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 1,
-                          (_("Filename")),renderer,"text", 1,NULL);
+                          (_("Enable/Disable")),renderer,"active", 1,NULL);
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 2,
+                          (_("Filename")),renderer,"text", 2,NULL);
 
   //set hint and selection
   gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(w),TRUE);
@@ -2120,14 +2168,10 @@ PostUI :: create_parts_tab (TaskUpload* ptr)
   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), _parts_store);
-  ++row;                                              //todo
-  gtk_table_attach (GTK_TABLE(t), w, 0, 2, row, row+2, fe, fill, 0, 0);
-
-  //7: OK and close Buttons
   ++row;
+  gtk_table_attach (GTK_TABLE(t), w, 0, 2, row, row+1, fe, fill, 0, 0);
 
   return t;
-
 }
 
 GtkWidget*
@@ -2249,7 +2293,10 @@ PostUI :: remove_files (void)
   tasks_set tasks = get_selected_files();
   tasks_set::iterator nit;
   for (nit = tasks.begin(); nit != tasks.end();nit, ++nit)
-    _file_queue_tasks.erase(*nit);
+    {
+       delete (*nit);
+      _file_queue_tasks.erase(*nit);
+    }
   update_filequeue_tab();
 }
 
@@ -2339,18 +2386,21 @@ PostUI :: ~PostUI ()
   g_object_unref (G_OBJECT(_message));
 }
 
+
+
 void
 PostUI :: select_parts ()
 {
 
-  TaskUpload* ptr(0);
   tasks_set set(get_selected_files());
-  ptr = *set.begin();
+  _upload_ptr = *set.begin();
+
+  if (!_upload_ptr) return;
+
+  _total_parts = (int) (((long)_upload_ptr->get_byte_count() + (4000*128-1)) / (4000*128));
+
   GtkWidget * w;
   GtkTreeIter iter;
-  const int total = (int) (((long)ptr->get_byte_count() + (4000*128-1)) / (4000*128));
-
-  std::cerr<<total<<std::endl;
 
   w = _part_select = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   g_signal_connect (_part_select, "delete-event", G_CALLBACK(delete_parts_cb), this);
@@ -2358,7 +2408,7 @@ PostUI :: select_parts ()
   gtk_window_set_title (GTK_WINDOW(w), _("Select Parts"));
   int x,h;
   x = 350;
-  h = 450;
+  h = 650;
   gtk_window_set_default_size (GTK_WINDOW(w), x, h);
 
   // populate the window
@@ -2366,25 +2416,34 @@ PostUI :: select_parts ()
   gtk_container_add (GTK_CONTAINER(w), vbox);
 
   GtkWidget * notebook = gtk_notebook_new ();
-  gtk_notebook_append_page (GTK_NOTEBOOK(notebook), create_parts_tab(ptr), gtk_label_new_with_mnemonic(_("_Parts")));
-  gtk_notebook_append_page (GTK_NOTEBOOK(notebook), create_log_tab(),   gtk_label_new_with_mnemonic(_("_Log")));
+  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);
 
-  //populate parts tab
-  GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(_parts_store)));
-  for (int i=1;i<=total+100;++i)
+  gtk_widget_show_all (w);
+  update_parts_tab();
+
+}
+
+void
+PostUI :: update_parts_tab()
+{
+  GtkWidget    * w    = _parts_store ;
+  GtkListStore *store = GTK_LIST_STORE(
+                        gtk_tree_view_get_model(GTK_TREE_VIEW(w)));
+  GtkTreeIter   iter;
+  gtk_list_store_clear(store);
+  gboolean res(FALSE);
+
+  for (int i=1;i<=_total_parts;++i)
   {
     gtk_list_store_append (store, &iter);
+    res = (_upload_ptr->_needed.find(i) != _upload_ptr->_needed.end()) ? TRUE : FALSE;
     gtk_list_store_set (store, &iter,
-                      0, true,
-                      1, ptr->basename().c_str(), -1);
+                      0, i,
+                      1, res,
+                      2, _upload_ptr->basename().c_str(), -1);
   }
-
-    gtk_widget_show_all (w);
-
-
-//  update_parts_tab();
-
 }
 
 PostUI :: PostUI (GtkWindow    * parent,
@@ -2414,7 +2473,10 @@ PostUI :: PostUI (GtkWindow    * parent,
   _charset (DEFAULT_CHARSET),
   _group_entry_changed_id (0),
   _group_entry_changed_idle_tag (0),
-  _file_queue_empty(true)
+  _file_queue_empty(true),
+  _upload_ptr(0),
+  _total_parts(0),
+  _upload_cursor(0)
 {
   g_assert (profiles.has_profiles());
   g_return_if_fail (message != 0);
@@ -2534,13 +2596,22 @@ PostUI :: prompt_user_for_queueable_files (tasks_set& queue, GtkWindow * parent,
         groups.insert(groupname);
     }
 
-    for (; cur; cur = cur->next)
+    int i(0);
+    for (; cur; cur = cur->next, ++i)
 		{
-		  TaskUpload::needed_t tmp; //todo
-      _file_queue_tasks.insert(		  new TaskUpload(std::string((const char*)cur->data),
-                                     profile.posting_server,
-                                     groups, subject, author, tmp, 0,
-                                     TaskUpload::YENC));
+		  TaskUpload* tmp = new TaskUpload(std::string((const char*)cur->data),
+                               profile.posting_server,
+                               groups, subject, author, 0,
+                               TaskUpload::YENC);
+		  _file_queue_tasks.insert(tmp);
+      TaskUpload::Needed tmp2;
+      const int parts = (int) (((long)tmp->get_byte_count() + (4000*128-1)) / (4000*128));
+      for (int j=1; j<=parts; ++j)
+      {
+        tmp2.partial = true;
+        tmp2.partno = j;
+        tmp->needed().insert(needed_p(j,tmp2));
+      }
 		}
   	g_slist_free (tmp_list);
   }
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index ded6d83..1973d68 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -35,7 +35,7 @@ namespace pan
   class Queue;
 
 
-  typedef std::multiset<TaskUpload*> tasks_set;
+  typedef std::set<TaskUpload*> tasks_set;
 
   /**
    * Dialog for posting new messages Pan's GTK GUI.
@@ -58,6 +58,7 @@ namespace pan
     public:
       GtkWidget * root() { return _root; }
       GtkWidget * part_select() { return _part_select; }
+      GtkWidget * parts_store() { return _parts_store; }
       void rot13_selection ();
       void wrap_body ();
       void spawn_editor ();
@@ -73,6 +74,7 @@ namespace pan
       void set_wrap_mode (bool wrap);
       void set_always_run_editor (bool);
       void update_filequeue_tab();
+      void update_parts_tab();
 
       //popup action entries
       void remove_files ();
@@ -158,8 +160,15 @@ namespace pan
       GtkWidget* create_main_tab ();
       GtkWidget* create_extras_tab ();
       GtkWidget* create_filequeue_tab ();
-      GtkWidget* create_parts_tab (TaskUpload* ptr);
+      GtkWidget* create_parts_tab ();
       GtkWidget* create_log_tab ();
+      TaskUpload* _upload_ptr;
+      int _total_parts;
+      typedef std::map<int, TaskUpload::Needed> needed_t;
+      typedef std::pair<int, TaskUpload::Needed> needed_p;
+      typedef std::vector<needed_t> needed_v;
+      needed_v _needed_v;
+      int _upload_cursor;
 
     private:
       std::string utf8ize (const StringView&) const;
@@ -194,6 +203,12 @@ namespace pan
       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);
+
+    public:
+      TaskUpload* upload_ptr() { return _upload_ptr; }
+      int cursor() { return _upload_cursor; }
+
   };
 }
 
diff --git a/pan/tasks/decoder.cc b/pan/tasks/decoder.cc
index 5e8bfa8..2295b2f 100644
--- a/pan/tasks/decoder.cc
+++ b/pan/tasks/decoder.cc
@@ -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 f50aa31..57c5fa1 100644
--- a/pan/tasks/encoder.cc
+++ b/pan/tasks/encoder.cc
@@ -100,7 +100,6 @@ Encoder :: do_work()
     if (((res = UUInitialize())) != UURET_OK)
     {
       log_errors.push_back(_("Error initializing uulib")); // log error
-      this->cancel();
     } else {
       UUSetMsgCallback (this, uu_log);
       UUSetBusyCallback (this, uu_busy_poll, 100);
@@ -109,13 +108,6 @@ Encoder :: do_work()
       outfile = fopen(buf,"wb");
       while (1) {
 
-        // skip not wanted parts of binary file
-//        if (parts->end() != parts->find(cnt))
-//        {
-//          ++cnt;
-//          res = UURET_CONT;
-//          goto _end;
-//        }
         // 4000 lines SHOULD be OK for ANY nntp server ...
         res = UUE_PrepPartial (outfile, NULL, (char*)filename.c_str(),YENC_ENCODED,
                                (char*)basename.c_str(),0644, cnt, 4000,
@@ -154,6 +146,7 @@ void
 Encoder :: uu_log (void* data, char* message, int severity)
 {
   Encoder *self = static_cast<Encoder *>(data);
+  if (self->was_cancelled()) return;
   char * pch (g_locale_to_utf8 (message, -1, 0, 0, 0));
 
   if (severity >= UUMSG_WARNING)
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
index 5808963..e31afa4 100644
--- a/pan/tasks/encoder.h
+++ b/pan/tasks/encoder.h
@@ -79,6 +79,7 @@ namespace pan
 
       std::set<int>* parts;
       friend class TaskUpload;
+      friend class PostUI;
       TaskUpload * task;
       TaskUpload::EncodeMode encode_mode;
       std::string   filename;
diff --git a/pan/tasks/nzb.cc b/pan/tasks/nzb.cc
index d8c382e..8eb5d32 100644
--- a/pan/tasks/nzb.cc
+++ b/pan/tasks/nzb.cc
@@ -51,6 +51,7 @@ namespace
     TaskUpload::needed_t needed_parts;       // TaskUpload
     Article a;
     Quark posting_server;
+    bool encoded;   // encoder was done already
     PartBatch parts;
     tasks_t tasks;
     ArticleCache& cache;
@@ -103,7 +104,6 @@ namespace
         else if (!strcmp (*k,"subject")) mc.a.subject = *v;
         else if (!strcmp (*k,"server"))  mc.posting_server = Quark(*v);
       }
-      std::cerr<<"upload begin tag\n";
     }
 
     else if (!strcmp (element_name, "segment")) {
@@ -122,9 +122,7 @@ namespace
              if (!strcmp (*k,"bytes"))  mc.bytes = strtoul (*v,0,10);
         else if (!strcmp (*k,"number")) mc.number = atoi (*v);
       }
-      std::cerr<<"part begin tag\n";
     }
-
   }
 
   // Called for close tags </foo>
@@ -155,8 +153,9 @@ namespace
       n.bytes = mc.bytes;
       n.filename = mc.text;
       n.partno = mc.number;
-      mc.needed_parts.push_back(n);
-      std::cerr<<"part end tag\n";
+      n.partial = false;
+      std::pair<int,TaskUpload::Needed> tmp(mc.number,n);
+      mc.needed_parts.insert(tmp);
     }
 
     else if (!strcmp(element_name,"path"))
@@ -181,8 +180,12 @@ namespace
     else if (!strcmp (element_name, "upload"))
     {
       debug("adding taskupload from nzb.\n");
-      mc.tasks.push_back (new TaskUpload (mc.path, const_cast<const Quark&>(mc.posting_server),
-                          mc.groups, mc.a.subject.to_string(), mc.a.author.to_string(), mc.needed_parts, 0, TaskUpload::YENC));
+      TaskUpload* tmp = new TaskUpload (mc.path, const_cast<const Quark&>(mc.posting_server),
+                          mc.groups, mc.a.subject.to_string(), mc.a.author.to_string(), 0, TaskUpload::YENC);
+       //update needed struct
+      foreach (TaskUpload::needed_t, mc.needed_parts, it)
+        tmp->needed().insert(*it);
+      mc.tasks.push_back (tmp);
     }
   }
 
@@ -346,11 +349,7 @@ NZB :: nzb_to_xml (std::ostream             & out,
       out  << "\" subject=\"";
       escaped (out, task->_subject);
       out  << "\" server=\"";
-      escaped (out, task->_server.to_string());
-      out  << "\" encoded=\"";
-      char buf[3];
-      g_snprintf(buf,3,"%d",(int)task->_encoder_has_run);
-      escaped (out, StringView(buf)) << "\">\n";
+      escaped (out, task->_server.to_string()) << "\">\n";
       ++depth;
       out << indent(depth)
           << "<path>" << task->_filename << "</path>\n";
@@ -367,9 +366,9 @@ NZB :: nzb_to_xml (std::ostream             & out,
 
       foreach_const (TaskUpload::needed_t, task->_needed, it)
         out << indent(depth)
-            << "<part" << " bytes=\"" << (*it).bytes << '"'
-                       << " number=\"" << (*it).partno << '"'
-                       << ">" << (*it).filename<< "</part>\n";
+            << "<part" << " bytes=\"" << (*it).second.bytes << '"'
+                       << " number=\"" << (*it).second.partno << '"'
+                       << ">" << (*it).second.filename<< "</part>\n";
       --depth;
       out  << indent(depth) << "</parts>\n";
       --depth;
diff --git a/pan/tasks/task-article.cc b/pan/tasks/task-article.cc
index 3c77f7b..e529d52 100644
--- a/pan/tasks/task-article.cc
+++ b/pan/tasks/task-article.cc
@@ -132,7 +132,7 @@ TaskArticle :: ~TaskArticle ()
   // ensure our on_worker_done() doesn't get called after we're dead
   if (_decoder)
       _decoder->cancel_silently();
-  
+
   _cache.release (_article.get_part_mids());
 }
 
@@ -291,7 +291,7 @@ TaskArticle :: on_nntp_done  (NNTP             * nntp,
       }
       break;
   }
-  
+
   update_work (nntp);
   check_in (nntp, health);
 }
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index 0728fe9..0f62983 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -27,7 +27,7 @@
 #include <sstream>
 #include <iostream>
 #include <fstream>
-
+#include <cstdio>
 extern "C" {
 #include <glib/gi18n.h>
 }
@@ -44,14 +44,31 @@ using namespace pan;
 
 namespace
 {
-  std::string get_description (const char* name, bool enc)
+  std::string get_description (const char* name)
   {
     char buf[1024];
-    if (!enc)
-      snprintf (buf, sizeof(buf), _("Uploading %s"), name);
-    else
-      snprintf (buf, sizeof(buf), _("Encoding %s"), name);
-    return std::string (buf);
+    char * freeme = g_path_get_basename(name);
+    snprintf (buf, sizeof(buf), _("Uploading %s"), freeme);
+    g_free(freeme);
+    return buf;
+  }
+
+  std::string get_basename(const char* f)
+  {
+    char buf[1024];
+    char * freeme = g_path_get_basename(f);
+    snprintf (buf, sizeof(buf), _("%s"), freeme);
+    g_free(freeme);
+    return buf;
+  }
+}
+
+
+namespace
+{
+  void delete_cache(const TaskUpload::Needed& n)
+  {
+    unlink(n.filename.c_str());
   }
 }
 
@@ -64,20 +81,18 @@ TaskUpload :: TaskUpload ( const std::string         & filename,
                            quarks_t                  & groups,
                            std::string                 subject,
                            std::string                 author,
-                           needed_t                  & todo,
                            Progress::Listener        * listener,
                            const TaskUpload::EncodeMode  enc):
-  Task ("UPLOAD", get_description(filename.c_str(), true)),
+  Task ("UPLOAD", get_description(filename.c_str())),
   _filename(filename),
-  _basename (std::string(g_path_get_basename(filename.c_str()))),
+  _basename (g_path_get_basename(filename.c_str())),
   _server(server),
   _groups(groups),
   _subject (subject),
   _author(author),
   _encoder(0),
   _encoder_has_run (false),
-  _encode_mode(enc),
-  _extern(todo)
+  _encode_mode(enc)
 {
   if (listener != 0)
     add_listener (listener);
@@ -85,7 +100,6 @@ TaskUpload :: TaskUpload ( const std::string         & filename,
   struct stat sb;
   stat(filename.c_str(),&sb);
   _bytes = sb.st_size;
-
   update_work ();
 }
 
@@ -95,7 +109,7 @@ TaskUpload :: update_work (NNTP* checkin_pending)
 
   int working(0);
   foreach (needed_t, _needed, nit) {
-    Needed& n (*nit);
+    Needed& n (nit->second);
     if (n.nntp && n.nntp!=checkin_pending)
       ++working;
   }
@@ -126,8 +140,8 @@ TaskUpload :: use_nntp (NNTP * nntp)
 
   Needed * needed (0);
   for (needed_t::iterator it(_needed.begin()), end(_needed.end()); !needed && it!=end; ++it)
-    if (it->nntp==0)
-      needed = &*it;
+    if (it->second.nntp==0)
+      needed = &it->second;
 
   if (!needed)
   {
@@ -159,16 +173,6 @@ TaskUpload :: on_nntp_line  (NNTP               * nntp,
                               const StringView   & line_in)
 {}
 
-
-// delete cached files to avoid "disk full" problems
-namespace
-{
-  void delete_cache(const TaskUpload::Needed& n)
-  {
-    unlink(n.filename.c_str());
-  }
-}
-
 void
 TaskUpload :: on_nntp_done  (NNTP             * nntp,
                              Health             health,
@@ -177,10 +181,20 @@ TaskUpload :: on_nntp_done  (NNTP             * nntp,
 
   needed_t::iterator it;
   for (it=_needed.begin(); it!=_needed.end(); ++it)
-    if (it->nntp == nntp)
+    if (it->second.nntp == nntp)
       break;
 
-  bool post_ok(false);
+  switch (health)
+  {
+    case OK:
+      break;
+    /* if the connection was aborted with SIGPIPE, let this error silently by and
+     * let GIOSocket code handle this */
+    case ERR_NETWORK:
+      std::cerr<<"err network!\n";
+      it->second.reset();
+      goto _end;
+  }
 
   switch (atoi(response.str))
   {
@@ -192,7 +206,12 @@ TaskUpload :: on_nntp_done  (NNTP             * nntp,
       Log :: add_err_va (_("Posting of file %s failed: %s"), _basename.c_str(), response.str);
       break;
     case ARTICLE_POSTED_OK:
-      post_ok = true;
+      delete_cache(it->second);
+      _needed.erase (it);
+      increment_step(1);
+      if (_needed.empty())
+        Log :: add_info_va(_("Posting of file %s succesful: %s"),
+               _basename.c_str(), response.str);
       break;
     case TOO_MANY_CONNECTIONS:
       // lockout for 120 secs, but try
@@ -203,23 +222,8 @@ TaskUpload :: on_nntp_done  (NNTP             * nntp,
       break;
   }
 
-  switch (health)
-  {
-    case OK:
-      delete_cache(*it);
-      _needed.erase (it);
-        if (_needed.empty() && post_ok)
-        Log :: add_info_va(_("Posting of file %s succesful: %s"),
-               _basename.c_str(), response.str);
-      break;
-
-    case ERR_NETWORK:
-      _state.set_need_nntp(nntp->_server);
-      break;
-  }
-
-  update_work();
-  increment_step(1);
+  _end:
+  update_work(nntp);
   check_in (nntp, health);
 
 }
@@ -233,7 +237,7 @@ TaskUpload :: get_bytes_remaining () const
 {
   unsigned long bytes (0);
   foreach_const (needed_t, _needed, it)
-    bytes += it->bytes;
+    bytes += it->second.bytes;
   return bytes;
 }
 
@@ -263,8 +267,8 @@ TaskUpload :: use_encoder (Encoder* encoder)
 void
 TaskUpload :: stop ()
 {
-  if (_encoder)
-      _encoder->cancel();
+//  if (_encoder)
+//      _encoder->cancel();
 }
 
 // called in the main thread by WorkerPool
@@ -286,12 +290,20 @@ TaskUpload :: on_worker_done (bool cancelled)
     foreach_const(Encoder::log_t, _encoder->log_infos, it)
       Log :: add_info(it->c_str());
 
+    int num_errors = _encoder->log_severe.size() +
+                     _encoder->log_errors.size();
+
     if (!_encoder->log_errors.empty())
       set_error (_encoder->log_errors.front());
 
-    if (!_encoder->log_severe.empty())
-      _state.set_health (ERR_LOCAL);
-    else {
+    if (num_errors>0)
+    {
+      /* stop state if encoder has encountered errors */
+      _state.set_completed ();
+      set_finished(ERR_LOCAL);
+    }
+    else
+    {
       set_step (100);
       _encoder_has_run = true;
       _total_parts = _encoder->total_parts;
@@ -304,20 +316,37 @@ TaskUpload :: on_worker_done (bool cancelled)
       char buf[2048];
       struct stat sb;
 
-        for (int i=1; i<=_total_parts; ++i)
+      int total(0);
+      /* not found: skip, we don't need that part
+         found: if (partial) then assign the needed values
+      */
+      for (int i=1; i<=_total_parts; ++i)
+      {
+        needed_t::iterator it = _needed.find(i);
+        if (it == _needed.end())
+          continue;
+        else if (it->second.partial)
         {
           n.partno = i;
           g_snprintf(buf,sizeof(buf),"%s/%s.%d",
-                     file::get_uulib_path().c_str(),
-                     _basename.c_str(), i);
+                   file::get_uulib_path().c_str(),
+                   _basename.c_str(), i);
           n.filename = buf;
           stat(buf, &sb);
           n.bytes = sb.st_size;
-          _needed.push_back (n);
         }
-
-      init_steps (_total_parts);
-      set_step (0);
+          ++total;
+      }
+
+      if (total==0)
+      {
+        _state.set_completed();
+        set_finished(OK);
+      } else
+      {
+        init_steps (_total_parts);
+        set_step (total);
+      }
     }
   }
 
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
index 7a7b1fd..edd309c 100644
--- a/pan/tasks/task-upload.h
+++ b/pan/tasks/task-upload.h
@@ -53,10 +53,12 @@ namespace pan
         unsigned long bytes;
         int partno;
         NNTP* nntp;
-        Needed (): nntp(0) {}
+        bool partial;
+        Needed (): nntp(0), bytes(0) , partial(false) {}
+        void reset() { nntp = 0; }
       };
 
-      typedef std::deque<Needed> needed_t;
+      typedef std::map<int, Needed> needed_t;
 
       enum EncodeMode
       {
@@ -71,7 +73,6 @@ namespace pan
                    quarks_t                  & groups,
                    std::string                 subject,
                    std::string                 author,
-                   needed_t                  & todo,
                    Progress::Listener        * listener= 0,
                    TaskUpload::EncodeMode enc= YENC);
       virtual ~TaskUpload ();
@@ -83,14 +84,15 @@ namespace pan
       const std::string& filename()  { return  _filename; }
       const std::string& subject ()  { return  _subject;  }
       unsigned long get_byte_count() { return _bytes;     }
+      needed_t& needed()             { return _needed;    }
 
-      /** only call this for tasks in the NEED_DECODE state
-       * attempts to acquire the saver thread and start saving
-       * returns false if failed or true if the save process started
+      /** only call this for tasks in the NEED_ENCODE state
+       * attempts to acquire the encoder thread and start encoding
+       * returns false if failed or true if the encoding process started
        * (intended to be used with the Queue class). If true is returned,
-       * a side-effect is that the task is now in the DECODING state.
+       * a side-effect is that the task is now in the ENCODING state.
        */
-      virtual void use_encoder (Encoder*);
+    virtual void use_encoder (Encoder*);
 
     private: // Task subclass
       virtual void use_nntp (NNTP * nntp);
@@ -107,6 +109,7 @@ namespace pan
 
     private: // implementation
       friend class Encoder;
+      friend class PostUI;
       friend class NZB;
       Encoder * _encoder;
       bool _encoder_has_run;
@@ -118,13 +121,13 @@ namespace pan
       int _total_parts; // filled in by encoder
       unsigned long _bytes;
       Mutex mut;
+      int _pos_in_queue;
+      char* _tmp;   // for g_path etc...
 
     private:
       needed_t       _needed;
-      needed_t       _extern;
-      std::set<int>  _parts;
-
       void update_work (NNTP * checkin_pending = 0);
+
   };
 
 // from mime-utils.cc
diff --git a/uulib/uuencode.c b/uulib/uuencode.c
index 2d985a2..b57e389 100644
--- a/uulib/uuencode.c
+++ b/uulib/uuencode.c
@@ -1779,12 +1779,13 @@ UUE_PrepPartialExt (FILE *outfile, FILE *infile,
 
   _FP_free (subline);
 
+  /* pan change (imhotep): these could lead to SIGSEV, so I changed them to check for NULL pointers */
   if (infile==NULL) {
-    if (res != UURET_OK) {
+    if (res != UURET_OK && theifile) {
       fclose (theifile);
       return res;
     }
-    if (feof (theifile)) {
+    if (feof (theifile) && theifile) {
       fclose (theifile);
       return UURET_OK;
     }



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