[pan] Fix titles for generated nzb



commit bbd082f73284ab55273206bc4cb08ac321f0d23e
Author: Thomas Tanner <thosrtanner googlemail com>
Date:   Mon Jul 11 20:23:03 2022 +0100

    Fix titles for generated nzb
    
    As there were 3 functions that generated NZBs (one slightly differently),
    I've taken the opportunity to refactor
    
    Fixes #76

 pan/gui/post-ui.cc |   6 +-
 pan/tasks/nzb.cc   | 267 +++++++++++++++++++++++------------------------------
 pan/tasks/nzb.h    |   5 +-
 3 files changed, 123 insertions(+), 155 deletions(-)
---
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 53f0b69..a53dd03 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -1018,7 +1018,7 @@ PostUI :: on_progress_finished (Progress&, int status) // posting finished
         if (ptr) NZB :: upload_list_to_xml_file (_out, ptr->_upload_list);
         if (_running_uploads==0 )
         {
-          _out << "</nzb>\n";
+          NZB::print_footer(_out);
           _out.close();
         }
       mut.unlock();
@@ -1204,9 +1204,7 @@ PostUI :: maybe_post_message (GMimeMessage * message)
     if (!_save_file.empty())
     {
       _out.open(_save_file.c_str(), std::fstream::out | std::fstream::app);
-      _out << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
-      << "<!DOCTYPE nzb PUBLIC \"-//newzBin//DTD NZB 1.0//EN\" 
\"http://www.newzbin.com/DTD/nzb/nzb-1.0.dtd\";>\n"
-      << "<nzb xmlns=\"http://www.newzbin.com/DTD/2003/nzb\";>\n";
+      NZB::print_header(_out);
     }
 
     std::vector<Task*> tasks;
diff --git a/pan/tasks/nzb.cc b/pan/tasks/nzb.cc
index da3d7d6..582c77b 100644
--- a/pan/tasks/nzb.cc
+++ b/pan/tasks/nzb.cc
@@ -18,12 +18,18 @@
  *
  */
 
+#include "nzb.h"
+#include "task-article.h"
+#include "task-upload.h"
+
 #include <config.h>
 #include <iostream>
 #include <fstream>
 #include <sstream>
 #include <string>
 #include <map>
+#include <regex>
+
 #include <glib.h>
 #include <pan/general/debug.h>
 #include <pan/general/file-util.h>
@@ -34,11 +40,8 @@
 #include <pan/usenet-utils/mime-utils.h>
 #include <pan/general/utf8-utils.h>
 #include <pan/data-impl/rules-filter.h>
-#include "nzb.h"
-#include "task-article.h"
-#include "task-upload.h"
 
-using namespace pan;
+namespace pan {
 
 namespace
 {
@@ -259,17 +262,102 @@ namespace
   }
 }
 
+namespace {
+
+std::ostream &print_article(
+  std::ostream &out,
+  Article const &a,
+  bool task_dump = false,
+  bool paused = false,
+  Quark const *path = nullptr)
+{
+  int depth = 1;
+  out << indent(depth++) << "<file" << " poster=\"";
+  escaped (out, a.author.to_view());
+  out  << "\" date=\"" << a.time_posted << "\" subject=\"";
+  //This is nasty. pan munges the article title of a multipart article to
+  //xxxxxxxxx (/<parts>), but nzb wants (1/<parts>)
+  std::string subject(a.subject);
+  //Not doing this for task dump as I'm not entirely sure what task dump expects
+  //to load
+  if (not task_dump)
+  {
+      subject = std::regex_replace(subject,
+                                   std::regex("\\((/[0-9]*\\))$"),
+                                   "(1$1");
+  }
+  escaped (out, subject) << "\">\n";
+
+  if (task_dump)
+  {
+    // path to save this to.
+    // This isn't part of the nzb spec.
+    if (!path->empty()) {
+      out << indent(depth) << "<path>";
+      escaped (out, path->to_view());
+      out << "</path>\n";
+    }
+
+    out << indent(depth) <<"<paused>";
+    out << paused << "</paused>\n";
+  }
+
+  // what groups was this crossposted in?
+  quarks_t groups;
+  foreach_const (Xref, a.xref, xit)
+    groups.insert (xit->group);
+  out << indent(depth++) << "<groups>\n";
+  foreach_const (quarks_t, groups, git)
+    out << indent(depth) << "<group>" << *git << "</group>\n";
+  out << indent(--depth) << "</groups>\n";
+
+  // now for the parts...
+  out << indent(depth++) << "<segments>\n";
+  for (Article::part_iterator it(a.pbegin()), end(a.pend()); it!=end; ++it)
+  {
+    std::string mid = it.mid ();
+
+    // remove the surrounding < > as per nzb spec
+    if (mid.size()>=2 && mid[0]=='<') {
+      mid.erase (0, 1);
+      mid.resize (mid.size()-1);
+    }
+
+    // serialize this part
+    out << indent(depth)
+        << "<segment" << " bytes=\"" << it.bytes() << '"'
+        << " number=\"" << it.number() << '"'
+        << ">";
+    escaped(out, mid);
+    out  << "</segment>\n";
+  }
+  out << indent(--depth) << "</segments>\n";
+  out << indent(--depth) << "</file>\n";
+  return out;
+}
+
+}
+
+std::ostream &NZB::print_header(std::ostream &out)
+{
+  out << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
+      << "<!DOCTYPE nzb PUBLIC \"-//newzBin//DTD NZB 1.0//EN\" "
+      << "\"http://www.newzbin.com/DTD/nzb/nzb-1.0.dtd\";>\n"
+      << "<nzb xmlns=\"http://www.newzbin.com/DTD/2003/nzb\";>\n";
+  return out;
+}
+
+std::ostream &NZB::print_footer(std::ostream &out)
+{
+  return out << "</nzb>\n";
+}
+
 /* Saves all current tasks to ~/.$PAN_HOME/tasks.nzb */
 std::ostream&
 NZB :: nzb_to_xml (std::ostream             & out,
                    const std::vector<Task*> & tasks)
 {
-  int depth (0);
-
-  out << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
-      << "<!DOCTYPE nzb PUBLIC \"-//newzBin//DTD NZB 1.0//EN\" 
\"http://www.newzbin.com/DTD/nzb/nzb-1.0.dtd\";>\n"
-      << indent(depth++)
-      << "<nzb xmlns=\"http://www.newzbin.com/DTD/2003/nzb\";>\n";
+  print_header(out);
 
   foreach_const (tasks_t, tasks, it)
   {
@@ -277,62 +365,20 @@ NZB :: nzb_to_xml (std::ostream             & out,
     if (task)
     {
 
-      if (task->get_save_path().empty()) // this task is for reading, not saving...
-        continue;
-
-      const Article& a (task->get_article());
-      out << indent(depth++)
-          << "<file" << " poster=\"";
-      escaped (out, a.author.to_view());
-      out  << "\" date=\"" << a.time_posted << "\" subject=\"";
-      escaped (out, a.subject.to_view()) << "\">\n";
-
-      // path to save this to.
-      // This isn't part of the nzb spec.
-      const Quark& path (task->get_save_path());
-      if (!path.empty()) {
-        out << indent(depth) << "<path>";
-        escaped (out, path.to_view());
-        out << "</path>\n";
-      }
-      out << indent(depth) <<"<paused>";
-      out << (task->start_paused()) << "</paused>\n";
-
-      // what groups was this crossposted in?
-      quarks_t groups;
-      foreach_const (Xref, a.xref, xit)
-        groups.insert (xit->group);
-      out << indent(depth++) << "<groups>\n";
-      foreach_const (quarks_t, groups, git)
-        out << indent(depth) << "<group>" << *git << "</group>\n";
-      out << indent(--depth) << "</groups>\n";
-
-      // now for the parts...
-      out << indent(depth++) << "<segments>\n";
-      for (Article::part_iterator it(a.pbegin()), end(a.pend()); it!=end; ++it)
+      if (task->get_save_path().empty())
       {
-        std::string mid = it.mid ();
-
-        // remove the surrounding < > as per nzb spec
-        if (mid.size()>=2 && mid[0]=='<') {
-          mid.erase (0, 1);
-          mid.resize (mid.size()-1);
-        }
-
-        // serialize this part
-        out << indent(depth)
-            << "<segment" << " bytes=\"" << it.bytes() << '"'
-            << " number=\"" << it.number() << '"'
-            << ">";
-        escaped(out, mid);
-        out  << "</segment>\n";
+        // this task is for reading, not saving...
+        continue;
       }
-      out << indent(--depth) << "</segments>\n";
-      out << indent(--depth) << "</file>\n";
+
+      print_article(out,
+                    task->get_article(),
+                    true,
+                    task->start_paused(),
+                    &task->get_save_path());
     }
   }
-  out << indent(--depth) << "</nzb>\n";
-  return out;
+  return print_footer(out);
 }
 
 /* Saves upload_list to XML file for distribution */
@@ -340,51 +386,12 @@ std::ostream&
 NZB :: upload_list_to_xml_file (std::ostream   & out,
                    const std::vector<Article*> & tasks)
 {
-int depth (0);
 
   foreach_const (std::vector<Article*>, tasks, it)
   {
-    Article * task (*it);
-    const Article& a (*task);
-
-    out << indent(depth++)
-        << "<file" << " poster=\"";
-    escaped (out, a.author.to_view());
-    out  << "\" date=\"" << a.time_posted << "\" subject=\"";
-    escaped (out, a.subject.to_view()) << "\">\n";
-
-    // what groups was this crossposted in?
-    quarks_t groups;
-    foreach_const (Xref, a.xref, xit)
-      groups.insert (xit->group);
-    out << indent(depth++) << "<groups>\n";
-    foreach_const (quarks_t, groups, git)
-      out << indent(depth) << "<group>" << *git << "</group>\n";
-    out << indent(--depth) << "</groups>\n";
-
-    // now for the parts...
-    out << indent(depth++) << "<segments>\n";
-    for (Article::part_iterator it(a.pbegin()), end(a.pend()); it!=end; ++it)
-    {
-      std::string mid  = it.mid ();
-
-      // remove the surrounding < > as per nzb spec
-      if (mid.size()>=2 && mid[0]=='<') {
-        mid.erase (0, 1);
-        mid.resize (mid.size()-1);
-      }
-
-      // serialize this part
-      out << indent(depth)
-          << "<segment" << " bytes=\"" << it.bytes() << '"'
-                        << " number=\"" << it.number() << '"'
-                        << ">";
-      escaped(out, mid);
-      out  << "</segment>\n";
-    }
-    out << indent(--depth) << "</segments>\n";
-    out << indent(--depth) << "</file>\n";
+    print_article(out, **it);
   }
+
   return out;
 }
 
@@ -393,60 +400,22 @@ std::ostream&
 NZB :: nzb_to_xml_file (std::ostream        & out,
                    const std::vector<Task*> & tasks)
 {
-  int depth (0);
-
-  out << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
-      << "<!DOCTYPE nzb PUBLIC \"-//newzBin//DTD NZB 1.0//EN\" 
\"http://www.newzbin.com/DTD/nzb/nzb-1.0.dtd\";>\n"
-      << indent(depth++)
-      << "<nzb xmlns=\"http://www.newzbin.com/DTD/2003/nzb\";>\n";
+  print_header(out);
 
   foreach_const (tasks_t, tasks, it)
   {
     TaskArticle * task (dynamic_cast<TaskArticle*>(*it));
-    if (!task) // not a download task, for example an upload task...
-      continue;
-
-    const Article& a (task->get_article());
-    out << indent(depth++)
-        << "<file" << " poster=\"";
-    escaped (out, a.author.to_view());
-    out  << "\" date=\"" << a.time_posted << "\" subject=\"";
-    escaped (out, a.subject.to_view()) << "\">\n";
 
-    // what groups was this crossposted in?
-    quarks_t groups;
-    foreach_const (Xref, a.xref, xit)
-      groups.insert (xit->group);
-    out << indent(depth++) << "<groups>\n";
-    foreach_const (quarks_t, groups, git)
-      out << indent(depth) << "<group>" << *git << "</group>\n";
-    out << indent(--depth) << "</groups>\n";
-
-    // now for the parts...
-    out << indent(depth++) << "<segments>\n";
-    for (Article::part_iterator it(a.pbegin()), end(a.pend()); it!=end; ++it)
+    if (!task)
     {
-      std::string mid = it.mid ();
-
-      // remove the surrounding < > as per nzb spec
-      if (mid.size()>=2 && mid[0]=='<') {
-        mid.erase (0, 1);
-        mid.resize (mid.size()-1);
-      }
-
-      // serialize this part
-      out << indent(depth)
-          << "<segment" << " bytes=\""  << it.bytes() << '"'
-                        << " number=\"" << it.number() << '"'
-                        << ">";
-      escaped(out, mid);
-      out  << "</segment>\n";
+      // not a download task, for example an upload task...
+      continue;
     }
-    out << indent(--depth) << "</segments>\n";
-    out << indent(--depth) << "</file>\n";
+
+    print_article(out, task->get_article());
   }
 
-  out << indent(--depth) << "</nzb>\n";
-  return out;
+  return print_footer(out);
 }
 
+}
diff --git a/pan/tasks/nzb.h b/pan/tasks/nzb.h
index d3b2035..57da27d 100644
--- a/pan/tasks/nzb.h
+++ b/pan/tasks/nzb.h
@@ -20,10 +20,9 @@
 #ifndef __NZB_H__
 #define __NZB_H__
 
+#include <iosfwd>
 #include <vector>
 #include <pan/data/data.h>
-#include <pan/usenet-utils/MersenneTwister.h>
-#include <unistd.h>
 
 namespace pan
 {
@@ -64,7 +63,9 @@ namespace pan
     static std::ostream&  nzb_to_xml_file (std::ostream             & out,
                                            const std::vector<Task*> & tasks);
 
+    static std::ostream &print_header(std::ostream &out);
 
+    static std::ostream &print_footer(std::ostream &out);
 
   };
 }


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