[pan2: 54/268] [!] encodecache fixed (for good i hope) [*] added save option for upload queues
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2: 54/268] [!] encodecache fixed (for good i hope) [*] added save option for upload queues
- Date: Mon, 2 Jan 2012 15:42:32 +0000 (UTC)
commit 01b704533d8d61ed129276cb7c67718974f74552
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date: Tue Jun 7 16:34:40 2011 +0200
[!] encodecache fixed (for good i hope)
[*] added save option for upload queues
pan/data/encode-cache.cc | 11 +-
pan/data/encode-cache.o | Bin 889992 -> 872312 bytes
pan/gui/my-valgrind.sh | 2 +-
pan/gui/post-ui.cc | 68 +++++-
pan/gui/post-ui.h | 3 +
pan/gui/prefs-ui.cc | 11 +-
pan/tasks/encoder.cc | 67 +++---
pan/tasks/encoder.h | 5 +
pan/tasks/nzb.cc | 29 +--
pan/tasks/task-upload.cc | 65 +++---
pan/tasks/task-upload.h | 6 +-
pan/usenet-utils/Makefile.am | 3 +-
pan/usenet-utils/MersenneTwister.h | 461 ++++++++++++++++++++++++++++++++++++
uulib/uudeview.h | 4 +-
uulib/uuencode.c | 26 ++-
15 files changed, 651 insertions(+), 110 deletions(-)
---
diff --git a/pan/data/encode-cache.cc b/pan/data/encode-cache.cc
index 1de3acf..a12b86e 100644
--- a/pan/data/encode-cache.cc
+++ b/pan/data/encode-cache.cc
@@ -123,7 +123,6 @@ EncodeCache :: EncodeCache (const StringView& path, size_t max_megs):
{
struct stat stat_p;
g_snprintf (filename, sizeof(filename), "%s%c%s", _path.c_str(), G_DIR_SEPARATOR, fname);
- std::cerr<<"loaded "<<filename<<std::endl;
if (!stat (filename, &stat_p))
{
MsgInfo info;
@@ -135,8 +134,6 @@ EncodeCache :: EncodeCache (const StringView& path, size_t max_megs):
}
}
g_dir_close (dir);
- std::cerr <<"loaded " << _mid_to_info.size() << " articles into encode-cache from "
- << _path<<", size is : "<<_current_bytes<<" , max is "<<_max_megs * 1024 * 1024<<std::endl;
if (_current_bytes>_max_megs*1024*1024) resize();
}
}
@@ -229,6 +226,7 @@ void EncodeCache :: finalize (const Quark& message_id)
_mid_to_info[message_id]._size = sb.st_size;
fire_added (message_id);
_current_bytes += sb.st_size;
+ // resize();
}
void
@@ -241,7 +239,6 @@ EncodeCache :: reserve (const mid_sequence_t& mids)
void
EncodeCache :: release (const mid_sequence_t& mids)
{
- std::cerr<<"ec release"<<std::endl;
foreach_const (mid_sequence_t, mids, it)
if (!--_locks[*it])
_locks.erase (*it);
@@ -308,9 +305,9 @@ EncodeCache :: resize (guint64 max_bytes)
}
}
- std::cerr<< "cache expired " << removed.size() << " articles, "
- "has " << _mid_to_info.size() << " active "
- "and " << _locks.size() << " locked.\n";
+// std::cerr<< "cache expired " << removed.size() << " articles, "
+// "has " << _mid_to_info.size() << " active "
+// "and " << _locks.size() << " locked.\n";
if (!removed.empty())
fire_removed (removed);
diff --git a/pan/data/encode-cache.o b/pan/data/encode-cache.o
index 710d05b..80ba07b 100644
Binary files a/pan/data/encode-cache.o and b/pan/data/encode-cache.o differ
diff --git a/pan/gui/my-valgrind.sh b/pan/gui/my-valgrind.sh
index 21ae2fd..cc5fe47 100755
--- a/pan/gui/my-valgrind.sh
+++ b/pan/gui/my-valgrind.sh
@@ -2,4 +2,4 @@
export G_SLICE=always-malloc
export G_DEBUG=gc-friendly
export GLIBCXX_FORCE_NEW=1
-valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=64 --log-file=pan-valgrind --show-reachable=yes ./pan
+valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=42 --log-file=pan-valgrind --show-reachable=yes ./pan
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 514e7cb..137698a 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -58,6 +58,7 @@ extern "C" {
using namespace pan;
+#define QUEUE_SAVE_KEY "upload-queue-save-enabled"
#define USER_AGENT_PREFS_KEY "add-user-agent-header-when-posting"
#define MESSAGE_ID_PREFS_KEY "add-message-id-header-when-posting"
#define USER_AGENT_EXTRA_PREFS_KEY "user-agent-extra-info"
@@ -1967,6 +1968,10 @@ namespace
{
static_cast<Prefs*>(prefs_gpointer)->set_flag (USER_AGENT_PREFS_KEY, gtk_toggle_button_get_active(tb));
}
+ void queue_save_toggled_cb (GtkToggleButton * tb, gpointer prefs_gpointer)
+ {
+ static_cast<Prefs*>(prefs_gpointer)->set_flag (QUEUE_SAVE_KEY, gtk_toggle_button_get_active(tb));
+ }
}
namespace
@@ -2020,6 +2025,11 @@ PostUI :: create_filequeue_tab ()
w = add_button (buttons, GTK_STOCK_DELETE, G_CALLBACK(delete_clicked_cb), this);
gtk_widget_set_tooltip_text( w, _("Delete from Queue"));
gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
+ w = _save_check = gtk_check_button_new_with_mnemonic (_("Save queue to file"));
+ bool b = _prefs.get_flag (QUEUE_SAVE_KEY, true);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(w), b);
+ g_signal_connect (w, "toggled", G_CALLBACK(queue_save_toggled_cb), &_prefs);
+ gtk_box_pack_start (GTK_BOX(buttons), w, 0, 0, 0);
pan_box_pack_start_defaults (GTK_BOX(buttons), gtk_event_box_new());
gtk_box_pack_start (GTK_BOX(vbox), buttons, false, false, 0);
@@ -2613,7 +2623,7 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
if (_file_queue_empty) _file_queue_empty=!_file_queue_empty;
GSList * cur = g_slist_nth (tmp_list,0);
-
+ gtk_widget_destroy (w);
GMimeMessage* msg = new_message_from_ui(POSTING);
char * tmp;
@@ -2632,6 +2642,10 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
groups.insert(groupname);
}
+ bool b = _prefs.get_flag (QUEUE_SAVE_KEY, true);
+ if (b)
+ _save_file = prompt_user_for_upload_nzb_dir (GTK_WINDOW (gtk_widget_get_toplevel(_root)), _prefs);
+
int cnt(1);
for (; cur; cur = cur->next, ++cnt)
{
@@ -2646,6 +2660,9 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
TaskUpload::Needed n;
foreach_const (quarks_t, groups, git)
n.xref.insert (profile.posting_server, *git,0);
+ foreach_const (quarks_t, groups, git)
+ a.xref.insert (profile.posting_server, *git,0);
+
for (int i = 1; i <= total; ++i)
{
g_snprintf(buf,sizeof(buf),"%s.%d", basename, i);
@@ -2661,17 +2678,60 @@ PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, c
const std::string message_id = !profile.fqdn.empty()
? GNKSA::generate_message_id (profile.fqdn)
: GNKSA::generate_message_id_from_email_address (profile.address);
+
TaskUpload* tmp = new TaskUpload(std::string((const char*)cur->data),
profile.posting_server, _cache,
- a, message_id, &import, 0, TaskUpload::YENC);
+ a, message_id, _save_file, &import, 0, TaskUpload::YENC);
_file_queue_tasks.push_back(tmp);
}
- g_slist_free (tmp_list);
+ g_slist_free (tmp_list);
+
}
- gtk_widget_destroy (w);
g_object_unref (G_OBJECT(message));
update_filequeue_tab();
}
+std::string
+PostUI :: prompt_user_for_upload_nzb_dir (GtkWindow * parent, const Prefs& prefs)
+{
+ char buf[4096];
+ struct stat sb;
+ std::string path;
+
+ std::string prev_path = prefs.get_string ("default-save-attachments-path", g_get_home_dir ());
+ if (!file :: file_exists (prev_path.c_str()))
+ prev_path = g_get_home_dir ();
+ std::string prev_file(_("Untitled.nzb"));
+
+ GtkWidget * w = gtk_file_chooser_dialog_new (_("Save Upload Queue as NZB File"),
+ GTK_WINDOW(parent),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG(w), GTK_RESPONSE_ACCEPT);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (w), TRUE);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (w), prev_path.c_str());
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (w), prev_file.c_str());
+
+ GtkFileFilter * filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*.[Nn][Zz][Bb]");
+ gtk_file_filter_set_name (filter, _("NZB Files"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(w), filter);
+ gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(w), false);
+ if (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(w)))
+ {
+ char * tmp = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w));
+ path = tmp;
+ g_free (tmp);
+ }
+
+ gtk_widget_destroy (w);
+ return path;
+
+}
+
+
+
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index bfc4e0f..b5362bc 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -49,6 +49,7 @@ namespace pan
GMimeMessage*, Prefs&, GroupPrefs&, EncodeCache&);
void prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, const Prefs& prefs);
+ std::string prompt_user_for_upload_nzb_dir (GtkWindow * parent, const Prefs& prefs);
protected:
PostUI (GtkWindow*, Data&, Queue&, GroupServer&, Profiles&,
@@ -127,6 +128,7 @@ namespace pan
GtkWidget * _replyto_entry;
GtkWidget * _body_view;
GtkWidget * _user_agent_check;
+ GtkWidget * _save_check;
GtkWidget * _message_id_check;
GtkTextBuffer * _body_buf;
GtkTextBuffer * _headers_buf;
@@ -151,6 +153,7 @@ namespace pan
tasks_v _file_queue_tasks;
TaskUpload* _upload_ptr;
int _total_parts;
+ std::string _save_file;
private:
void add_actions (GtkWidget* box);
diff --git a/pan/gui/prefs-ui.cc b/pan/gui/prefs-ui.cc
index 029087f..574853d 100644
--- a/pan/gui/prefs-ui.cc
+++ b/pan/gui/prefs-ui.cc
@@ -475,7 +475,7 @@ PrefsDialog :: PrefsDialog (Prefs& prefs, GtkWindow* parent):
HIG :: workarea_add_wide_control (t, &row, w);
w = new_spin_button ("newsrc-autosave-timeout-min", 0, 60, prefs);
l = gtk_label_new(_("Minutes to autosave newsrc files."));
- HIG::workarea_add_row (t, &row, l, w);
+ HIG::workarea_add_row (t, &row, l, w);
HIG :: workarea_finish (t, &row);
gtk_notebook_append_page (GTK_NOTEBOOK(notebook), t, gtk_label_new_with_mnemonic(_("_Behavior")));
@@ -610,6 +610,15 @@ PrefsDialog :: PrefsDialog (Prefs& prefs, GtkWindow* parent):
HIG :: workarea_finish (t, &row);
gtk_notebook_append_page (GTK_NOTEBOOK(notebook), t, gtk_label_new_with_mnemonic(_("A_pplications")));
+ row = 0;
+ t = HIG :: workarea_create ();
+ HIG :: workarea_add_section_title (t, &row, _("Upload Queue Options"));
+ HIG :: workarea_add_section_spacer (t, row, 4);
+ w = new_check_button (_("Always save article information from Uploads to a file"), "upload-queue-save-enabled", false, prefs);
+ HIG :: workarea_add_wide_control (t, &row, w);
+ HIG :: workarea_finish (t, &row);
+ gtk_notebook_append_page (GTK_NOTEBOOK(notebook), t, gtk_label_new_with_mnemonic(_("O_ptions for Uploads")));
+
gtk_widget_show_all (notebook);
gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area( GTK_DIALOG(dialog))), notebook, true, true, 0);
_root = dialog;
diff --git a/pan/tasks/encoder.cc b/pan/tasks/encoder.cc
index fcbe1fd..2c77f56 100644
--- a/pan/tasks/encoder.cc
+++ b/pan/tasks/encoder.cc
@@ -37,48 +37,38 @@ extern "C" {
#include <pan/general/file-util.h>
#include <pan/general/macros.h>
#include <pan/general/utf8-utils.h>
+#include <pan/usenet-utils/MersenneTwister.h>
#include "encoder.h"
using namespace pan;
-namespace
+
+/** generates a unique message-id for a usenet post, consisting of
+ * the Îsec since the Epoch and 2 random numbers from a Mersenne-Twister RNG + the internal part counter
+ * source for RNG: http://www.jwz.org/doc/mid.html
+ */
+void
+Encoder :: generate_unique_id (StringView& mid, int cnt, std::string& s)
{
- void generate_unique_id (StringView& mid, std::string& filename, int cnt, std::string& s)
- {
- std::stringstream out;
- struct stat sb;
- struct timeval tv;
-
- const char * pch = mid.strchr ('@');
- StringView domain = mid.substr (pch+1, NULL);
- pch = domain.strchr ('>');
- domain = domain.substr (NULL, pch);
- domain.trim ();
-
- // add unique local part to message-id
- out << "pan.";
- const time_t now (time(NULL));
- struct tm local_now = *gmtime (&now);
- gettimeofday (&tv, NULL);
- char buf[64];
- std::strftime (buf, sizeof(buf), "%Y.%m.%d.%H.%M.%S", &local_now);
- out << buf;
- out << "." << tv.tv_sec << "." << tv.tv_usec << "." << tv.tv_sec*tv.tv_usec;
-
- // delimit
- out<< '@';
-
- // add domain
- out << domain;
- s = out.str();
- }
+ std::stringstream out;
+ struct stat sb;
+ struct timeval tv;
+ out << "pan$";
+ gettimeofday (&tv, NULL);
+ out << std::hex << tv.tv_usec << "$" << std::hex <<
+ mtrand.randInt() << "$" << std::hex << mtrand.randInt() <<std::hex << cnt;
+ // delimit
+ out<< '@';
+ // add domain
+ out << mid;
+ s = out.str();
}
Encoder :: Encoder (WorkerPool& pool):
_worker_pool (pool),
_gsourceid (-1)
-{
-}
+{}
+
Encoder :: ~Encoder()
{
@@ -155,8 +145,12 @@ Encoder :: do_work()
g_snprintf(buf, sizeof(buf), "\"%s\" - %s (/%03d)", basename.c_str(), subject.c_str(), needed->size());
tmp->subject = buf;
+ char cachename[4096];
for (TaskUpload::needed_t::iterator it = needed->begin(); it != needed->end(); ++it, ++cnt)
{
+
+ cache->get_filename(cachename, Quark(it->second.message_id));
+
FILE * fp = cache->get_fp_from_mid(it->second.message_id);
if (!fp)
{
@@ -166,7 +160,7 @@ Encoder :: do_work()
}
// 4000 lines SHOULD be OK for ANY nntp server ...
StringView mid(global_mid);
- generate_unique_id(mid, filename, cnt, s);
+ generate_unique_id(mid, cnt, s);
res = UUE_PrepPartial (fp, NULL, (char*)filename.c_str(),YENC_ENCODED,
(char*)basename.c_str(),0644, cnt, 4000,
0, (char*)groups.c_str(),
@@ -174,19 +168,16 @@ Encoder :: do_work()
(char*)subject.c_str(), (char*)s.c_str(), 0);
if (res != UURET_CONT) break;
-
cache->finalize(it->second.message_id);
- stat (it->second.message_id.c_str(), &sb);
+ stat (cachename, &sb);
it->second.bytes = sb.st_size;
task->_all_bytes += sb.st_size;
-
- std::cerr<<"add to batch: "<<it->second.message_id<<" "<<sb.st_size<<"\n";
-
batch.add_part(cnt, StringView(s), sb.st_size);
}
if (res != UURET_OK)
{
+ unlink(cachename); //brute-force
g_snprintf(buf, bufsz,
_("Error encoding %s: %s"),
basename.c_str(),
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
index 405d43e..e027498 100644
--- a/pan/tasks/encoder.h
+++ b/pan/tasks/encoder.h
@@ -31,6 +31,8 @@
#include <pan/general/locking.h>
#include <pan/general/worker-pool.h>
#include <pan/tasks/task-upload.h>
+#include <pan/usenet-utils/MersenneTwister.h>
+
extern "C" {
# define PROTOTYPES
# include <uulib/uudeview.h>
@@ -92,6 +94,9 @@ namespace pan
TaskUpload::needed_t* needed;
std::string global_mid;
Article article;
+ MTRand mtrand;
+
+ void generate_unique_id (StringView& mid, int cnt, std::string& s);
// These are set in the worker thread and polled in the main thread.
Mutex mut;
diff --git a/pan/tasks/nzb.cc b/pan/tasks/nzb.cc
index 7cafa04..97ec500 100644
--- a/pan/tasks/nzb.cc
+++ b/pan/tasks/nzb.cc
@@ -47,8 +47,9 @@ namespace
quarks_t groups;
std::string text;
std::string path;
- std::vector<std::string> groups_str; // TaskUpload
- TaskUpload::needed_t needed_parts; // TaskUpload
+ std::vector<std::string> groups_str; // TaskUpload
+ TaskUpload::needed_t needed_parts; // TaskUpload
+ std::string domain; // TaskUpload
Article a;
PartBatch parts;
tasks_t tasks;
@@ -74,7 +75,8 @@ namespace
a.clear ();
bytes = 0;
number = 0;
- needed_parts.clear(); // TaskUpload
+ needed_parts.clear(); // TaskUpload
+ domain.clear(); // TaskUpload
}
};
@@ -103,6 +105,7 @@ namespace
if (!strcmp (*k,"author")) mc.a.author = *v;
else if (!strcmp (*k,"subject")) mc.a.subject = *v;
else if (!strcmp (*k,"server")) mc.server = *v;
+ else if (!strcmp (*k,"domain")) mc.domain = *v;
}
}
@@ -149,10 +152,6 @@ namespace
}
else if (!strcmp(element_name, "part") && mc.number && !mc.text.empty()) {
-// if (mc.a.message_id.empty()) {
-// mc.a.message_id = mc.text;
-// mc.parts.init (mc.text);
-// }
mc.a.message_id = mc.text;
TaskUpload::Needed n;
n.partno = mc.number;
@@ -183,13 +182,11 @@ namespace
else if (!strcmp (element_name, "upload"))
{
debug("adding taskupload from nzb.\n");
-// mc.parts.sort ();
-// mc.a.set_parts (mc.parts);
-// foreach_const (quarks_t, mc.groups, git)
-// mc.a.xref.insert (mc.server, *git,0);
-
- TaskUpload* tmp = new TaskUpload (mc.path, mc.server, mc.encode_cache,
- mc.a, mc.a.message_id.to_string() , &mc.needed_parts, 0, TaskUpload::YENC);
+ foreach_const (quarks_t, mc.groups, git)
+ mc.a.xref.insert (mc.server, *git, 0);
+ TaskUpload* tmp = new TaskUpload (mc.path, mc.server, mc.encode_cache,mc.a,
+ mc.domain, std::string(""),
+ &mc.needed_parts, 0, TaskUpload::YENC);
mc.tasks.push_back (tmp);
}
}
@@ -356,7 +353,9 @@ NZB :: nzb_to_xml (std::ostream & out,
out << "\" subject=\"";
escaped (out, task->_subject);
out << "\" server=\"";
- escaped (out, task->_server.to_string()) << "\">\n";
+ escaped (out, task->_server.to_string());
+ out << "\" domain=\"nospam@";
+ escaped (out, task->_domain) << "\">\n";
++depth;
out << indent(depth)
<< "<path>" << task->_filename << "</path>\n";
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index 31b6487..83e2c3e 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -43,8 +43,6 @@ extern "C" {
using namespace pan;
-///TODO refresh actual filesize inside article parts! (by encoder)
-
namespace
{
std::string get_description (const char* name)
@@ -66,6 +64,22 @@ namespace
}
}
+namespace
+{
+ std::string get_domain(const StringView& mid)
+ {
+ const char * pch = mid.strchr ('@');
+ StringView domain;
+ if (pch) domain = mid.substr (pch+1, NULL);
+ if (pch) pch = domain.strchr ('>');
+ if (pch) domain = domain.substr (NULL, pch);
+ domain.trim ();
+
+ std::cerr<<"generate domain : "<<domain<<std::endl;
+
+ return domain.to_string();
+ }
+}
/***
****
@@ -75,7 +89,8 @@ TaskUpload :: TaskUpload (const std::string & filename,
const Quark & server,
EncodeCache & cache,
Article article,
- std::string mid,
+ std::string domain,
+ std::string save_file,
needed_t * imported,
Progress::Listener * listener,
const TaskUpload::EncodeMode enc):
@@ -85,12 +100,13 @@ TaskUpload :: TaskUpload (const std::string & filename,
_server(server),
_cache(cache),
_article(article),
+ _domain(get_domain(StringView(domain))),
+ _save_file(save_file),
_subject (article.subject.to_string()),
_author(article.author.to_string()),
_encoder(0),
_encoder_has_run (false),
_encode_mode(enc),
- _mid(mid),
_lines_per_file(4000),
_all_bytes(0)
{
@@ -121,10 +137,6 @@ TaskUpload :: build_needed_tasks(bool imported)
foreach_const (Xref, _article.xref, it)
_groups.insert (it->group);
-// TaskUpload::Needed n;
-// foreach_const (quarks_t, groups, git)
-// n.xref.insert (_server, *git, StringView(buf)==_article.message_id.to_string()
-// ? _article.xref.find_number(_server,*git) : 0);
Article::mid_sequence_t mids;
foreach (needed_t, _needed, it)
{
@@ -207,14 +219,14 @@ TaskUpload :: use_nntp (NNTP * nntp)
void
TaskUpload :: on_nntp_line (NNTP * nntp,
const StringView & line_in)
-{}
+{
+}
void
TaskUpload :: on_nntp_done (NNTP * nntp,
Health health,
const StringView & response)
{
-
char buf[4096];
Log::Entry tmp;
tmp.date = time(NULL);
@@ -274,18 +286,18 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
_logfile.push_back(tmp);
Log::add_entry_list (tmp, _logfile);
_logfile.clear();
- } else
- {
- Log::add_entry_list (tmp, _logfile);
- _logfile.clear();
- Log :: add_err_va (_("Posting of file %s not successful: Check the popup log!"),
- _basename.c_str(), response.str);
}
- break;
+
case TOO_MANY_CONNECTIONS:
// lockout for 120 secs, but try
_state.set_need_nntp(nntp->_server);
break;
+ default:
+ Log::add_entry_list (tmp, _logfile);
+ _logfile.clear();
+ Log :: add_err_va (_("Posting of file %s not successful: Check the popup log!"),
+ _basename.c_str(), response.str);
+ break;
}
_end:
@@ -327,7 +339,7 @@ TaskUpload :: use_encoder (Encoder* encoder)
groups += (*it).to_string();
}
_encoder->enqueue (this, &_cache, _article, _filename, _basename,
- groups, _subject, _author, _mid, YENC);
+ groups, _subject, _author, _domain, YENC);
debug ("encoder thread was free, enqueued work");
}
@@ -373,16 +385,6 @@ TaskUpload :: on_worker_done (bool cancelled)
check_in (d);
}
-namespace
-{
- void add_to_upload_list(std::vector<Article*>& vec)
- {
- std::ofstream out("/home/imhotep/download_list", std::fstream::out | std::fstream::app);
- NZB :: upload_list_to_xml_file (out, vec);
- out.close();
- }
-}
-
TaskUpload :: ~TaskUpload ()
{
// ensure our on_worker_done() doesn't get called after we're dead
@@ -392,5 +394,10 @@ TaskUpload :: ~TaskUpload ()
_cache.release(_article.get_part_mids());
_cache.resize();
- add_to_upload_list(_upload_list);
+ if (!_save_file.empty())
+ {
+ std::ofstream out(_save_file.c_str(), std::fstream::out | std::fstream::app);
+ NZB :: upload_list_to_xml_file (out, _upload_list);
+ out.close();
+ }
}
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
index 0106d2d..3b3eff8 100644
--- a/pan/tasks/task-upload.h
+++ b/pan/tasks/task-upload.h
@@ -80,7 +80,8 @@ namespace pan
const Quark & server,
EncodeCache & cache,
Article article,
- std::string mid,
+ std::string domain,
+ std::string save_file,
needed_t * imported=0,
Progress::Listener * listener= 0,
TaskUpload::EncodeMode enc= YENC);
@@ -135,9 +136,10 @@ namespace pan
EncodeCache& _cache;
std::deque<Log::Entry> _logfile; // for intermediate updates
Article _article;
- std::string _mid;
+ std::string _domain;
unsigned long _all_bytes;
std::vector<Article*> _upload_list;
+ std::string _save_file;
private:
needed_t _needed;
diff --git a/pan/usenet-utils/Makefile.am b/pan/usenet-utils/Makefile.am
index e845479..32749af 100644
--- a/pan/usenet-utils/Makefile.am
+++ b/pan/usenet-utils/Makefile.am
@@ -10,7 +10,8 @@ libusenetutils_a_SOURCES = \
numbers.cc \
scorefile.cc \
text-massager.cc \
- url-find.cc
+ url-find.cc \
+ MersenneTwister.h
noinst_HEADERS = \
defgroup.h \
diff --git a/pan/usenet-utils/MersenneTwister.h b/pan/usenet-utils/MersenneTwister.h
new file mode 100644
index 0000000..df1b9ec
--- /dev/null
+++ b/pan/usenet-utils/MersenneTwister.h
@@ -0,0 +1,461 @@
+// MersenneTwister.h
+// Mersenne Twister random number generator -- a C++ class MTRand
+// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// Richard J. Wagner v1.1 28 September 2009 wagnerr umich edu
+
+// The Mersenne Twister is an algorithm for generating random numbers. It
+// was designed with consideration of the flaws in various other generators.
+// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
+// are far greater. The generator is also fast; it avoids multiplication and
+// division, and it benefits from caches and pipelines. For more information
+// see the inventors' web page at
+// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+
+// Reference
+// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
+// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
+// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
+
+// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+// Copyright (C) 2000 - 2009, Richard J. Wagner
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The names of its contributors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+// The original code included the following notice:
+//
+// When you use this, send an email to: m-mat math sci hiroshima-u ac jp
+// with an appropriate reference to your work.
+//
+// It would be nice to CC: wagnerr umich edu and Cokus math washington edu
+// when you write.
+
+#ifndef MERSENNETWISTER_H
+#define MERSENNETWISTER_H
+
+// Not thread safe (unless auto-initialization is avoided and each thread has
+// its own MTRand object)
+
+#include <iostream>
+#include <climits>
+#include <cstdio>
+#include <ctime>
+#include <cmath>
+
+class MTRand {
+// Data
+public:
+ typedef unsigned long uint32; // unsigned integer type, at least 32 bits
+
+ enum { N = 624 }; // length of state vector
+ enum { SAVE = N + 1 }; // length of array for save()
+
+protected:
+ enum { M = 397 }; // period parameter
+
+ uint32 state[N]; // internal state
+ uint32 *pNext; // next value to get from state
+ int left; // number of values left before reload needed
+
+// Methods
+public:
+ MTRand( const uint32 oneSeed ); // initialize with a simple uint32
+ MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or array
+ MTRand(); // auto-initialize with /dev/urandom or time() and clock()
+ MTRand( const MTRand& o ); // copy
+
+ // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
+ // values together, otherwise the generator state can be learned after
+ // reading 624 consecutive values.
+
+ // Access to 32-bit random numbers
+ uint32 randInt(); // integer in [0,2^32-1]
+ uint32 randInt( const uint32 n ); // integer in [0,n] for n < 2^32
+ double rand(); // real number in [0,1]
+ double rand( const double n ); // real number in [0,n]
+ double randExc(); // real number in [0,1)
+ double randExc( const double n ); // real number in [0,n)
+ double randDblExc(); // real number in (0,1)
+ double randDblExc( const double n ); // real number in (0,n)
+ double operator()(); // same as rand()
+
+ // Access to 53-bit random numbers (capacity of IEEE double precision)
+ double rand53(); // real number in [0,1)
+
+ // Access to nonuniform random number distributions
+ double randNorm( const double mean = 0.0, const double stddev = 1.0 );
+
+ // Re-seeding functions with same behavior as initializers
+ void seed( const uint32 oneSeed );
+ void seed( uint32 *const bigSeed, const uint32 seedLength = N );
+ void seed();
+
+ // Saving and loading generator state
+ void save( uint32* saveArray ) const; // to array of size SAVE
+ void load( uint32 *const loadArray ); // from such array
+ friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
+ friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
+ MTRand& operator=( const MTRand& o );
+
+protected:
+ void initialize( const uint32 oneSeed );
+ void reload();
+ uint32 hiBit( const uint32 u ) const { return u & 0x80000000UL; }
+ uint32 loBit( const uint32 u ) const { return u & 0x00000001UL; }
+ uint32 loBits( const uint32 u ) const { return u & 0x7fffffffUL; }
+ uint32 mixBits( const uint32 u, const uint32 v ) const
+ { return hiBit(u) | loBits(v); }
+ uint32 magic( const uint32 u ) const
+ { return loBit(u) ? 0x9908b0dfUL : 0x0UL; }
+ uint32 twist( const uint32 m, const uint32 s0, const uint32 s1 ) const
+ { return m ^ (mixBits(s0,s1)>>1) ^ magic(s1); }
+ static uint32 hash( time_t t, clock_t c );
+};
+
+// Functions are defined in order of usage to assist inlining
+
+inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
+{
+ // Get a uint32 from t and c
+ // Better than uint32(x) in case x is floating point in [0,1]
+ // Based on code by Lawrence Kirby (fred genesis demon co uk)
+
+ static uint32 differ = 0; // guarantee time-based seeds will change
+
+ uint32 h1 = 0;
+ unsigned char *p = (unsigned char *) &t;
+ for( size_t i = 0; i < sizeof(t); ++i )
+ {
+ h1 *= UCHAR_MAX + 2U;
+ h1 += p[i];
+ }
+ uint32 h2 = 0;
+ p = (unsigned char *) &c;
+ for( size_t j = 0; j < sizeof(c); ++j )
+ {
+ h2 *= UCHAR_MAX + 2U;
+ h2 += p[j];
+ }
+ return ( h1 + differ++ ) ^ h2;
+}
+
+inline void MTRand::initialize( const uint32 seed )
+{
+ // Initialize generator state with seed
+ // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
+ // In previous versions, most significant bits (MSBs) of the seed affect
+ // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
+ register uint32 *s = state;
+ register uint32 *r = state;
+ register int i = 1;
+ *s++ = seed & 0xffffffffUL;
+ for( ; i < N; ++i )
+ {
+ *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
+ r++;
+ }
+}
+
+inline void MTRand::reload()
+{
+ // Generate N new values in state
+ // Made clearer and faster by Matthew Bellew (matthew bellew home com)
+ static const int MmN = int(M) - int(N); // in case enums are unsigned
+ register uint32 *p = state;
+ register int i;
+ for( i = N - M; i--; ++p )
+ *p = twist( p[M], p[0], p[1] );
+ for( i = M; --i; ++p )
+ *p = twist( p[MmN], p[0], p[1] );
+ *p = twist( p[MmN], p[0], state[0] );
+
+ left = N, pNext = state;
+}
+
+inline void MTRand::seed( const uint32 oneSeed )
+{
+ // Seed the generator with a simple uint32
+ initialize(oneSeed);
+ reload();
+}
+
+inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
+{
+ // Seed the generator with an array of uint32's
+ // There are 2^19937-1 possible initial states. This function allows
+ // all of those to be accessed by providing at least 19937 bits (with a
+ // default seed length of N = 624 uint32's). Any bits above the lower 32
+ // in each element are discarded.
+ // Just call seed() if you want to get array from /dev/urandom
+ initialize(19650218UL);
+ register int i = 1;
+ register uint32 j = 0;
+ register int k = ( N > seedLength ? N : seedLength );
+ for( ; k; --k )
+ {
+ state[i] =
+ state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
+ state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
+ state[i] &= 0xffffffffUL;
+ ++i; ++j;
+ if( i >= N ) { state[0] = state[N-1]; i = 1; }
+ if( j >= seedLength ) j = 0;
+ }
+ for( k = N - 1; k; --k )
+ {
+ state[i] =
+ state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
+ state[i] -= i;
+ state[i] &= 0xffffffffUL;
+ ++i;
+ if( i >= N ) { state[0] = state[N-1]; i = 1; }
+ }
+ state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
+ reload();
+}
+
+inline void MTRand::seed()
+{
+ // Seed the generator with an array from /dev/urandom if available
+ // Otherwise use a hash of time() and clock() values
+
+ // First try getting an array from /dev/urandom
+ FILE* urandom = fopen( "/dev/urandom", "rb" );
+ if( urandom )
+ {
+ uint32 bigSeed[N];
+ register uint32 *s = bigSeed;
+ register int i = N;
+ register bool success = true;
+ while( success && i-- )
+ success = fread( s++, sizeof(uint32), 1, urandom );
+ fclose(urandom);
+ if( success ) { seed( bigSeed, N ); return; }
+ }
+
+ // Was not successful, so use time() and clock() instead
+ seed( hash( time(NULL), clock() ) );
+}
+
+inline MTRand::MTRand( const uint32 oneSeed )
+ { seed(oneSeed); }
+
+inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
+ { seed(bigSeed,seedLength); }
+
+inline MTRand::MTRand()
+ { seed(); }
+
+inline MTRand::MTRand( const MTRand& o )
+{
+ register const uint32 *t = o.state;
+ register uint32 *s = state;
+ register int i = N;
+ for( ; i--; *s++ = *t++ ) {}
+ left = o.left;
+ pNext = &state[N-left];
+}
+
+inline MTRand::uint32 MTRand::randInt()
+{
+ // Pull a 32-bit integer from the generator state
+ // Every other access function simply transforms the numbers extracted here
+
+ if( left == 0 ) reload();
+ --left;
+
+ register uint32 s1;
+ s1 = *pNext++;
+ s1 ^= (s1 >> 11);
+ s1 ^= (s1 << 7) & 0x9d2c5680UL;
+ s1 ^= (s1 << 15) & 0xefc60000UL;
+ return ( s1 ^ (s1 >> 18) );
+}
+
+inline MTRand::uint32 MTRand::randInt( const uint32 n )
+{
+ // Find which bits are used in n
+ // Optimized by Magnus Jonsson (magnus smartelectronix com)
+ uint32 used = n;
+ used |= used >> 1;
+ used |= used >> 2;
+ used |= used >> 4;
+ used |= used >> 8;
+ used |= used >> 16;
+
+ // Draw numbers until one is found in [0,n]
+ uint32 i;
+ do
+ i = randInt() & used; // toss unused bits to shorten search
+ while( i > n );
+ return i;
+}
+
+inline double MTRand::rand()
+ { return double(randInt()) * (1.0/4294967295.0); }
+
+inline double MTRand::rand( const double n )
+ { return rand() * n; }
+
+inline double MTRand::randExc()
+ { return double(randInt()) * (1.0/4294967296.0); }
+
+inline double MTRand::randExc( const double n )
+ { return randExc() * n; }
+
+inline double MTRand::randDblExc()
+ { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
+
+inline double MTRand::randDblExc( const double n )
+ { return randDblExc() * n; }
+
+inline double MTRand::rand53()
+{
+ uint32 a = randInt() >> 5, b = randInt() >> 6;
+ return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
+}
+
+inline double MTRand::randNorm( const double mean, const double stddev )
+{
+ // Return a real number from a normal (Gaussian) distribution with given
+ // mean and standard deviation by polar form of Box-Muller transformation
+ double x, y, r;
+ do
+ {
+ x = 2.0 * rand() - 1.0;
+ y = 2.0 * rand() - 1.0;
+ r = x * x + y * y;
+ }
+ while ( r >= 1.0 || r == 0.0 );
+ double s = sqrt( -2.0 * log(r) / r );
+ return mean + x * s * stddev;
+}
+
+inline double MTRand::operator()()
+{
+ return rand();
+}
+
+inline void MTRand::save( uint32* saveArray ) const
+{
+ register const uint32 *s = state;
+ register uint32 *sa = saveArray;
+ register int i = N;
+ for( ; i--; *sa++ = *s++ ) {}
+ *sa = left;
+}
+
+inline void MTRand::load( uint32 *const loadArray )
+{
+ register uint32 *s = state;
+ register uint32 *la = loadArray;
+ register int i = N;
+ for( ; i--; *s++ = *la++ ) {}
+ left = *la;
+ pNext = &state[N-left];
+}
+
+inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
+{
+ register const MTRand::uint32 *s = mtrand.state;
+ register int i = mtrand.N;
+ for( ; i--; os << *s++ << "\t" ) {}
+ return os << mtrand.left;
+}
+
+inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
+{
+ register MTRand::uint32 *s = mtrand.state;
+ register int i = mtrand.N;
+ for( ; i--; is >> *s++ ) {}
+ is >> mtrand.left;
+ mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
+ return is;
+}
+
+inline MTRand& MTRand::operator=( const MTRand& o )
+{
+ if( this == &o ) return (*this);
+ register const uint32 *t = o.state;
+ register uint32 *s = state;
+ register int i = N;
+ for( ; i--; *s++ = *t++ ) {}
+ left = o.left;
+ pNext = &state[N-left];
+ return (*this);
+}
+
+#endif // MERSENNETWISTER_H
+
+// Change log:
+//
+// v0.1 - First release on 15 May 2000
+// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// - Translated from C to C++
+// - Made completely ANSI compliant
+// - Designed convenient interface for initialization, seeding, and
+// obtaining numbers in default or user-defined ranges
+// - Added automatic seeding from /dev/urandom or time() and clock()
+// - Provided functions for saving and loading generator state
+//
+// v0.2 - Fixed bug which reloaded generator one step too late
+//
+// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
+//
+// v0.4 - Removed trailing newline in saved generator format to be consistent
+// with output format of built-in types
+//
+// v0.5 - Improved portability by replacing static const int's with enum's and
+// clarifying return values in seed(); suggested by Eric Heimburg
+// - Removed MAXINT constant; use 0xffffffffUL instead
+//
+// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
+// - Changed integer [0,n] generator to give better uniformity
+//
+// v0.7 - Fixed operator precedence ambiguity in reload()
+// - Added access for real numbers in (0,1) and (0,n)
+//
+// v0.8 - Included time.h header to properly support time_t and clock_t
+//
+// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
+// - Allowed for seeding with arrays of any length
+// - Added access for real numbers in [0,1) with 53-bit resolution
+// - Added access for real numbers from normal (Gaussian) distributions
+// - Increased overall speed by optimizing twist()
+// - Doubled speed of integer [0,n] generation
+// - Fixed out-of-range number generation on 64-bit machines
+// - Improved portability by substituting literal constants for long enum's
+// - Changed license from GNU LGPL to BSD
+//
+// v1.1 - Corrected parameter label in randNorm from "variance" to "stddev"
+// - Changed randNorm algorithm from basic to polar form for efficiency
+// - Updated includes from deprecated <xxxx.h> to standard <cxxxx> forms
+// - Cleaned declarations and definitions to please Intel compiler
+// - Revised twist() operator to work on ones'-complement machines
+// - Fixed reload() function to work when N and M are unsigned
+// - Added copy constructor and copy operator from Salvador Espana
diff --git a/uulib/uudeview.h b/uulib/uudeview.h
index 8df7e9d..258ef37 100644
--- a/uulib/uudeview.h
+++ b/uulib/uudeview.h
@@ -237,7 +237,7 @@ int UUEXPORT UUEncodeToFile _ANSI_ARGS_((FILE *, char *, int,
int UUEXPORT UUE_PrepSingle _ANSI_ARGS_((FILE *, FILE *,
char *, int,
char *, int,
- char *, char *,
+ char *, char *, char*,
char *, int));
int UUEXPORT UUE_PrepPartial _ANSI_ARGS_((FILE *, FILE *,
char *, int,
@@ -249,7 +249,7 @@ int UUEXPORT UUE_PrepSingleExt _ANSI_ARGS_((FILE *, FILE *,
char *, int,
char *, int,
char *, char *,
- char *, char *,
+ char *, char *, char*,
int));
int UUEXPORT UUE_PrepPartialExt _ANSI_ARGS_((FILE *, FILE *,
char *, int,
diff --git a/uulib/uuencode.c b/uulib/uuencode.c
index c02eba3..e71f582 100644
--- a/uulib/uuencode.c
+++ b/uulib/uuencode.c
@@ -1491,13 +1491,13 @@ UUE_PrepSingle (FILE *outfile, FILE *infile,
char *infname, int encoding,
char *outfname, int filemode,
char *destination, char *from,
- char *subject, int isemail)
+ char *subject, char* mid, int isemail)
{
return UUE_PrepSingleExt (outfile, infile,
infname, encoding,
outfname, filemode,
destination, from,
- subject, NULL,
+ subject, mid, NULL,
isemail);
}
@@ -1506,7 +1506,7 @@ UUE_PrepSingleExt (FILE *outfile, FILE *infile,
char *infname, int encoding,
char *outfname, int filemode,
char *destination, char *from,
- char *subject, char *replyto,
+ char *subject, char* mid, char *replyto,
int isemail)
{
mimemap *miter=mimetable;
@@ -1547,9 +1547,9 @@ UUE_PrepSingleExt (FILE *outfile, FILE *infile,
if (encoding == YENC_ENCODED) {
if (subject)
- sprintf (subline, "- %s - %s (001/001)", oname, subject);
+ sprintf (subline, "\"%s\" - %s (001/001)", oname, subject);
else
- sprintf (subline, "- %s - (001/001)", oname);
+ sprintf (subline, "\"%s\" - (001/001)", oname);
}
else {
if (subject)
@@ -1569,6 +1569,12 @@ UUE_PrepSingleExt (FILE *outfile, FILE *infile,
fprintf (outfile, "Subject: %s%s", subline, eolstring);
+ if (mid)
+ {
+ fprintf(outfile, "Message-ID: <%s>%s", mid, eolstring);
+ }
+
+
if (replyto) {
fprintf (outfile, "Reply-To: %s%s", replyto, eolstring);
}
@@ -1709,7 +1715,7 @@ UUE_PrepPartialExt (FILE *outfile, FILE *infile,
if (infile==NULL) fclose (theifile);
return UUE_PrepSingleExt (outfile, infile, infname, encoding,
outfname, filemode, destination,
- from, subject, replyto, isemail);
+ from, subject, mid, replyto, isemail);
}
/*
@@ -1761,10 +1767,10 @@ UUE_PrepPartialExt (FILE *outfile, FILE *infile,
fprintf (outfile, "Subject: %s%s", subline, eolstring);
-// if (mid)
-// {
-// fprintf(outfile, "Message-ID: <%s>%s", mid, eolstring);
-// }
+ if (mid)
+ {
+ fprintf(outfile, "Message-ID: <%s>%s", mid, eolstring);
+ }
if (replyto) {
fprintf (outfile, "Reply-To: %s%s", replyto, eolstring);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]