Hi,
next patch:
* mixminion client now supports --followup-to=news.group (loosely
checked for syntactic validity) and --x-no-archive (boolean).
* delivery modules now support "FromTag" and "SubjectTag", each
prepended to (if user-specified) from name resp. subject line.
* mixminion server now rejects out-of-order headers (found this
one in the end-to-end spec).
===== Beginn =====
Index: Common.py
===================================================================
--- Common.py (revision 6)
+++ Common.py (working copy)
@@ -1533,8 +1533,8 @@
#----------------------------------------------------------------------
-# A single newsgroup is a sequence of dot-separated atoms.
-_SINGLE_NEWSGROUP_PAT = r"(?:%s)(?:\.(?:%s))*" % (_ATOM_PAT, _ATOM_PAT)
+# A single newsgroup is a sequence of at least two dot-separated atoms.
+_SINGLE_NEWSGROUP_PAT = r"(?:%s)(?:\.(?:%s))+" % (_ATOM_PAT, _ATOM_PAT)
# A list of newsgroups is a sequence of comma-separated newsgroups.
_NEWSGROUPS_PAT = r"\A%s(,%s)*\Z" % (_SINGLE_NEWSGROUP_PAT, _SINGLE_NEWSGROUP_PAT)
NEWSGROUPS_RE = re.compile(_NEWSGROUPS_PAT)
Index: Packet.py
===================================================================
--- Packet.py (revision 6)
+++ Packet.py (working copy)
@@ -869,7 +869,7 @@
MAX_HEADER_LEN = 900
def encodeMailHeaders(subject=None, fromAddr=None, inReplyTo=None,
- references=None):
+ references=None, followupTo=None, xNoArchive=0):
"""Given (optionally) any of the headers permissible for email
messages, return a string to be prepended to a message before
encoding. Raise MixError on failure."""
@@ -886,6 +886,12 @@
headers['IN-REPLY-TO'] = inReplyTo
if references:
headers['REFERENCES'] = references
+ if followupTo:
+ if not isNewsgroups(followupTo):
+ raise MixError("Invalid followup-to %r " % followupTo)
+ headers['FOLLOWUP-TO'] = followupTo
+ if xNoArchive:
+ headers['X-NO-ARCHIVE'] = 'yes'
return encodeMessageHeaders(headers)
def encodeMessageHeaders(headers):
@@ -915,16 +921,20 @@
Skips improperly formatted headers."""
headers = {}
msg = message
+ previous = None
while 1:
if msg[0] == '\n':
return msg[1:], headers
m = HEADER_RE.match(msg)
if m:
k,v = m.groups()
- if len(v) > MAX_HEADER_LEN:
+ if previous and k < previous:
+ LOG.warn("Rejecting out-of-order exit header %r:%r...",k,v[:30])
+ elif len(v) > MAX_HEADER_LEN:
LOG.warn("Rejecting overlong exit header %r:%r...",k,v[:30])
else:
headers[k] = v
+ previous = k
msg = msg[m.end():]
else:
LOG.warn("Could not parse headers on message; not using them.")
Index: server/Modules.py
===================================================================
--- server/Modules.py (revision 6)
+++ server/Modules.py (working copy)
@@ -962,6 +962,7 @@
# subject: Default subject to use for outgoing mail, if none is given
# in the message.
# fromTag: String to prepend to from name.
+ # subjectTag: String to prepend to subject.
# returnAddress: Return address for mail; should be an rfc822-style
# mailbox.
# header: Text that should be appended after the headers and before
@@ -983,6 +984,7 @@
'MessageHeader' : ('ALLOW', None, None),
'MessageFooter' : ('ALLOW', None, None),
'FromTag' : ('ALLOW', None, "[Anon]"),
+ 'SubjectTag' : ('ALLOW', None, None),
'ReturnAddress' : ('ALLOW', None, None),
}
@@ -998,7 +1000,13 @@
return None
headers = packet.getHeaders()
- subject = headers.get("SUBJECT", self.subject)
+ if headers.has_key("SUBJECT"):
+ if self.subjectTag:
+ subject = "%s %s" % (self.subjectTag, headers.get("SUBJECT"))
+ else:
+ subject = headers.get("SUBJECT")
+ else:
+ subject = self.subject
fromAddr = headers.get("FROM")
if fromAddr and self.allowFromAddr:
fromAddr = '"%s %s" <%s>' % (self.fromTag, fromAddr,
@@ -1008,14 +1016,25 @@
morelines = []
if mixminion.Packet.NEWS_TYPE in self.getExitTypes():
- newsgroups = packet.getAddress()
- if isNewsgroups(newsgroups):
- if newsgroups.count(',') > MAX_NEWSGROUPS-1:
- LOG.warn("Dropping excessive crossposting: %s" % newsgroups)
- return None
- morelines.append("Newsgroups: %s\n" % newsgroups)
+ newsgroups = packet.getAddress().lower()
+ if not isNewsgroups(newsgroups):
+ LOG.warn("Invalid newsgroups: %s" % newsgroups)
+ return None
else:
- LOG.warn("Invalid newsgroups: %s" % newsgroups)
+ if newsgroups.count(',') > MAX_NEWSGROUPS-1:
+ LOG.warn("Dropping excessive crossposting: %s" % newsgroups)
+ return None
+ morelines.append("Newsgroups: %s\n" % newsgroups)
+
+ if headers.has_key("FOLLOWUP-TO"):
+ followupto = headers['FOLLOWUP-TO'].lower()
+ if not isNewsgroups(followupto):
+ LOG.warn("Invalid followup-to: %s" % followupto)
+ else:
+ morelines.append("Followup-To: %s\n" % followupto)
+ if headers.has_key("X-NO-ARCHIVE"):
+ morelines.append("X-No-Archive: yes\n")
+
if headers.has_key("IN-REPLY-TO"):
morelines.append("In-Reply-To: %s\n" % headers['IN-REPLY-TO'])
if headers.has_key("REFERENCES"):
@@ -1141,7 +1160,8 @@
# These fields are needed by MailBase
self.initializeHeaders(sec)
- self.fromTag = "[Anon]"
+ self.fromTag = sec.get('FromTag', "[Anon]")
+ self.subjectTag = sec.get('SubjectTag', "")
# Enable module
moduleManager.enableModule(self)
@@ -1268,7 +1288,8 @@
# These fields are needed by MailBase
self.initializeHeaders(sec)
- self.fromTag = "[Anon]"
+ self.fromTag = sec.get('FromTag', "[Anon]")
+ self.subjectTag = sec.get('SubjectTag', "")
# Parse the address file.
self.addresses = {}
@@ -1420,6 +1441,7 @@
self.blacklist = None
self.returnAddress = sec['ReturnAddress']
self.fromTag = sec.get('FromTag', "[Anon]")
+ self.subjectTag = sec.get('SubjectTag', "")
self.allowFromAddr = sec['AllowFromAddress']
self.armorPlaintext = sec['ArmorPlaintext']
@@ -1504,6 +1526,7 @@
self.server = sec['Server']
self.retrySchedule = sec['Retry']
self.fromTag = sec.get('FromTag', "[Anon]")
+ self.subjectTag = sec.get('SubjectTag', "")
self.allowFromAddr = sec['AllowFromAddress']
self.armorPlaintext = sec['ArmorPlaintext']
self.command = cmd[0]
Index: ClientMain.py
===================================================================
--- ClientMain.py (revision 6)
+++ ClientMain.py (working copy)
@@ -1079,7 +1079,7 @@
shortOpts += "P:H:"
longOpts += ["path=","hops="]
if headers:
- longOpts += ["subject=", "from=", "in-reply-to=", "references="]
+ longOpts += ["subject=", "from=", "in-reply-to=", "references=", "followup-to=", "x-no-archive"]
if dest:
shortOpts += "t:"
longOpts += ["to="]
@@ -1115,6 +1115,8 @@
or '-' for a reply block read from stdin.
--subject=<str>, --from=<str>, --in-reply-to=<str>, --references=<str>
Specify an email header for the exiting message.
+ --followup-to=<str>, --x-no-archive
+ Specify a news header for the exiting message.
--deliver-fragments If the message is too long to fit in a single
packet, then deliver multiple fragmented packets
to the recipient instead of having the server
@@ -1194,7 +1196,8 @@
sendUsageAndExit(cmd)
inFile = '-'
- h_subject = h_from = h_irt = h_references = None
+ h_subject = h_from = h_irt = h_references = h_fut = None
+ h_xna = 0
no_ss_fragment = 0
for opt,val in options:
if opt in ('-i', '--input'):
@@ -1207,6 +1210,10 @@
h_irt = val
elif opt == '--references':
h_references = val
+ elif opt == '--followup-to':
+ h_fut = val
+ elif opt == '--x-no-archive':
+ h_xna = 1
elif opt == '--deliver-fragments':
no_ss_fragment = 1
@@ -1226,7 +1233,8 @@
# they won't work.
try:
headerStr = encodeMailHeaders(subject=h_subject, fromAddr=h_from,
- inReplyTo=h_irt, references=h_references)
+ inReplyTo=h_irt, references=h_references,
+ followupTo=h_fut, xNoArchive=h_xna)
except MixError, e:
raise UIError("Invalid headers: %s"%e)
if no_ss_fragment:
@@ -1311,6 +1319,8 @@
-i <file>, --input=<file> Read the message from <file>. (Defaults to stdin.)
--subject=<str>, --from=<str>, --in-reply-to=<str>, --references=<str>
Specify an email header for the exiting message.
+ --followup-to=<str>, --x-no-archive
+ Specify a news header for the exiting message.
--deliver-fragments If the message is too long to fit in a single
packet, then deliver multiple fragmented packets
to the recipient instead of having the server
@@ -1323,7 +1333,8 @@
input=1, headers=1)
inFile = '-'
- h_subject = h_from = h_irt = h_references = None
+ h_subject = h_from = h_irt = h_references = h_fut = None
+ h_xna = 0
no_ss_fragment = 0
reply = 0
for opt,val in options:
@@ -1337,6 +1348,10 @@
h_irt = val
elif opt == '--references':
h_references = val
+ elif opt == '--followup-to':
+ h_fut = val
+ elif opt == '--x-no-archive':
+ h_xna = 1
elif opt == '--deliver-fragments':
no_ss_fragment = 1
elif opt in ('-R', '--reply'):
@@ -1353,7 +1368,8 @@
# they won't work.
try:
headerStr = encodeMailHeaders(subject=h_subject, fromAddr=h_from,
- inReplyTo=h_irt, references=h_references)
+ inReplyTo=h_irt, references=h_references,
+ followupTo=h_fut, xNoArchive=h_xna)
except MixError, e:
raise UIError("Invalid headers: %s"%e)
if no_ss_fragment:
===== Ende =====
Ciao
Tobias
--
mbox:admin@tainaron
Attachment:
pgplnbFRIP3nH.pgp
Description: PGP signature