[pan2: 250/268] Merge branch 'master' into test2



commit e1e087c6393000df43157e0c2c5078af52403646
Merge: 4c64147 c07626c
Author: Heinrich MÃller <henmull src gnome org>
Date:   Fri Dec 23 17:20:14 2011 +0100

    Merge branch 'master' into test2
    
    Conflicts:
    	configure.in
    	pan/data-impl/data-impl.cc
    	pan/data-impl/data-impl.h
    	pan/data-impl/headers.cc
    	pan/data/data.cc
    	pan/data/data.h
    	pan/gui/Makefile.am
    	pan/gui/actions.cc
    	pan/gui/group-prefs-dialog.cc
    	pan/gui/gui.cc
    	pan/gui/gui.h
    	pan/gui/header-pane.cc
    	pan/gui/header-pane.h
    	pan/gui/pan-ui.h
    	pan/gui/post-ui.h
    	pan/gui/profiles-dialog.cc
    	pan/tasks/task-article.h
    	pan/usenet-utils/mime-utils.cc
    	pan/usenet-utils/mime-utils.h
    	po/de.po
    	po/es.po
    	po/sl.po

 pan/data/data.h                   |    4 +
 pan/general/utf8-utils.cc         |    2 +-
 pan/gui/Makefile.am               |    4 +-
 pan/gui/actions.cc                |    1 +
 pan/gui/body-pane.cc              |   16 +
 pan/gui/body-pane.h               |    1 +
 pan/gui/group-prefs-dialog.cc     |  120 +-
 pan/gui/group-prefs-dialog.h      |    1 +
 pan/gui/gui.cc                    |   55 +-
 pan/gui/header-pane.cc            |   40 +-
 pan/gui/header-pane.h             |    1 +
 pan/gui/post-ui.cc                |   48 +-
 pan/gui/post-ui.h                 |    1 +
 pan/gui/prefs-ui.cc               |   15 +-
 pan/gui/prefs.cc                  |    1 +
 pan/gui/prefs.h                   |    1 +
 pan/tasks/task-article.cc         |   19 +-
 pan/tasks/task-article.h          |   13 +
 pan/usenet-utils/gnksa-test.cc    |   11 +-
 pan/usenet-utils/gnksa.cc         |   62 +-
 pan/usenet-utils/message-check.cc |    1 +
 pan/usenet-utils/mime-utils.cc    |   99 +-
 pan/usenet-utils/mime-utils.h     |   17 +-
 po/de.po                          | 1756 ++++--------
 po/sl.po                          | 5839 +++++++++++++++++--------------------
 25 files changed, 3726 insertions(+), 4402 deletions(-)
---
diff --cc pan/data/data.h
index 3ba0db5,94354d1..d0ab7cf
--- a/pan/data/data.h
+++ b/pan/data/data.h
@@@ -317,11 -249,11 +317,15 @@@ namespace pa
  
        typedef std::set<Listener*> listeners_t;
        listeners_t _listeners;
+ 
+     public:
+ 
+       virtual void fire_article_flag_changed (const Article* a, const Quark& group);
  
 +    public:
 +
 +      virtual void fire_article_flag_changed (articles_t& a, const Quark& group);
 +
      /*****************************************************************
      ***
      ***  GROUPS
diff --cc pan/gui/Makefile.am
index 0314f05,c36242d..958374a
--- a/pan/gui/Makefile.am
+++ b/pan/gui/Makefile.am
@@@ -98,8 -93,8 +98,8 @@@ WINRCOBJ 
  endif
  
  pan_SOURCES = gui.cc pan.cc $(WINRC)
- pan_LDADD = ./libpangui.a $(WINRCOBJ) ../data-impl/libpandata.a ../tasks/libtasks.a ../data/libdata.a ../usenet-utils/libusenetutils.a ../general/libgeneralutils.a \
-             ../../uulib/libuu.a @GTKSPELL_LIBS@ @GTK_LIBS@ @GMIME_LIBS@ @GLIB_LIBS@ @GNUTLS_LIBS@ @LIBNOTIFY_LIBS@ @LIBGNOME_KEYRING_1_LIBS@
 -pan_LDADD = ./libpangui.a $(WINRCOBJ) -lenchant ../data-impl/libpandata.a ../tasks/libtasks.a ../data/libdata.a ../usenet-utils/libusenetutils.a ../general/libgeneralutils.a ../../uulib/libuu.a @GTKSPELL_LIBS@ @GTK_LIBS@ @GMIME_LIBS@ @GLIB_LIBS@
 -
++pan_LDADD = ./libpangui.a $(WINRCOBJ) -lenchant ../data-impl/libpandata.a ../tasks/libtasks.a ../data/libdata.a ../usenet-utils/libusenetutils.a ../general/libgeneralutils.a ../../uulib/libuu.a \
++		@GTKSPELL_LIBS@ @GTK_LIBS@ @GMIME_LIBS@ @GLIB_LIBS@ @GNUTLS_LIBS@ @LIBNOTIFY_LIBS@ @LIBGNOME_KEYRING_1_LIBS@
  if HAVE_WIN32
  pan_LDFLAGS = -mwindows
  endif
diff --cc pan/gui/body-pane.h
index 0bdda2f,dd3d110..96918fd
--- a/pan/gui/body-pane.h
+++ b/pan/gui/body-pane.h
@@@ -106,9 -83,10 +106,10 @@@ namespace pa
        bool read_more_or_less (bool more);
        char* body_to_utf8 (GMimePart*);
        void set_text_from_message (GMimeMessage*);
 -      void append_part (GMimeObject*, GtkAllocation*);
 +      void append_part (GMimeObject*, GMimeObject*, GtkAllocation*);
        static gboolean expander_activated_idle (gpointer self);
        static void expander_activated_cb (GtkExpander*, gpointer self);
+       static void verbose_clicked_cb (GtkWidget*, GdkEvent  *event, gpointer self_gpointer);
        static void foreach_part_cb (GMimeObject*, GMimeObject*, gpointer self);
        static void text_size_allocated (GtkWidget*, GtkAllocation*, gpointer);
        static gboolean text_size_allocated_idle_cb (gpointer p);
diff --cc pan/gui/group-prefs-dialog.cc
index cabf364,ee47e02..ccc3e59
--- a/pan/gui/group-prefs-dialog.cc
+++ b/pan/gui/group-prefs-dialog.cc
@@@ -61,10 -106,22 +108,25 @@@ GroupPrefsDialog :: save_from_gui (
  
    // save path...
    const char * pch (file_entry_get (_save_path));
 -  _group_prefs.set_string (_group, "default-group-save-path", pch);
 +  foreach_const (quarks_v, _groups, it)
 +    _group_prefs.set_string (*it, "default-group-save-path", pch);
 +
 +  _group_prefs.save () ;
+ 
+   // spellchecker language
+ #ifdef HAVE_GTKSPELL
+   GtkTreeIter iter;
+   if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX(_spellchecker_language), &iter))
+ 		return;
+ 
+   gchar* name(0);
+ 	GtkTreeModel* model = gtk_combo_box_get_model (GTK_COMBO_BOX(_spellchecker_language));
+ 	gtk_tree_model_get (model, &iter, 0, &name, -1);
+ 
+   if (name) _group_prefs.set_string (_group, "spellcheck-language", name);
+   g_free(name);
+ #endif
+ 
  }
  
  void
@@@ -110,16 -167,61 +172,62 @@@ namespac
  
      return w;
    }
+ 
+   GtkWidget*
+   create_spellcheck_combo_box ( const Quark      & group,
+                                 const GroupPrefs & group_prefs)
+   {
+     GtkWidget * w;
+ 
+ #ifdef HAVE_GTKSPELL
+     init_spell();
+     deinit_spell();
+ 
+     GtkTreeModel *model;
+     GtkListStore * store = gtk_list_store_new (1, G_TYPE_STRING);
+     GtkTreeIter iter, storeit;
+     bool valid(false);
+ 
+ 
+     std::string lang = group_prefs.get_string(group, "spellcheck-language","");
+ 
+     while (l.langs)
+     {
+       gchar* data = (gchar*)l.langs->data;
+       if (data)
+       {
+         gtk_list_store_append (store, &iter);
+         gtk_list_store_set (store, &iter, 0, data, -1);
+         if (g_strcmp0 ((const char*)l.langs->data,lang.c_str())==0) { storeit = iter; valid=true; }
+       }
+       l.langs = l.langs->next;
+     }
+     model = GTK_TREE_MODEL(store);
+     w = gtk_combo_box_new_with_model (model);
+     g_object_unref(store);
+ 
+     GtkCellRenderer * renderer (gtk_cell_renderer_text_new ());
+     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), renderer, TRUE);
+     gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), renderer, "text", 0, NULL);
+ 
+     if (valid) gtk_combo_box_set_active_iter (GTK_COMBO_BOX(w), &storeit);
+ 
+     if (l.langs) g_list_free(l.langs);
+ #endif
+     return w;
+   }
+ 
  }
  
+ 
 -GroupPrefsDialog :: GroupPrefsDialog (Data         & data,
 -                                      const Quark  & group,
 -                                      GroupPrefs   & group_prefs,
 -                                      GtkWindow    * parent_window):
 -  _group (group),
 +GroupPrefsDialog :: GroupPrefsDialog (Data            & data,
 +                                      const quarks_v  & groups,
 +                                      GroupPrefs      & group_prefs,
 +                                      GtkWindow       * parent_window):
 +  _groups (groups),
    _group_prefs (group_prefs)
  {
 +
    GtkWidget * dialog = gtk_dialog_new_with_buttons (_("Pan: Group Preferences"),
                                                      parent_window,
                                                      GTK_DIALOG_DESTROY_WITH_PARENT,
@@@ -133,32 -235,33 +241,39 @@@
    int row (0);
    GtkWidget *t, *w, *l;
    t = HIG :: workarea_create ();
 +
    char buf[512];
 -  g_snprintf (buf, sizeof(buf), _("Properties for %s"), group.c_str());
 +  if (groups.size() != 1)
 +    g_snprintf (buf, sizeof(buf), _("Properties for Groups"));
 +  else
 +    g_snprintf (buf, sizeof(buf), _("Properties for %s"), groups[0].c_str());
 +
    HIG::workarea_add_section_title (t, &row, buf);
-     HIG :: workarea_add_section_spacer (t, row, 3);
-     _charset = w = e_charset_combo_box_new( );
+     HIG :: workarea_add_section_spacer (t, row, 4);
+     GtkWidget* box = _charset = e_charset_combo_box_new( );
 -    e_charset_combo_box_set_charset(
 -        E_CHARSET_COMBO_BOX(box),
 -        _group_prefs.get_string (group, "character-encoding", "UTF-8").c_str());
 -
 -    HIG :: workarea_add_row (t, &row, _("Character _encoding:"), _charset);
 +    e_charset_combo_box_set_charset( E_CHARSET_COMBO_BOX(_charset), _group_prefs.get_string (groups[0], "character-encoding", "UTF-8").c_str());
 +    HIG :: workarea_add_row (t, &row, _("Character _encoding:"), w);
+ 
      w = _save_path = file_entry_new (_("Directory for Saving Attachments"));
      char * pch = g_build_filename (g_get_home_dir(), "News", NULL);
 -    const std::string dir (_group_prefs.get_string (_group, "default-group-save-path", pch));
 +    std::string dir;
 +    if (groups.size() != 1)
 +      dir = pch;
 +    else
 +      dir = _group_prefs.get_string (groups[0], "default-group-save-path", pch);
      g_free (pch);
      file_entry_set (w, dir.c_str());
+ 
      HIG :: workarea_add_row (t, &row, _("Directory for _saving attachments:"), w);
 -
 -    w = _profile = create_profiles_combo_box (data, group, group_prefs);
 +    w = _profile = create_profiles_combo_box (data, groups, group_prefs);
      l = HIG :: workarea_add_row (t, &row, _("Posting _profile:"), w);
 +
      gtk_widget_set_sensitive (l, gtk_widget_get_sensitive(w));
+ #ifdef HAVE_GTKSPELL
+     w = _spellchecker_language = create_spellcheck_combo_box ( group, group_prefs);
+ 
+     HIG :: workarea_add_row (t, &row, _("Spellchecker _language:"), w);
+ #endif
  
    gtk_widget_show_all (t);
    gtk_box_pack_start ( GTK_BOX( gtk_dialog_get_content_area( GTK_DIALOG( dialog))), t, true, true, 0);
diff --cc pan/gui/gui.cc
index 4c8f0d7,a4c2187..4e133c0
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@@ -26,8 -26,7 +26,9 @@@ extern "C" 
    #include <sys/types.h> // for chmod
    #include <sys/stat.h> // for chmod
    #include <glib/gi18n.h>
 +  #include <dirent.h>
+   #include <iconv.h>
 +
  }
  #include <pan/general/debug.h>
  #include <pan/general/e-util.h>
@@@ -393,7 -370,7 +394,8 @@@ GUI :: ~GUI (
      g_object_unref (*it);
    g_object_unref (G_OBJECT(_ui_manager));
  
 +  deinit_gpg();
+   if (iconv_inited) iconv_close(conv);
  }
  
  /***
@@@ -1138,28 -1067,6 +1142,18 @@@ GUI :: do_flag_on (
  }
  
  void
 +GUI :: do_flag_off ()
 +{
 +  do_flag(false);
 +}
 +
- 
- void
- GUI :: do_flag (bool on)
++void GUI :: do_flag (bool t)
 +{
-   /// TODO flag selection
-   std::vector<const Article*> v(_header_pane->get_full_selection_v());
-   g_return_if_fail(!v.empty());
-   foreach (std::vector<const Article*>,v,it)
-   {
-     Article* a((Article*)*it);
-     a->set_flag(on);
-   }
-   const Quark& g(_header_pane->get_group());
-   _data.fire_article_flag_changed(v, g);
++
 +}
 +
++
 +void
  GUI :: do_mark_all_flagged()
  {
    _header_pane->mark_all_flagged();
diff --cc pan/gui/header-pane.cc
index 4ce33a9,46d56e4..bcc6426
--- a/pan/gui/header-pane.cc
+++ b/pan/gui/header-pane.cc
@@@ -33,7 -34,7 +34,8 @@@ extern "C" 
  #include <pan/general/macros.h>
  #include <pan/general/quark.h>
  #include <pan/usenet-utils/filter-info.h>
 +#include <pan/usenet-utils/rules-info.h>
+ #include <pan/usenet-utils/mime-utils.h>
  #include <pan/data/article.h>
  #include <pan/data/data.h>
  #include <pan/icons/pan-pixbufs.h>
@@@ -294,10 -311,15 +315,15 @@@ HeaderPane :: render_subject (GtkTreeVi
    const bool bold (!row->is_read);
  
    const Article * a (self->get_article (model, iter));
-   const char * text (a->subject.c_str());
+ 
+   char* ret = __g_mime_iconv_strdup(conv, a->subject.c_str());
+   std::string res;
+   if (ret) res = ret;
+   g_free(ret);
+ 
    char buf[512];
  
 -  bool underlined (false);
 +  bool unread (false);
  
    if (counter.unread_children)
    {
@@@ -308,22 -330,17 +334,22 @@@
      gtk_tree_path_free (path);
  
      if (!expanded) {
 -      underlined = row->is_read;
 +      unread = row->is_read;
-       snprintf (buf, sizeof(buf), "%s (%lu)", text, counter.unread_children);
-       text = buf;
+       snprintf (buf, sizeof(buf), "%s (%lu)", res.c_str(), counter.unread_children);
+       res = buf;
      }
    }
  
 +  std::string def_bg, def_fg;
 +  def_fg = p.get_color_str_wo_fallback("color-read-fg");
 +  def_bg = p.get_color_str_wo_fallback("color-read-bg");
 +
    g_object_set (renderer,
-     "text", text,
+     "text", res.c_str(),
      "weight", (bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL),
 -    "underline", (underlined ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE),
 -    NULL);
 +    "foreground", unread ? (def_fg.empty() ? NULL : def_fg.c_str()) : NULL,
 +    "background", unread ? (def_bg.empty() ? NULL : def_bg.c_str()) : NULL, NULL);
 +
  }
  
  HeaderPane::Row*
diff --cc pan/gui/post-ui.h
index 632a8b0,8e1b130..05fef71
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@@ -153,26 -112,8 +153,27 @@@ namespace pa
        str2str_t _profile_headers;
        std::string _unchanged_body;
        int _wrap_pixels;
+       std::string _spellcheck_language;
  
 +      GMimeContentEncoding _enc;
 +
 +      /* binpost */
 +      bool _file_queue_empty;
 +      TaskUpload* _upload_ptr;
 +      int _total_parts;
 +      std::string _save_file;
 +      MTRand rng;
 +      int _uploads;
 +
 +    public:
 +      bool _realized;
 +
 +    private:
 +      friend class UploadQueue;
 +      virtual void on_queue_tasks_added (UploadQueue&, int index, int count);
 +      virtual void on_queue_task_removed (UploadQueue&, Task&, int index);
 +      virtual void on_queue_task_moved (UploadQueue&, Task&, int new_index, int old_index);
 +
      private:
        void add_actions (GtkWidget* box);
        void apply_profile_to_body ();
diff --cc pan/gui/prefs-ui.cc
index 1b38eb0,2f7cce5..9029ecf
--- a/pan/gui/prefs-ui.cc
+++ b/pan/gui/prefs-ui.cc
@@@ -585,27 -530,9 +586,27 @@@ PrefsDialog :: PrefsDialog (Prefs& pref
      w = gtk_button_new_from_stock (GTK_STOCK_SELECT_FONT);
      l = charset_label = gtk_label_new (NULL);
      gtk_misc_set_alignment (GTK_MISC(l), 0.0, 0.0);
-     update_default_charset_label(_prefs.get_string("default_charset","UTF-8"));
+     update_default_charset_label(_prefs.get_string("default-charset","UTF-8"));
      g_signal_connect (w, "clicked", G_CALLBACK(select_prefs_charset_cb), this);
      HIG::workarea_add_row (t, &row, w, l);
 +    HIG::workarea_add_section_divider (t, &row);
 +    HIG :: workarea_add_section_title (t, &row, _("Autosave Article Draft"));
 +    w = new_spin_button ("draft-autosave-timeout-min", 0, 60, prefs);
 +    l = gtk_label_new(_("Minutes to autosave the current Article Draft."));
 +    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, _("Systray Behaviour"));
 +    HIG :: workarea_add_section_spacer (t, row, 2);
 +    w = new_check_button (_("Hide to system tray"), "status-icon", false, prefs);
 +    HIG :: workarea_add_wide_control (t, &row, w);
 +    w = new_check_button (_("Start Pan minimized"), "start-minimized", false, prefs);
 +    HIG :: workarea_add_wide_control (t, &row, w);
 +#ifdef HAVE_LIBNOTIFY
 +    w = new_check_button (_("Show notifications"), "use-notify", false, prefs);
 +    HIG :: workarea_add_wide_control (t, &row, w);
 +#endif
    HIG :: workarea_finish (t, &row);
    gtk_notebook_append_page (GTK_NOTEBOOK(notebook), t, gtk_label_new_with_mnemonic(_("_Behavior")));
  
diff --cc pan/tasks/task-article.cc
index 6a0bb8f,80e1278..dca050f
--- a/pan/tasks/task-article.cc
+++ b/pan/tasks/task-article.cc
@@@ -49,27 -52,21 +52,35 @@@ namespac
      std::string stripped;
      mime::remove_multipart_from_subject (article.subject.c_str(), stripped);
  
+     const char* str = stripped.c_str();
+     iconv_t c = iconv_open("UTF-8","UTF-8");
+     char * res = __g_mime_iconv_strdup(c, str);
+     iconv_close(c);
+ 
      char buf[1024];
      if (save)
-       snprintf (buf, sizeof(buf), _("Saving %s"), stripped.c_str());
+       snprintf (buf, sizeof(buf), _("Saving %s"), res);
      else
-       snprintf (buf, sizeof(buf), _("Reading %s"), stripped.c_str());
+       snprintf (buf, sizeof(buf), _("Reading %s"), res);
+ 
+     g_free(res);
+ 
      return std::string (buf);
    }
 +
 +  std::string get_groups_str(const Article& a)
 +  {
 +    std::string r;
 +    quarks_t groups;
 +    int cnt(1);
 +    foreach_const (Xref, a.xref, xit)
 +    {
 +      r += xit->group.to_string();
 +      if (cnt != a.xref.size() && a.xref.size() != 1) r+=", ";
 +      ++cnt;
 +    }
 +    return r;
 +  }
  }
  
  TaskArticle :: TaskArticle (const ServerRank          & server_rank,
diff --cc pan/tasks/task-article.h
index 4494161,4f7245f..c8c87f5
--- a/pan/tasks/task-article.h
+++ b/pan/tasks/task-article.h
@@@ -110,9 -97,21 +110,22 @@@ namespace pa
        friend class Decoder;
        Decoder * _decoder;
        bool _decoder_has_run;
 +      std::string _groups;
 +      const SaveOptions _options;
  
 -    private:
+ 
+ //      typedef std::pair<std::string,StringView> lines_p;
+ //      typedef std::vector<lines_p> lines_v;
+ //
+ //      struct CacheAdder
+ //      {
+ //        lines_v lines;
+ //        void add(std::string& q, const StringView& v)
+ //          { lines.push_back(lines_p(q,v)); }
+ //      };
+ //
+ //      CacheAdder adder;
+ 
        struct Needed {
          std::string message_id;
          unsigned long bytes;
diff --cc pan/usenet-utils/mime-utils.cc
index 0433b53,b4ac29b..3525b04
--- a/pan/usenet-utils/mime-utils.cc
+++ b/pan/usenet-utils/mime-utils.cc
@@@ -40,6 -38,129 +40,101 @@@ extern "C
  
  using namespace pan;
  
 -/***
 -**** YENC
 -***/
 -
 -#define YENC_MARKER_BEGIN      "=ybegin"
 -#define YENC_MARKER_BEGIN_LEN  7
 -#define YENC_MARKER_PART       "=ypart"
 -#define YENC_MARKER_PART_LEN   6
 -#define YENC_MARKER_END        "=yend"
 -#define YENC_MARKER_END_LEN    5
 -#define YENC_TAG_PART          " part="
 -#define YENC_TAG_LINE          " line="
 -#define YENC_TAG_SIZE          " size="
 -#define YENC_TAG_NAME          " name="
 -#define YENC_TAG_BEGIN         " begin="
 -#define YENC_TAG_END           " end="
 -#define YENC_TAG_PCRC32                " pcrc32="
 -#define YENC_TAG_CRC32         " crc32="
 -#define YENC_FULL_LINE_LEN     256
 -#define YENC_HALF_LINE_LEN     128
 -#define YENC_ESC_NULL          "=@"
 -#define YENC_ESC_TAB           "=I"
 -#define YENC_ESC_LF            "=J"
 -#define YENC_ESC_CR            "=M"
 -#define YENC_ESC_ESC           "={"
 -#define YENC_SHIFT             42
 -#define YENC_QUOTE_SHIFT       64
 -
+ namespace pan
+ {
+ 
+   iconv_t conv(0);
+   bool iconv_inited(false);
+ 
+   char *
+   __g_mime_iconv_strndup (iconv_t cd, const char *str, size_t n)
+   {
+ 
+     size_t inleft, outleft, converted = 0;
+     char *out, *outbuf;
+     const char *inbuf;
+     size_t outlen;
+     int errnosav;
+ 
+     if (cd == (iconv_t) -1 || !iconv_inited)
+       return g_strndup (str, n);
+ 
+     outlen = n * 2 + 16;
+     out = (char*)g_malloc (outlen + 4);
+ 
+     inbuf = str;
+     inleft = n;
+ 
+     do {
+       errno = 0;
+       outbuf = out + converted;
+       outleft = outlen - converted;
+ 
+       converted = iconv (cd, (char **) &inbuf, &inleft, &outbuf, &outleft);
+ 
+       if (converted != (size_t) -1 && errno == 0) {
+         /*
 -         * EINVAL  An  incomplete  multibyte sequence has been encoun­
++         * EINVAL  An  incomplete  multibyte sequence has been encounï
+          *         tered in the input.
+          *
+          * We'll just have to ignore it...
+          */
+         break;
+       }
+ 
+       if (errno != E2BIG && errno != EILSEQ) {
+         errnosav = errno;
+         g_free (out);
+ 
+         /* reset the cd */
+         iconv (cd, NULL, NULL, NULL, NULL);
+ 
+         errno = errnosav;
+ 
+         return NULL;
+       }
+ 
+       /*
+ 		 * E2BIG   There is not sufficient room at *outbuf.
+ 		 *
+ 		 * We just need to grow our outbuffer and try again.
+ 		 */
+       {
+         converted = outbuf - out;
+         outlen += inleft * 2 + 16;
+         out = (char*)g_realloc (out, outlen + 4);
+         outbuf = out + converted;
+       }
+ 
+     } while (TRUE);
+ 
+     /* flush the iconv conversion */
+     while (iconv (cd, NULL, NULL, &outbuf, &outleft) == (size_t) -1) {
+       if (errno != E2BIG)
+         break;
+ 
+       outlen += 16;
+       converted = outbuf - out;
+       out = (char*)g_realloc (out, outlen + 4);
+       outleft = outlen - converted;
+       outbuf = out + converted;
+     }
+ 
+     /* Note: not all charsets can be nul-terminated with a single
+              nul byte. UCS2, for example, needs 2 nul bytes and UCS4
+              needs 4. I hope that 4 nul bytes is enough to terminate all
+              multibyte charsets? */
+ 
+     /* nul-terminate the string */
+     memset (outbuf, 0, 4);
+ 
+     /* reset the cd */
+     iconv (cd, NULL, NULL, NULL, NULL);
+ 
+     return out;
+   }
+ }
+ 
  namespace
  {
     const char*
@@@ -361,139 -482,12 +456,139 @@@ namespac
  
  enum EncType
  {
 -	ENC_PLAIN,
 +	ENC_PLAIN ,
  	ENC_YENC,
 -	ENC_UU
 +	ENC_UU,
 +	ENC_BASE64,
 +	ENC_QP
  };
  
 -namespace
 +namespace pan
 +{
 +
 +  /*
 +   base64.cpp and base64.h
 +
-    Copyright (C) 2004-2008 Renéyffenegger
++   Copyright (C) 2004-2008 Renï Nyffenegger
 +
 +   This source code is provided 'as-is', without any express or implied
 +   warranty. In no event will the author be held liable for any damages
 +   arising from the use of this software.
 +
 +   Permission is granted to anyone to use this software for any purpose,
 +   including commercial applications, and to alter it and redistribute it
 +   freely, subject to the following restrictions:
 +
 +   1. The origin of this source code must not be misrepresented; you must not
 +      claim that you wrote the original source code. If you use this source code
 +      in a product, an acknowledgment in the product documentation would be
 +      appreciated but is not required.
 +
 +   2. Altered source versions must be plainly marked as such, and must not be
 +      misrepresented as being the original source code.
 +
 +   3. This notice may not be removed or altered from any source distribution.
 +
-    Renéyffenegger rene nyffenegger adp-gmbh ch
++   Renï Nyffenegger rene nyffenegger adp-gmbh ch
 +
 +*/
 +
 +  static const std::string base64_chars =
 +             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 +             "abcdefghijklmnopqrstuvwxyz"
 +             "0123456789+/";
 +
 +
 +  static inline bool is_base64(unsigned char c) {
 +    return (isalnum(c) || (c == '+') || (c == '/'));
 +  }
 +
 +  std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
 +    std::string ret;
 +    int i = 0;
 +    int j = 0;
 +    unsigned char char_array_3[3];
 +    unsigned char char_array_4[4];
 +
 +    while (in_len--) {
 +      char_array_3[i++] = *(bytes_to_encode++);
 +      if (i == 3) {
 +        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
 +        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
 +        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
 +        char_array_4[3] = char_array_3[2] & 0x3f;
 +
 +        for(i = 0; (i <4) ; i++)
 +          ret += base64_chars[char_array_4[i]];
 +        i = 0;
 +      }
 +    }
 +
 +    if (i)
 +    {
 +      for(j = i; j < 3; j++)
 +        char_array_3[j] = '\0';
 +
 +      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
 +      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
 +      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
 +      char_array_4[3] = char_array_3[2] & 0x3f;
 +
 +      for (j = 0; (j < i + 1); j++)
 +        ret += base64_chars[char_array_4[j]];
 +
 +      while((i++ < 3))
 +        ret += '=';
 +
 +    }
 +
 +    return ret;
 +
 +  }
 +
 +  std::string base64_decode(std::string const& encoded_string) {
 +    int in_len = encoded_string.size();
 +    int i = 0;
 +    int j = 0;
 +    int in_ = 0;
 +    unsigned char char_array_4[4], char_array_3[3];
 +    std::string ret;
 +
 +    while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
 +      char_array_4[i++] = encoded_string[in_]; in_++;
 +      if (i ==4) {
 +        for (i = 0; i <4; i++)
 +          char_array_4[i] = base64_chars.find(char_array_4[i]);
 +
 +        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
 +        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
 +        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
 +
 +        for (i = 0; (i < 3); i++)
 +          ret += char_array_3[i];
 +        i = 0;
 +      }
 +    }
 +
 +    if (i) {
 +      for (j = i; j <4; j++)
 +        char_array_4[j] = 0;
 +
 +      for (j = 0; j <4; j++)
 +        char_array_4[j] = base64_chars.find(char_array_4[j]);
 +
 +      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
 +      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
 +      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
 +
 +      for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
 +    }
 +
 +    return ret;
 +  }
 +}
 +
 +namespace pan
  {
    struct TempPart
    {
diff --cc pan/usenet-utils/mime-utils.h
index f25ce2f,a89da0a..fa89512
--- a/pan/usenet-utils/mime-utils.h
+++ b/pan/usenet-utils/mime-utils.h
@@@ -26,53 -26,18 +26,58 @@@
  #include <gmime/gmime-stream.h>
  #include <gmime/gmime-message.h>
  #include <pan/general/string-view.h>
 +#include <pan/usenet-utils/gpg.h>
 +
 +/***
 +**** YENC
 +***/
 +
 +#define YENC_MARKER_BEGIN      "=ybegin"
 +#define YENC_MARKER_BEGIN_LEN  7
 +#define YENC_MARKER_PART       "=ypart"
 +#define YENC_MARKER_PART_LEN   6
 +#define YENC_MARKER_END        "=yend"
 +#define YENC_MARKER_END_LEN    5
 +#define YENC_TAG_PART          " part="
 +#define YENC_TAG_LINE          " line="
 +#define YENC_TAG_SIZE          " size="
 +#define YENC_TAG_NAME          " name="
 +#define YENC_TAG_BEGIN         " begin="
 +#define YENC_TAG_END           " end="
 +#define YENC_TAG_PCRC32        " pcrc32="
 +#define YENC_TAG_CRC32         " crc32="
 +#define YENC_FULL_LINE_LEN     256
 +#define YENC_HALF_LINE_LEN     128
 +#define YENC_ESC_NULL          "=@"
 +#define YENC_ESC_TAB           "=I"
 +#define YENC_ESC_LF            "=J"
 +#define YENC_ESC_CR            "=M"
 +#define YENC_ESC_ESC           "={"
 +#define YENC_SHIFT             42
 +#define YENC_QUOTE_SHIFT       64
 +
 +#define NEEDS_DECODING(encoding) ((encoding == GMIME_CONTENT_ENCODING_BASE64) ||   \
 +                                 (encoding == GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE))
  
+ extern "C"
+ {
+   #include <iconv.h>
+ }
+ 
  namespace pan
  {
 +
 +  std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
 +  std::string base64_decode(std::string const& encoded_string);
 +
 +  GMimeMessage* message_add_signed_part (const std::string& uid, const std::string& body_str, GMimeMessage* body);
 +  GMimeMessage* gpg_encrypt (const std::string& uid, const std::string& body_str, GMimeMessage* body, GPtrArray* rcp, bool sign);
 +  bool gpg_verify_mps (GMimeObject*, GPGDecErr&);
 +
    /**
 -   * Utilities to build and parse GMimeMesasges.
 +   * Utilities to build and parse GMimeMessages.
     *
-    * Most of nastiness this is to handle Usenet's use of chainging together
+    * Most of this nastiness is to handle Usenet's use of chainging together
     * multiple articles as parts of a whole.  This code tries to build
     * a multipart GMimeMessage from multiple posts when necessary, and to
     * also handle Usenet's loose standards for uu/yenc by checking each line
@@@ -105,8 -70,17 +110,18 @@@
  
    char *pan_g_mime_message_get_body (GMimeMessage *message, gboolean *is_html);
    void pan_g_mime_message_add_recipients_from_string (GMimeMessage *message, GMimeRecipientType type, const char *string);
 +  void pan_g_mime_message_set_message_id (GMimeMessage *msg, const char *mid);
  
+   extern iconv_t conv;
+   extern bool iconv_inited;
+ 
+   char * __g_mime_iconv_strndup (iconv_t cd, const char *str, size_t n);
+ 
+   static char * __g_mime_iconv_strdup (iconv_t cd, const char *str)
+   {
+     return __g_mime_iconv_strndup(cd, str, strlen(str));
+   }
+ 
  }
  
  



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