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

Bug#235941: [PATCH] Papercut 0.9.13 improvements



Hi!

While making a Debian package for Papercut, I made a few changes in 
Papercut that you may be interested in.

Attached is a patch that does the following:

  * Remove she-bang from module source files

    Theses Python files are not meant to be run alone, adding
    she-bangs makes lintian barf, and darcs setting +x where it
    should not.

  * Use os.path.join more extensively

    os.path.join was already used in the Maildir storage. This function
    is now used more extensively to avoid errors related to trailing
    slashes.

  * Add support to run in background

    Following Python Cookbook reciepe 6.7.  A pid file is created on
    startup and removed on exit.

  * Add support for command-line options

    Using the optparse Python module.  It allows the daemon to run in
    foreground mode using [-f | --foreground].

  * Fix a bug in article receiving

    Line separators were not stripped from articles during reading, but
    added later when joining them in do_POST.

  * Add automatic hostname detection

    If nntp_hostname is set to None, the hostname is automatically
    detected using socket.gethostname.  A fallback to 127.0.0.1
    is triggered on exceptions.

    This hostname is then resolved via socket.gethostbyname to give
    NNTPServer the correct IP address.

Also, please note that most of your your copyrights are outdated.

Thank you for this software, it's exactly what I have been looking for.

Regards,
-- 
Jérémy
--- papercut-0.9.13.orig/auth/__init__.py
+++ papercut-0.9.13/auth/__init__.py
@@ -1,3 +1,2 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: __init__.py,v 1.1 2002/04/04 23:10:20 jpm Exp $
--- papercut-0.9.13.orig/auth/mysql.py
+++ papercut-0.9.13/auth/mysql.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: mysql.py,v 1.3 2003/04/26 00:24:55 jpm Exp $
 import MySQLdb
--- papercut-0.9.13.orig/auth/postnuke_phpbb_mysql_users.py
+++ papercut-0.9.13/auth/postnuke_phpbb_mysql_users.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: postnuke_phpbb_mysql_users.py,v 1.1 2004/08/01 01:51:48 jpm Exp $
 import MySQLdb
--- papercut-0.9.13.orig/auth/phpnuke_phpbb_mysql_users.py
+++ papercut-0.9.13/auth/phpnuke_phpbb_mysql_users.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 import MySQLdb
 import settings
--- papercut-0.9.13.orig/auth/phpbb_mysql_users.py
+++ papercut-0.9.13/auth/phpbb_mysql_users.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: phpbb_mysql_users.py,v 1.4 2003/09/19 03:11:51 jpm Exp $
 import MySQLdb
--- papercut-0.9.13.orig/auth/phorum_pgsql_users.py
+++ papercut-0.9.13/auth/phorum_pgsql_users.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: phorum_pgsql_users.py,v 1.3 2004/01/14 22:26:40 jpm Exp $
 from pyPgSQL import PgSQL
--- papercut-0.9.13.orig/auth/phorum_mysql_users.py
+++ papercut-0.9.13/auth/phorum_mysql_users.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: phorum_mysql_users.py,v 1.5 2004/01/14 22:26:40 jpm Exp $
 import MySQLdb
--- papercut-0.9.13.orig/storage/phorum_pgsql.py
+++ papercut-0.9.13/storage/phorum_pgsql.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: phorum_pgsql.py,v 1.13 2004/08/01 01:51:48 jpm Exp $
 from pyPgSQL import PgSQL
@@ -10,6 +9,7 @@
 import strutil
 import smtplib
 import md5
+import os.path
 
 # patch by Andreas Wegmann <Andreas.Wegmann@VSA.de> to fix the handling of unusual encodings of messages
 q_quote_multiline = re.compile("=\?(.*?)\?[qQ]\?(.*?)\?=.*?=\?\\1\?[qQ]\?(.*?)\?=", re.M | re.S)
@@ -132,7 +132,8 @@
 
     def get_notification_emails(self, forum_id):
         # open the configuration file
-        fp = open("%s%s.php" % (settings.phorum_settings_path, forum_id), "r")
+        fp = open("%s.php" % os.path.join(settings.phorum_settings_path,
+	                                  forum_id), "r")
         content = fp.read()
         fp.close()
         # get the value of the configuration variable
@@ -186,7 +187,8 @@
         forum_id, forum_name = self.cursor.fetchone()
         forum_name.strip()
         # open the main configuration file
-        fp = open("%sforums.php" % (settings.phorum_settings_path), "r")
+        fp = open("%s.php" % os.path.join(settings.phorum_settings_path,
+	                                  'forums'), "r")
         content = fp.read()
         fp.close()
         # regexps to get the content from the phorum configuration files
--- papercut-0.9.13.orig/storage/__init__.py
+++ papercut-0.9.13/storage/__init__.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: __init__.py,v 1.4 2002/03/26 22:55:00 jpm Exp $
 
--- papercut-0.9.13.orig/storage/strutil.py
+++ papercut-0.9.13/storage/strutil.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: strutil.py,v 1.3 2003/02/22 00:46:18 jpm Exp $
 import time
--- papercut-0.9.13.orig/storage/p2p.py
+++ papercut-0.9.13/storage/p2p.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: p2p.py,v 1.2 2002/04/03 23:07:22 jpm Exp $
 import settings
--- papercut-0.9.13.orig/storage/mysql.py
+++ papercut-0.9.13/storage/mysql.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: mysql.py,v 1.44 2004/08/01 01:51:48 jpm Exp $
 import MySQLdb
--- papercut-0.9.13.orig/storage/phpbb_mysql.py
+++ papercut-0.9.13/storage/phpbb_mysql.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002, 2003, 2004 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: phpbb_mysql.py,v 1.20 2004/08/01 01:51:48 jpm Exp $
 import MySQLdb
--- papercut-0.9.13.orig/storage/phpnuke_phpbb_mysql.py
+++ papercut-0.9.13/storage/phpnuke_phpbb_mysql.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002, 2003, 2004 Joao Prado Maia. See the LICENSE file for more information.
 import MySQLdb
 import time
--- papercut-0.9.13.orig/storage/phorum_mysql.py
+++ papercut-0.9.13/storage/phorum_mysql.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: phorum_mysql.py,v 1.47 2004/08/01 01:51:48 jpm Exp $
 import MySQLdb
@@ -10,6 +9,7 @@
 import strutil
 import smtplib
 import md5
+import os.path
 
 # patch by Andreas Wegmann <Andreas.Wegmann@VSA.de> to fix the handling of unusual encodings of messages
 q_quote_multiline = re.compile("=\?(.*?)\?[qQ]\?(.*?)\?=.*?=\?\\1\?[qQ]\?(.*?)\?=", re.M | re.S)
@@ -126,7 +126,8 @@
 
     def get_notification_emails(self, forum_id):
         # open the configuration file
-        fp = open("%s%s.php" % (settings.phorum_settings_path, forum_id), "r")
+        fp = open("%s.php" % os.path.join(settings.phorum_settings_path,
+	                                  forum_id), "r")
         content = fp.read()
         fp.close()
         # get the value of the configuration variable
@@ -179,7 +180,8 @@
         self.cursor.execute(stmt)
         forum_id, forum_name = self.cursor.fetchone()
         # open the main configuration file
-        fp = open("%sforums.php" % (settings.phorum_settings_path), "r")
+        fp = open("%s.php" % os.path.join(settings.phorum_settings_path,
+	                                  'forums'), "r")
         content = fp.read()
         fp.close()
         # regexps to get the content from the phorum configuration files
--- papercut-0.9.13.orig/storage/mime.py
+++ papercut-0.9.13/storage/mime.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: mime.py,v 1.1 2002/02/03 06:15:25 jpm Exp $
 import re
--- papercut-0.9.13.orig/storage/mbox.py
+++ papercut-0.9.13/storage/mbox.py
@@ -1,8 +1,8 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: mbox.py,v 1.7 2004/08/01 01:51:48 jpm Exp $
 
 import os
+import os.path
 import mailbox
 import settings
 import strutil
@@ -19,7 +19,7 @@
         self.mbox_dir = settings.mbox_path
 
     def get_mailbox(self, filename):
-        return mailbox.PortableUnixMailbox(open(self.mbox_dir + filename))
+        return mailbox.PortableUnixMailbox(open(os.path.join(self.mbox_dir, filename)))
 
     def get_file_list(self):
         return os.listdir(self.mbox_dir)
--- papercut-0.9.13.orig/storage/maildir.py
+++ papercut-0.9.13/storage/maildir.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2004 Scott Parish, Joao Prado Maia
 # See the LICENSE file for more information.
 # $Id: maildir.py,v 1.2 2004/08/01 01:51:48 jpm Exp $
--- papercut-0.9.13.orig/storage/forwarding_proxy.py
+++ papercut-0.9.13/storage/forwarding_proxy.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 import nntplib
 import re
 import time
--- papercut-0.9.13.orig/papercut.py
+++ papercut-0.9.13/papercut.py
@@ -1,6 +1,8 @@
 #!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: papercut.py,v 1.93 2005/03/05 04:06:54 jpm Exp $
+import atexit
+import socket
 import SocketServer
 import sys
 import os
@@ -9,6 +11,7 @@
 import re
 import traceback
 import StringIO
+from optparse import OptionParser
 
 # papercut based modules
 import settings
@@ -772,7 +775,7 @@
             440 posting not allowed
             441 posting failed
         """
-        lines = "\r\n".join(self.article_lines)
+        lines = "".join(self.article_lines)
         # check the 'Newsgroups' header
         group_name = newsgroups_regexp.search(lines, 0).groups()[0].strip()
         if not backend.group_exists(group_name):
@@ -870,6 +873,24 @@
         time.sleep(1)
         sys.exit(0)
 
+    def exit_cleanup():
+        os.remove(settings.pid_file)
+
+    parser = OptionParser(version="%%prog %s" % __VERSION__)
+    parser.add_option("-f", "--foreground", action="store_false",
+                      dest="background", default=True,
+                      help="don't run in background")
+    (options, args) = parser.parse_args()
+
+    if len(args) > 0:
+        parser.print_help()
+        sys.exit(1)
+
+    # check for another papercut running
+    if os.path.exists(settings.pid_file):
+        print >>sys.stderr, "papercut seems already running."
+        sys.exit(1)
+
     # dynamic loading of the appropriate storage backend module
     temp = __import__('storage.%s' % (settings.storage_backend), globals(), locals(), ['Papercut_Storage'])
     if settings.nntp_cache == 'yes':
@@ -879,10 +900,83 @@
 
     # now for the authentication module, if needed
     if settings.nntp_auth == 'yes':
+        # check for the appropriate configuration
+        if auth_backend == '':
+            sys.exit("Please configure the 'nntp_auth' and 'auth_backend' " +
+                     "options correctly and restart Papercut.")
         temp = __import__('auth.%s' % (settings.auth_backend), globals(), locals(), ['Papercut_Auth'])
         auth = temp.Papercut_Auth()
 
+    if not settings.nntp_hostname:
+        try:
+            settings.nntp_hostname = socket.gethostname()
+        except:
+            print >>sys.stderr, (
+                "Unable to determine hostname. Using 127.0.0.1 as a " +
+                "fallback. Please set nntp_hostname in " +
+                "/etc/papercut/settings.py.")
+            settings.nntp_hostname = "127.0.0.1"
+    
+    try:
+        ip_address = socket.gethostbyname(settings.nntp_hostname)
+    except:
+        print >>sys.stderr, (
+            "Unable to lookup %s. Using 127.0.0.1 as a " +
+            "fallback. Please check nntp_hostname in " +
+            "/etc/papercut/settings.py." % settings.nntp_hostname)
+        ip_address = "127.0.0.1"
+
+    if options.background:
+        # first fork
+        try:
+            pid = os.fork()
+            if pid > 0:
+                # Exit first parent
+                sys.exit(0)
+        except OSError, e:
+            print >>sys.stderr, "fork #1 failed: %d (%s)" % (
+                                    e.errno, e.strerror)
+            sys.exit(1)
+
+        # unlink parent environment
+        fp = open('/dev/null', 'rw')
+        sys.stdin = sys.__stdin__ = fp
+        #sys.stdout = sys.__stdout__ = fp
+        #sys.stderr = sys.__stderr__ = fp
+        del fp
+        os.chdir('/')
+        os.setsid()
+        os.umask(0)
+
+        # second fork
+        try:
+            pid = os.fork()
+            if pid > 0:
+                # write pid file and exit parent process
+                fp = open(settings.pid_file, 'w')
+                fp.write("%d\n" % pid)
+                fp.close()
+                sys.exit(0)
+        except OSError, e:
+            print >>sys.stderr, "fork #2 failed: %d (%s)" % (
+                                    e.errno, e.strerror)
+            sys.exit(1)
+    else: # foreground
+        fp = open(settings.pid_file, 'w')
+        fp.write("%d\n" % os.getpid())
+        fp.close()
+
+    settings.logEvent(
+        'Papercut %s (%s storage module) - starting up (PID: %d)'
+        % (__VERSION__, settings.storage_backend, os.getpid()))
+
+    # register signal handler
+    signal.signal(signal.SIGTERM, sighandler)
     signal.signal(signal.SIGINT, sighandler)
-    print 'Papercut %s (%s storage module) - starting up' % (__VERSION__, settings.storage_backend)
-    server = NNTPServer((settings.nntp_hostname, settings.nntp_port), NNTPRequestHandler)
+    signal.signal(signal.SIGQUIT, sighandler)
+    # register cleanup function
+    atexit.register(exit_cleanup)
+
+    server = NNTPServer((ip_address, settings.nntp_port),
+                        NNTPRequestHandler)
     server.serve_forever()
--- papercut-0.9.13.orig/TODO
+++ papercut-0.9.13/TODO
@@ -4,6 +4,4 @@
 - Set the self.commands and self.extensions on the storage extensions, as some storages do not support all commands
 - MODE STREAM (it means several commands at the same time without waiting for responses)
 - Check more the patterns of searching (wildmat) -> backend.format_wildcards() -> Work in progress
-- Fork the server to the background automatically (using fork()?)
-- Make a command line option to make the server actually run on the foreground (-f option?)
 - Add a --verbose flag to replace the current __DEBUG__ flag
\ No newline at end of file
--- papercut-0.9.13.orig/portable_locker.py
+++ papercut-0.9.13/portable_locker.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # $Id: portable_locker.py,v 1.2 2002/10/03 01:05:24 jpm Exp $
 
 # Note: this was originally from Python Cookbook, which was 
--- papercut-0.9.13.orig/papercut_cache.py
+++ papercut-0.9.13/papercut_cache.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (c) 2002 Joao Prado Maia. See the LICENSE file for more information.
 # $Id: papercut_cache.py,v 1.7 2002/10/04 03:14:38 jpm Exp $
 
@@ -6,6 +5,7 @@
 import md5
 import time
 import os
+import os.path
 import cPickle
 import portable_locker
 # papercut settings file
@@ -72,7 +72,8 @@
 
     def _get_filename(self, *args, **kwds):
         arguments = '%s%s%s' % (self.name, args, kwds)
-        return '%s%s' % (settings.nntp_cache_path, binascii.hexlify(md5.new(arguments).digest()))
+        return os.path.join(settings.nntp_cache_path,
+                            binascii.hexlify(md5.new(arguments).digest()))
 
 
 class Cache:

Attachment: pgpp7ro1u6Fhe.pgp
Description: PGP signature


Reply to: