[pan2/testing: 171/279] theading is now: (original post) +-- reply with body +-- file 1 +-- file 2 . . .



commit cf38fefbfc3a0678e27a75dba38363c0544f1148
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Mon Jul 18 09:57:00 2011 +0200

    theading is now:
    (original post)
    +-- reply with body
        +-- file 1
        +-- file 2
        .
        .
        .
        +-- last file
    for all the other files the message body is discarded.

 pan.cbp                     |    2 +
 pan/gui/gui.cc              |   16 ++--
 pan/gui/post-ui.cc          |   98 +++++++++++++----------
 pan/gui/post-ui.h           |    6 +-
 pan/gui/prefs-ui.cc         |   19 +++--
 pan/tasks/Makefile.am       |    2 +
 pan/tasks/encoder.cc        |   10 +--
 pan/tasks/encoder.h         |    4 +-
 pan/tasks/task-multipost.cc |  181 +++++++++++++++++++++++++++++++++++++++++++
 pan/tasks/task-multipost.h  |  122 +++++++++++++++++++++++++++++
 pan/tasks/task-upload.cc    |   83 +++++++++++--------
 pan/tasks/task-upload.h     |   28 +++++--
 uulib/uuencode.c            |    2 -
 13 files changed, 455 insertions(+), 118 deletions(-)
---
diff --git a/pan.cbp b/pan.cbp
index 3c1517b..4c546b9 100644
--- a/pan.cbp
+++ b/pan.cbp
@@ -227,6 +227,8 @@
 		<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-multipost.cc" />
+		<Unit filename="pan/tasks/task-multipost.h" />
 		<Unit filename="pan/tasks/task-post.cc" />
 		<Unit filename="pan/tasks/task-post.h" />
 		<Unit filename="pan/tasks/task-upload.cc" />
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index 48e7bfa..cc22eb3 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -170,9 +170,9 @@ namespace
   };
 
   static GtkTargetEntry target_list[] = {
-          { "STRING",     0, TARGET_STRING },
-          { "text/plain", 0, TARGET_STRING },
-          { "application/x-rootwindow-drop", 0, TARGET_ROOTWIN }
+          { const_cast<char*>("STRING"),     0, TARGET_STRING },
+          { const_cast<char*>("text/plain"), 0, TARGET_STRING },
+          { const_cast<char*>("application/x-rootwindow-drop"), 0, TARGET_ROOTWIN }
   };
 }
 
@@ -276,11 +276,11 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, EncodeCache& encode_c
   g_signal_connect (w, "clicked", G_CALLBACK(show_task_window_cb), this);
 
   // drag and drop for message-ids
-//  gtk_drag_dest_set(w,GTK_DEST_DEFAULT_ALL,target_list,3,GDK_ACTION_COPY);
-//  gtk_drag_dest_add_text_targets(w);
-//  gtk_drag_dest_add_uri_targets(w);
-//  g_signal_connect (w, "drag-data-received", G_CALLBACK(dragged_rcvd), this);
-//  g_signal_connect (w, "drag-drop", G_CALLBACK (dragged), this);
+//  gtk_drag_dest_set(_workarea_bin,GTK_DEST_DEFAULT_ALL,target_list,3,GDK_ACTION_COPY);
+//  gtk_drag_dest_add_text_targets(_workarea_bin);
+//  gtk_drag_dest_add_uri_targets(_workarea_bin);
+//  g_signal_connect (_workarea_bin, "drag-data-received", G_CALLBACK(dragged_rcvd), this);
+//  g_signal_connect (_workarea_bin, "drag-drop", G_CALLBACK (dragged), this);
 
   gtk_container_add (GTK_CONTAINER(w), _queue_size_label);
   frame = gtk_frame_new (NULL);
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 20d5c02..1b71f9c 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -927,7 +927,10 @@ PostUI :: maybe_mail_message (GMimeMessage * message)
 void
 PostUI :: on_progress_finished (Progress&, int status) // posting finished
 {
-  bool close(false);
+
+  std::cerr<<"status "<<status<<std::endl;
+  if (status==-1) { --_running_uploads; return; }
+
   if (_file_queue_empty)
   {
     _post_task->remove_listener (this);
@@ -939,23 +942,24 @@ PostUI :: on_progress_finished (Progress&, int status) // posting finished
     gtk_widget_destroy (_post_dialog);
   } else
   {
+    --_running_uploads;
+    int no = status;
+    TaskUpload * ptr = _upload_queue[no];
+
     if (!_save_file.empty())
     {
       mut.lock();
-        int no = status;
-        TaskUpload * ptr = _upload_queue[no];
         if (ptr) NZB :: upload_list_to_xml_file (_out, ptr->_upload_list);
-        --_running_uploads;
         if (_running_uploads==0 )
         {
           _out << "</nzb>\n";
           _out.close();
-          close = true;
         }
       mut.unlock();
-      if (close) close_window(true);
     }
+
   }
+  if (_running_uploads==0) close_window(true);
 }
 
 void
@@ -1074,7 +1078,6 @@ PostUI :: maybe_post_message (GMimeMessage * message)
     _upload_queue.get_all_tasks(tasks);
     int cnt(0);
     char buf[2048];
-    int lpf = _prefs.get_int("upload-option-bpf",1024*512);
     struct stat sb;
     _running_uploads = tasks.size();
 
@@ -1085,9 +1088,33 @@ PostUI :: maybe_post_message (GMimeMessage * message)
       d = !profile.fqdn.empty()
       ? GNKSA::generate_message_id (profile.fqdn)
       : GNKSA::generate_message_id_from_email_address (profile.address);
-    StringView domain(d);
+    StringView d2(d);
+    StringView domain;
+      const char * pch = d2.strchr ('@');
+      if (pch != NULL)
+         domain = d2.substr (pch+1, NULL);
+      else
+        domain = d2;
 
-    /// TODO maybe update tasks' msg headers here ???
+    std::string last_mid;
+    std::string first_mid;
+
+    // dummy taskupload for master article without attachment, dbg!!
+    const Profile profile (get_current_profile ());
+    std::string out;
+    generate_unique_id(domain, 1,out);
+    first_mid = out;
+    Article a(tasks[0]->_article);
+
+    TaskUpload::UploadInfo f;
+    f.total=1;
+    TaskUpload::Needed n;
+    n.mid = out;
+    TaskUpload * tmp = new TaskUpload("",profile.posting_server,_cache,a,f,new_message_from_ui(UPLOADING));
+    tmp->_needed.insert(std::pair<int, TaskUpload::Needed>(1,n));
+    tmp->_queue_pos = -1;
+    _queue.add_task (tmp, Queue::BOTTOM);
+    tmp->add_listener(this);
 
     /* init taskupload variables before adding the tasks to the queue for processing */
     foreach (PostUI::tasks_t, tasks, it)
@@ -1099,39 +1126,24 @@ PostUI :: maybe_post_message (GMimeMessage * message)
       TaskUpload::Needed n;
 
       // generate domain for rng numbers
-      int total = get_total_parts(t->_filename.c_str(), t);
-      StringView d;
-      const char * pch = domain.strchr ('@');
-      if (pch != NULL)
-         d = domain.substr (pch+1, NULL);
-      else
-        d = domain;
-
-      // generate rng number for message-ids
-      // compose subject lines
-      // build needed struct for upload
-      // set queue position for listeners
-      // start queue and initialize listeners
-      // NOTE: the postui class won't be destroyed after that, because we need some data from it
-      // (for example for saving the nzb file). it will be hidden and destroyed on destruction of
-      // the last Taskupload task.
-      // (perhaps this could be changed if we added a listener for this in gui.cc and let post-ui.cc die) (??)
-
-      std::string last_mid;
+      int total = get_total_parts(t->_filename.c_str());
+      std::cerr<<"total of "<<t->_filename<<" : "<<total<<std::endl;
 
       foreach (std::set<int>, t->_wanted, pit)
       {
         if (custom_mid)
         {
             std::string out;
-            generate_unique_id(d, *pit,out);
+            generate_unique_id(domain, *pit,out);
             n.mid = out;
+            if (first_mid.empty()) first_mid = out;
         }
 
         g_snprintf(buf,sizeof(buf),"%s.%d", basename, *pit);
         n.message_id = buf;
         n.partno = *pit;
         n.last_mid = last_mid;
+        t->_first_mid = first_mid;
         last_mid = n.mid;
         t->_needed.insert(std::pair<int,TaskUpload::Needed>(*pit,n));
       }
@@ -1141,8 +1153,6 @@ PostUI :: maybe_post_message (GMimeMessage * message)
 
       _queue.add_task (*it, Queue::BOTTOM);
       t->add_listener(this);
-
-      _upload_listeners.push_back(t);
     }
     gtk_widget_hide (_root); // hide the main window, we still need the class' data
   }
@@ -2717,7 +2727,7 @@ PostUI :: select_encode (GtkAction* a)
     foreach(tasks_t, tasks, it)
     {
       const char* f = (*it)->_filename.c_str();
-      int total(get_total_parts (f,*it));
+      int total(get_total_parts (f));
 
       (*it)->_encode_mode = tmp;
       (*it)->_total_parts = total;
@@ -2730,11 +2740,12 @@ PostUI :: select_encode (GtkAction* a)
 }
 
 int
-PostUI :: get_total_parts(const char* file, TaskUpload* it)
+PostUI :: get_total_parts(const char* file)
 {
     struct stat sb;
     stat (file,&sb);
-    return std::max(1,(int)std::ceil((double)sb.st_size / (double)_prefs.get_int("upload-option-bpf",1024*512)));
+    int max (std::max(1,(int)std::ceil((double)sb.st_size / (1024*_prefs.get_int("upload-option-kbpf",512)))));
+    return max;
 }
 
 void
@@ -2791,7 +2802,7 @@ PostUI :: select_parts ()
 
   if (!_upload_ptr) return;
 
-  int new_parts = get_total_parts(_upload_ptr->_filename.c_str(), _upload_ptr);
+  int new_parts = get_total_parts(_upload_ptr->_filename.c_str());
   if (_total_parts != new_parts)
   {
     _upload_ptr->_wanted.clear();
@@ -2909,9 +2920,12 @@ PostUI :: PostUI (GtkWindow    * parent,
   _body_changed_id(0),
   _body_changed_idle_tag(0),
   _filequeue_eventbox (0),
-  _filequeue_label (0)
+  _filequeue_label (0),
+  _multipart(g_mime_multipart_new_with_subtype("mixed"))
 {
 
+  g_mime_multipart_set_boundary(_multipart,"$pan_multipart_gmime_message$");
+
   rng.seed();
 
   _upload_queue.add_listener (this);
@@ -3029,12 +3043,9 @@ PostUI :: prompt_user_for_queueable_files (GtkWindow * parent, const Prefs& pref
         gtk_widget_destroy (w);
 
         TaskUpload::UploadInfo ui;
-        // not used for now...
-        ui.comment1 = _prefs.get_flag("upload-queue-append-subject-enabled",false);
         // query lines per file value
-        ui.bpf = _prefs.get_int("upload-option-bpf",1024*512);
+        ui.kbpf = _prefs.get_int("upload-option-kbpf",512);
 
-        GSList * cur = g_slist_nth (tmp_list,0);
         std::string author;
         profile.get_from_header(author);
         std::string subject(utf8ize (g_mime_message_get_subject (tmp)));
@@ -3049,6 +3060,7 @@ PostUI :: prompt_user_for_queueable_files (GtkWindow * parent, const Prefs& pref
               groups.insert(Quark(groupname));
         }
 
+        GSList * cur = g_slist_nth (tmp_list,0);
         for (; cur; cur = cur->next)
         {
           GMimeMessage * msg (new_message_from_ui (UPLOADING));
@@ -3062,11 +3074,11 @@ PostUI :: prompt_user_for_queueable_files (GtkWindow * parent, const Prefs& pref
 
           struct stat sb;
           // yEnc encoding is the default, user can change that with popup-menu
-          stat ((const char*)cur->data,&sb);
-          ui.total = std::max(1,(int)std::ceil((double)sb.st_size / (double)_prefs.get_int("upload-option-bpf",1024*512)));
+          ui.total = get_total_parts((const char*)cur->data);
+          std::cerr<<"ui total "<<ui.total<<" "<<(const char*)cur->data<<" "<<get_total_parts((const char*)cur->data)<<std::endl;
           TaskUpload* tmp = new TaskUpload(std::string((const char*)cur->data),
                             profile.posting_server, _cache,
-                            a, ui, msg ,0, TaskUpload::YENC);
+                            a, ui, msg ,0, TaskUpload::YENC, TaskUpload::BULK );
 
           // insert wanted parts to upload
           for (int i=1;i<=ui.total; ++i)
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index 753f1ff..b67867e 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -112,7 +112,7 @@ namespace pan
       void set_message (GMimeMessage*);
 
     private:
-      virtual void on_progress_finished (Progress&, int status);
+      virtual void on_progress_finished (Progress&, int status=OK);
       virtual void on_progress_error (Progress&, const StringView&);
 
       virtual void on_progress_step (Progress&, int p) {}
@@ -150,7 +150,6 @@ namespace pan
       std::string _current_signature;
       GtkWidget * _post_dialog;
       TaskPost * _post_task;
-      std::vector<TaskUpload*> _upload_listeners;
       typedef std::map<std::string, std::string> str2str_t;
       str2str_t _hidden_headers;
       str2str_t _profile_headers;
@@ -163,6 +162,7 @@ namespace pan
       int _total_parts;
       std::string _save_file;
       MTRand rng;
+      GMimeMultipart * _multipart;
 
     private:
       friend class UploadQueue;
@@ -246,7 +246,7 @@ namespace pan
 
       void generate_unique_id (StringView& mid, int cnt, std::string& s);
 
-      int get_total_parts(const char* file, TaskUpload* it);
+      int get_total_parts(const char* file);
 
     private:
       guint _draft_autosave_id;
diff --git a/pan/gui/prefs-ui.cc b/pan/gui/prefs-ui.cc
index 479f71b..d9fbc2c 100644
--- a/pan/gui/prefs-ui.cc
+++ b/pan/gui/prefs-ui.cc
@@ -622,18 +622,19 @@ PrefsDialog :: PrefsDialog (Prefs& prefs, GtkWindow* parent):
 
   row = 0;
   t = HIG :: workarea_create ();
-  HIG :: workarea_add_section_title (t, &row, _("Upload Subject Line Appearance"));
+  HIG :: workarea_add_section_title (t, &row, _("Encoding Options"));
   HIG :: workarea_add_section_spacer (t, row, 4);
-  w = new_check_button (_("Append Subject to all Posts"), "upload-queue-append-subject-enabled", false, prefs);
-  HIG :: workarea_add_wide_control (t, &row, w);
-  HIG :: workarea_add_section_title (t, &row, _("Upload Subject Line Appearance"));
-  HIG :: workarea_add_section_spacer (t, row, 4);
-  // 256 mb blocks max, 512 kb min
-  w = new_spin_button ("upload-option-bpf", 5000, 1024*1024*256, prefs);
-  l = gtk_label_new(_("Default Bytes per File (for yEnc Encoder)"));
+  // 16 MiB blocks max, 512 kb min
+  w = new_spin_button ("upload-option-kbpf", 512, 1024*16, prefs);
+  l = gtk_label_new(_("Default KB per File (for Encoder)"));
   gtk_misc_set_alignment (GTK_MISC(l), 0.0, 0.5);
-  gtk_label_set_mnemonic_widget(GTK_LABEL(l), w);
   HIG::workarea_add_row (t, &row, w, l);
+
+//  HIG::workarea_add_section_divider (t, &row);
+//  HIG :: workarea_add_section_title (t, &row, _("Attachment Options (Bulk Uploads)"));
+//  w = new_check_button (_("Single master reply/followup with body, attachments are replies"), "upload-option-reply-multi", 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/tasks/Makefile.am b/pan/tasks/Makefile.am
index 9e3bbdd..5626290 100644
--- a/pan/tasks/Makefile.am
+++ b/pan/tasks/Makefile.am
@@ -12,6 +12,7 @@ libtasks_a_SOURCES = \
   task-post.cc \
   task-xover.cc \
   task-upload.cc \
+  task-multipost.cc \
   nntp.cc \
   nzb.cc \
   queue.cc \
@@ -34,6 +35,7 @@ noinst_HEADERS = \
   task-groups.h \
   task-post.h \
   task-upload.h \
+  task-multipost.h \
   task-weak-ordering.h \
   task-xover.h \
   nntp.h  \
diff --git a/pan/tasks/encoder.cc b/pan/tasks/encoder.cc
index bedfac1..1e17282 100644
--- a/pan/tasks/encoder.cc
+++ b/pan/tasks/encoder.cc
@@ -66,7 +66,7 @@ Encoder :: enqueue (TaskUpload                      * task,
                     std::string                     & filename,
                     std::string                     & basename,
                     std::string                     & subject,
-                    int                               bpf,
+                    int                               kbpf,
                     const TaskUpload::EncodeMode      enc)
 
 {
@@ -79,7 +79,7 @@ Encoder :: enqueue (TaskUpload                      * task,
   this->needed = &task->_needed;
   this->cache = cache;
   this->article = article;
-  this->bpf = bpf;
+  this->kbpf = kbpf;
   this->subject = subject;
 
   percent = 0;
@@ -150,7 +150,7 @@ Encoder :: do_work()
         continue;
       }
 
-      res = UUEncodePartial_byFSize (fp, NULL, (char*)filename.c_str(), enc , (char*)basename.c_str(), NULL, 0644, cnt, bpf ,&crc);
+      res = UUEncodePartial_byFSize (fp, NULL, (char*)filename.c_str(), enc , (char*)basename.c_str(), 0, 0, cnt, kbpf*1024 ,&crc);
 
       if (fp) fclose(fp);
 _no_encode:
@@ -177,13 +177,9 @@ _no_encode:
       log_errors.push_back(buf); // log error
     } else
       task->_upload_list.push_back(tmp);
-
   UUCleanUp ();
-
   }
-
   disable_progress_update();
-
 }
 
 /***
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
index 6f962cd..d0992ef 100644
--- a/pan/tasks/encoder.h
+++ b/pan/tasks/encoder.h
@@ -66,7 +66,7 @@ namespace pan
                     std::string                     & filename,
                     std::string                     & basename,
                     std::string                     & subject,
-                    int                               bpf,
+                    int                               kbpf,
                     const TaskUpload::EncodeMode      enc = TaskUpload::YENC);
 
     public:
@@ -85,7 +85,7 @@ namespace pan
       TaskUpload * task;
       TaskUpload::EncodeMode encode_mode;
       std::string   basename, filename, subject;
-      int bpf;
+      int kbpf;
       EncodeCache * cache;
       TaskUpload::needed_t * needed;
       Article * article;
diff --git a/pan/tasks/task-multipost.cc b/pan/tasks/task-multipost.cc
new file mode 100644
index 0000000..cfd8f87
--- /dev/null
+++ b/pan/tasks/task-multipost.cc
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2007  Charles Kerr <charles rebelbase com>
+ *
+ * This File:
+ * Copyright (C) 2007 Charles Kerr <charles rebelbase com>
+ * Copyright (C) 2007 Calin Culianu <calin ajvar org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <config.h>
+#include <algorithm>
+#include <cassert>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <cstdio>
+
+#include <pan/general/debug.h>
+#include <pan/general/file-util.h>
+#include <pan/general/log.h>
+#include <pan/general/macros.h>
+#include <pan/usenet-utils/mime-utils.h>
+#include <pan/usenet-utils/gnksa.h>
+#include "task-multipost.h"
+#include "nzb.h"
+
+using namespace pan;
+
+namespace
+{
+  std::string get_description (const char* name)
+  {
+    char buf[4096];
+    char * freeme = g_path_get_basename(name);
+    snprintf (buf, sizeof(buf), _("Uploading %s"), freeme);
+    g_free(freeme);
+    return buf;
+  }
+
+  std::string g_get_basename(const char* f)
+  {
+    char buf[4096];
+    char * freeme = g_path_get_basename(f);
+    snprintf (buf, sizeof(buf), "%s", freeme);
+    g_free(freeme);
+    return buf;
+  }
+}
+
+/***
+****
+***/
+
+TaskMultiPost :: TaskMultiPost (const std::string   & filename,
+                          const Quark               & server,
+                          Article                     article,
+                          GMimeMessage *              msg,
+                          Progress::Listener        * listener):
+  Task ("UPLOAD", get_description(filename.c_str())),
+  _filename(filename),
+  _basename (g_get_basename(filename.c_str())),
+  _server(server),
+  _article(article),
+  _subject (article.subject.to_string()),
+  _author(article.author.to_string()),
+  _msg (msg)
+{
+
+
+//  struct stat sb;
+//  stat(filename.c_str(),&sb);
+//  _bytes = sb.st_size;
+
+}
+
+void
+TaskMultiPost :: build_needed_tasks()
+{
+
+  foreach (needed_t, _needed, it)
+  {
+    _mids.push_back(Quark(it->second.message_id));
+  }
+
+}
+
+void
+TaskMultiPost :: update_work (NNTP* checkin_pending)
+{
+
+  int working(0);
+  foreach (needed_t, _needed, nit)
+  {
+    TaskUpload::Needed& n (nit->second);
+    if (n.nntp && n.nntp!=checkin_pending)
+      ++working;
+  }
+
+  /* only need encode if mode is NOT plain */
+  if (working)
+  {
+    _state.set_working();
+  }
+  else if (!working)
+  {
+    _state.set_need_nntp(_server);
+  }
+  else if (_needed.empty())
+  {
+    _state.set_completed();
+    set_finished(OK);
+  }
+}
+
+
+void
+TaskMultiPost :: use_nntp (NNTP * nntp)
+{
+  nntp->post(StringView(""), this);
+
+  update_work ();
+}
+
+/***
+****
+***/
+
+void
+TaskMultiPost :: on_nntp_line (NNTP * nntp,
+                              const StringView & line_in) {}
+
+void
+TaskMultiPost :: on_nntp_done (NNTP * nntp,
+                             Health health,
+                             const StringView & response)
+{
+
+  update_work(nntp);
+  check_in (nntp, health);
+
+}
+
+/***
+****
+***/
+
+unsigned long
+TaskMultiPost :: get_bytes_remaining () const
+{
+  unsigned long bytes (0);
+  foreach_const (needed_t, _needed, it)
+    bytes += (unsigned long)it->second.bytes;
+  return bytes;
+}
+
+
+void
+TaskMultiPost :: stop ()
+{
+}
+
+
+TaskMultiPost :: ~TaskMultiPost ()
+{
+
+
+}
diff --git a/pan/tasks/task-multipost.h b/pan/tasks/task-multipost.h
new file mode 100644
index 0000000..b17c276
--- /dev/null
+++ b/pan/tasks/task-multipost.h
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2006  Charles Kerr <charles rebelbase com>
+ *
+ * This file
+ * Copyright (C) 2007 Charles Kerr <charles rebelbase com>
+ * Copyright (C) 2007 Calin Culianu <calin ajvar org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _TaskMultiPost_h_
+#define _TaskMultiPost_h_
+
+#include <pan/general/locking.h>
+#include <pan/data/article.h>
+#include <pan/data/data.h>
+#include <pan/general/log.h>
+#include <pan/data/xref.h>
+#include <pan/tasks/nntp.h>
+#include <pan/tasks/task.h>
+#include <pan/tasks/task-upload.h>
+
+extern "C" {
+  #define PROTOTYPES
+  #include <uulib/uudeview.h>
+  #include <glib/gi18n.h>
+};
+
+#include <set>
+
+namespace pan
+{
+  /**
+   * Task for uploading binary data to usenet
+   * @ingroup tasks
+   */
+  class TaskMultiPost: public Task,
+                    private NNTP::Listener
+
+  {
+    public:
+
+      const Article& get_article ()  { return _article; }
+
+      typedef std::vector<Quark> mid_sequence_t;
+
+      typedef std::map<int, TaskUpload::Needed> needed_t;
+
+      // life cycle
+      TaskMultiPost ( const std::string         & filename,
+                      const Quark               & server,
+                      Article                     article,
+                      GMimeMessage *              msg,
+                      Progress::Listener        * listener= 0);
+
+      virtual ~TaskMultiPost ();
+
+    public: // Task subclass
+      unsigned long get_bytes_remaining () const;
+      void stop ();
+      const std::string& get_basename()  { return  _basename; }
+
+      /** 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 ENCODING state.
+       */
+    private: // Task subclass
+      virtual void use_nntp (NNTP * nntp);
+
+    private: // NNTP::Listener subclass
+      virtual void on_nntp_line  (NNTP*, const StringView&);
+      virtual void on_nntp_done  (NNTP*, Health, const StringView&);
+
+
+    protected:
+      Quark _server;
+
+    private: // implementation
+      friend class PostUI;
+      friend class Queue;
+
+      std::string _filename;
+      std::string _basename;
+      std::string _subject, _master_subject, _author;
+      std::string _save_file;
+      int _total_parts, _needed_parts;
+      unsigned long _bytes;
+      Article _article;
+      unsigned long _all_bytes;
+
+      Article::mid_sequence_t _mids;
+      TaskUpload::needed_t _needed;
+
+      void update_work (NNTP * checkin_pending = 0);
+
+    public:
+      needed_t& needed() { return _needed; }
+      void build_needed_tasks();
+
+    private:
+      std::set<int> _wanted;
+      GMimeMessage * _msg;
+
+  };
+}
+
+#endif
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index c4937ad..6d16951 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -28,9 +28,7 @@
 #include <iostream>
 #include <fstream>
 #include <cstdio>
-extern "C" {
-#include <glib/gi18n.h>
-}
+
 #include <pan/general/debug.h>
 #include <pan/general/file-util.h>
 #include <pan/general/log.h>
@@ -76,7 +74,8 @@ TaskUpload :: TaskUpload (const std::string         & filename,
                           UploadInfo                  format,
                           GMimeMessage *              msg,
                           Progress::Listener        * listener,
-                          const TaskUpload::EncodeMode  enc):
+                          const TaskUpload::EncodeMode  enc,
+                          const TaskUpload::AttachMode  att):
   Task ("UPLOAD", get_description(filename.c_str())),
   _filename(filename),
   _basename (g_get_basename(filename.c_str())),
@@ -89,23 +88,23 @@ TaskUpload :: TaskUpload (const std::string         & filename,
   _encoder_has_run (false),
   _encode_mode(enc),
   _all_bytes(0),
-  _bpf(format.bpf),
+  _kbpf(format.kbpf),
   _queue_pos(0),
   _msg (msg),
   _total_parts(format.total),
   _save_file(format.save_file),
-  _first(true)
+  _first(true),
+  _att_mode(att)
 {
 
-
   const char * tmp (g_mime_object_get_header ((GMimeObject *)_msg, "References"));
   if (tmp) _references = std::string(tmp);
 
   struct stat sb;
   stat(filename.c_str(),&sb);
   _bytes = sb.st_size;
-  _state.set_paused();
 
+  _state.set_paused();
 }
 
 namespace
@@ -125,7 +124,6 @@ namespace
 void
 TaskUpload :: build_needed_tasks()
 {
-
   foreach (needed_t, _needed, it)
   {
     _mids.push_back(Quark(it->second.message_id));
@@ -150,8 +148,13 @@ TaskUpload :: update_work (NNTP* checkin_pending)
       ++working;
   }
 
+  if (_queue_pos == -1)
+  {
+    _state.set_need_nntp(_server);
+  }
+
   /* only need encode if mode is NOT plain */
-  if (!_encoder_has_run)
+  if (!_encoder_has_run && !_encoder && _queue_pos != -1)
   {
     _state.set_need_encoder();
   }
@@ -161,9 +164,7 @@ TaskUpload :: update_work (NNTP* checkin_pending)
   }
   else if ((_encoder_has_run && !_needed.empty()))
   {
-//    _state.set_completed();
-//    set_finished(_queue_pos);
-    _state.set_need_nntp(_server);
+      _state.set_need_nntp(_server);
   }
   else if (_needed.empty())
   {
@@ -172,17 +173,6 @@ TaskUpload :: update_work (NNTP* checkin_pending)
   }
 }
 
-namespace
-{
-  void mod_refs (GMimeMessage* msg, std::string& refs, std::string& mid)
-  {
-    if (mid.empty()) return ; // do nothing if no new mids are added
-    char buf[4096];
-    g_snprintf(buf,sizeof(buf), "%s <%s>", refs.c_str(), mid.c_str());
-    g_mime_object_set_header ((GMimeObject *) msg, "References", buf);
-  }
-}
-
 void
 TaskUpload :: prepend_headers(GMimeMessage* msg, TaskUpload::Needed * n, std::string& d)
 {
@@ -193,24 +183,34 @@ TaskUpload :: prepend_headers(GMimeMessage* msg, TaskUpload::Needed * n, std::st
 
     //modify subject
     char buf[4096];
-    g_mime_message_set_subject (msg, build_subject_line (buf, 4096, _subject, _basename, n->partno, _total_parts, _encode_mode));
+    if (_queue_pos != -1)
+      g_mime_message_set_subject (msg, build_subject_line (buf, 4096, _subject, _basename, n->partno, _total_parts, _encode_mode));
 
     //modify references header
-    mod_refs (msg, _references,  n->last_mid);
+    std::string mids(_references);
+    mids += " <" + _first_mid + "> ";
+    if (_first_mid != n->last_mid && !_first)  mids += "<" + n->last_mid + ">";
+    g_mime_object_set_header ((GMimeObject *) msg, "References", mids.c_str());
 
-    //extract whole message with headers (for first message, others only post headers + encoded data)
     char * all;
-    if (_first) all = g_mime_object_to_string ((GMimeObject *) msg);
+    if (_first && _queue_pos==-1)
+      all = g_mime_object_to_string ((GMimeObject *) msg);
     else
       all = g_mime_object_get_headers ((GMimeObject *) msg);
     out << all << "\n";
     out << d;
     d = out.str();
 
-    if (_first) g_free(all);
+    if (_first && _queue_pos==0) g_free(all);
     if (_first) _first = !_first;
 }
 
+GMimeObject *
+TaskUpload :: get_body(Needed* n)
+{
+  return 0;
+}
+
 void
 TaskUpload :: use_nntp (NNTP * nntp)
 {
@@ -258,22 +258,29 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
                              Health health,
                              const StringView & response)
 {
+
   char buf[4096];
   Log::Entry tmp;
   tmp.date = time(NULL);
   tmp.is_child = true;
+  bool found(false);
 
   needed_t::iterator it;
   for (it=_needed.begin(); it!=_needed.end(); ++it)
-    if (it->second.nntp == nntp)
+    if (it->second.nntp == nntp) {
+      found=true;
       break;
+    }
+
+  if (!found) return;
 
   bool post_ok(false);
   switch (health)
   {
     case OK:
-      increment_step(it->second.bytes);
-      _needed.erase (it);
+      std::cerr<<"OK "<<_queue_pos<<std::endl;
+//      increment_step(it->second.bytes);
+//      _needed.erase (it);
       post_ok = true;
       break;
     case ERR_NETWORK:
@@ -372,6 +379,9 @@ TaskUpload :: get_bytes_remaining () const
 void
 TaskUpload :: use_encoder (Encoder* encoder)
 {
+
+  if (!encoder) return;
+
   if (_state._work != NEED_ENCODER)
     check_in (encoder);
 
@@ -379,7 +389,7 @@ TaskUpload :: use_encoder (Encoder* encoder)
   init_steps(100);
   _state.set_working();
 
-  _encoder->enqueue (this, &_cache, &_article, _filename, _basename, _master_subject, _bpf, _encode_mode);
+  _encoder->enqueue (this, &_cache, &_article, _filename, _basename, _master_subject, _kbpf, _encode_mode);
   debug ("encoder thread was free, enqueued work");
 }
 
@@ -437,6 +447,9 @@ TaskUpload :: ~TaskUpload ()
       _encoder->cancel_silently();
 
   g_object_unref (G_OBJECT(_msg));
-//  _cache.release(_mids);
-//  _cache.resize();
+  if (_att_mode==BULK && _queue_pos != -1)
+  {
+    _cache.release(_mids);
+    _cache.resize();
+  }
 }
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
index b260002..adbf3b0 100644
--- a/pan/tasks/task-upload.h
+++ b/pan/tasks/task-upload.h
@@ -35,8 +35,10 @@
 #include <pan/tasks/task.h>
 
 extern "C" {
-#define PROTOTYPES
-#include <uulib/uudeview.h>
+  #define PROTOTYPES
+  #include <uulib/uudeview.h>
+  #include <gmime/gmime.h>
+  #include <glib/gi18n.h>
 };
 
 #include <set>
@@ -57,10 +59,9 @@ namespace pan
 
       struct UploadInfo
       {
-        bool comment1;
         std::string  save_file;
         std::string  mid;
-        int bpf;
+        int kbpf;
         int total;
       };
 
@@ -89,15 +90,22 @@ namespace pan
         YENC=2,
       };
 
+      enum AttachMode
+      {
+        BULK,
+        INLINE
+      };
+
       // life cycle
       TaskUpload ( const std::string         & filename,
                    const Quark               & server,
                    EncodeCache               & cache,
                    Article                     article,
                    UploadInfo                  format,
-                   GMimeMessage *              msg,
+                   GMimeMessage *              msg=0,
                    Progress::Listener        * listener= 0,
-                   EncodeMode enc= YENC);
+                   const EncodeMode enc= YENC,
+                   const AttachMode att= BULK);
 
       virtual ~TaskUpload ();
 
@@ -158,7 +166,8 @@ namespace pan
       bool _encoder_has_run;
       std::string _filename;
       std::string _basename;
-      TaskUpload::EncodeMode _encode_mode;
+      EncodeMode _encode_mode;
+      AttachMode _att_mode;
       std::string _subject, _master_subject, _author;
       std::string _save_file;
       int _total_parts, _needed_parts;
@@ -170,9 +179,10 @@ namespace pan
       std::vector<Article*> _upload_list;
       Article::mid_sequence_t _mids;
       int _queue_pos;
-      int _bpf;
+      int _kbpf;
       needed_t _needed;
       std::string _references; // original references, not to be touched!
+      std::string _first_mid;
 
       void update_work (NNTP * checkin_pending = 0);
 
@@ -186,9 +196,9 @@ namespace pan
       std::set<int> _wanted;
       GMimeMessage * _msg;
       void prepend_headers(GMimeMessage* msg, TaskUpload::Needed * n, std::string& d);
+      GMimeObject * get_body(Needed* n);
       void add_reference_to_list(std::string s);
       bool _first;
-
   };
 }
 
diff --git a/uulib/uuencode.c b/uulib/uuencode.c
index 5b4d1c6..4eebc69 100644
--- a/uulib/uuencode.c
+++ b/uulib/uuencode.c
@@ -1737,8 +1737,6 @@ UUEncodePartial_byFSize (FILE *outfile, FILE *infile,
         }
     }
 
-  printf("numparts %d\n", numparts);
-
   if (encoding == YENC_ENCODED)
     {
       pcrc = crc32(0L, Z_NULL, 0);



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