author | Mahlon E. Smith <mahlon@martini.nu> |
Fri, 03 Feb 2017 10:52:46 -0800 | |
changeset 13 | a03c08c289e9 |
parent 12 | 3cc813140c80 |
child 14 | cba9fb39bcdb |
permissions | -rw-r--r-- |
1
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
1 |
#!/usr/bin/ruby |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
2 |
# vim: set nosta noet ts=4 sw=4: |
1
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
3 |
# |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
4 |
# A Ruby interface to a single Ezmlm-idx mailing list directory. |
1
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
5 |
# |
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
6 |
# == Version |
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
7 |
# |
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
8 |
# $Id$ |
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
9 |
# |
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
10 |
#--- |
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
11 |
|
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
12 |
require 'pathname' |
13 | 13 |
require 'etc' |
1
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
14 |
require 'ezmlm' |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
15 |
require 'mail' |
1
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
16 |
|
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
17 |
|
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
18 |
### A Ruby interface to an ezmlm-idx mailing list directory |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
19 |
### |
1
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
20 |
class Ezmlm::List |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
21 |
|
13 | 22 |
# Quick address space detection, to (hopefully) |
23 |
# match the overflow size on this machine. |
|
24 |
# |
|
25 |
ADDRESS_SPACE = case [ 'i' ].pack( 'p' ).size |
|
26 |
when 4 |
|
27 |
32 |
|
28 |
when 8 |
|
29 |
64 |
|
30 |
end |
|
31 |
||
32 |
# Valid subdirectories/sections for subscriptions. |
|
33 |
SUBSCRIPTION_DIRS = %w[ deny mod digest allow ] |
|
34 |
||
35 |
||
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
36 |
### Create a new Ezmlm::List object for the specified +listdir+, which should be |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
37 |
### an ezmlm-idx mailing list directory. |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
38 |
### |
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
39 |
def initialize( listdir ) |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
40 |
listdir = Pathname.new( listdir ) unless listdir.is_a?( Pathname ) |
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
41 |
@listdir = listdir |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
42 |
end |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
43 |
|
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
44 |
# The Pathname object for the list directory |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
45 |
attr_reader :listdir |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
46 |
|
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
47 |
|
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
48 |
### Return the configured name of the list (without the host) |
13 | 49 |
### |
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
50 |
def name |
13 | 51 |
@name = self.read( 'outlocal' ) unless @name |
52 |
return @name |
|
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
53 |
end |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
54 |
|
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
55 |
|
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
56 |
### Return the configured host of the list |
13 | 57 |
### |
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
58 |
def host |
13 | 59 |
@host = self.read( 'outhost' ) unless @host |
60 |
return @host |
|
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
61 |
end |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
62 |
|
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
63 |
|
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
64 |
### Return the configured address of the list (in list@host form) |
13 | 65 |
### |
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
66 |
def address |
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
67 |
return "%s@%s" % [ self.name, self.host ] |
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
68 |
end |
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
69 |
alias_method :fullname, :address |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
70 |
|
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
71 |
|
13 | 72 |
### Return the email address of the list's owner. |
73 |
### |
|
74 |
def owner |
|
75 |
owner = self.read( 'owner' ) |
|
76 |
return owner =~ /@/ ? owner : nil |
|
77 |
end |
|
78 |
||
79 |
||
80 |
### Return the number of messages in the list archive. |
|
81 |
### |
|
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
82 |
def message_count |
13 | 83 |
count = self.read( 'archnum' ) |
84 |
return count ? Integer( count ) : 0 |
|
85 |
end |
|
86 |
||
87 |
||
88 |
### Fetch a sorted Array of the email addresses for all of the list's |
|
89 |
### subscribers. |
|
90 |
### |
|
91 |
def subscribers |
|
92 |
return self.read_subscriber_dir |
|
93 |
end |
|
94 |
||
95 |
||
96 |
### Returns an Array of email addresses of people responsible for |
|
97 |
### moderating subscription of a closed list. |
|
98 |
### |
|
99 |
def moderators |
|
100 |
return self.read_subscriber_dir( 'mod' ) |
|
101 |
end |
|
102 |
||
103 |
||
104 |
### Subscribe +addr+ to the list as a Moderator. |
|
105 |
### |
|
106 |
def add_moderator( *addr ) |
|
107 |
return self.subscribe( *addr, section: 'mod' ) |
|
108 |
end |
|
109 |
||
110 |
||
111 |
### Remove +addr+ from the list as a Moderator. |
|
112 |
### |
|
113 |
def remove_moderator( *addr ) |
|
114 |
return self.unsubscribe( *addr, section: 'mod' ) |
|
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
115 |
end |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
116 |
|
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
117 |
|
13 | 118 |
### Returns +true+ if +address+ is a subscriber to this list. |
119 |
### |
|
120 |
def include?( addr ) |
|
121 |
addr.downcase! |
|
122 |
file = self.subscription_dir + self.hashchar( addr ) |
|
123 |
return false unless file.exist? |
|
124 |
return file.read.scan( /T([^\0]+)\0/ ).flatten.include?( addr ) |
|
125 |
end |
|
126 |
||
127 |
||
128 |
### Subscribe +addr+ to the list within +section+. |
|
129 |
### |
|
130 |
def subscribe( *addr, section: nil ) |
|
131 |
addr.each do |address| |
|
132 |
next unless address.index( '@' ) |
|
133 |
address.downcase! |
|
134 |
||
135 |
file = self.subscription_dir( section ) + self.hashchar( address ) |
|
136 |
self.with_safety do |
|
137 |
if file.exist? |
|
138 |
addresses = file.read.scan( /T([^\0]+)\0/ ).flatten |
|
139 |
addresses << address |
|
140 |
file.open( 'w' ) do |f| |
|
141 |
f.print addresses.uniq.sort.map{|a| "T#{a}\0" }.join |
|
142 |
end |
|
143 |
||
144 |
else |
|
145 |
file.open( 'w' ) do |f| |
|
146 |
f.print "T%s\0" % [ address ] |
|
147 |
end |
|
148 |
end |
|
149 |
end |
|
150 |
end |
|
151 |
end |
|
152 |
||
153 |
||
154 |
### Unsubscribe +addr+ from the list within +section+. |
|
155 |
### |
|
156 |
def unsubscribe( *addr, section: nil ) |
|
157 |
addr.each do |address| |
|
158 |
address.downcase! |
|
159 |
||
160 |
file = self.subscribers_dir( section ) + self.hashchar( address ) |
|
161 |
self.with_safety do |
|
162 |
next unless file.exist? |
|
163 |
addresses = file.read.scan( /T([^\0]+)\0/ ).flatten |
|
164 |
addresses = addresses - [ address ] |
|
165 |
||
166 |
if addresses.empty? |
|
167 |
file.unlink |
|
168 |
else |
|
169 |
file.open( 'w' ) do |f| |
|
170 |
f.print addresses.uniq.sort.map{|a| "T#{a}\0" }.join |
|
171 |
end |
|
172 |
end |
|
173 |
end |
|
174 |
end |
|
175 |
end |
|
176 |
||
177 |
||
178 |
=begin |
|
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
179 |
### Return the Date parsed from the last post to the list. |
13 | 180 |
### |
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
181 |
def last_message_date |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
182 |
mail = self.last_post or return nil |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
183 |
return mail.date |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
184 |
end |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
185 |
|
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
186 |
|
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
187 |
### Return the author of the last post to the list. |
13 | 188 |
### |
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
189 |
def last_message_author |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
190 |
mail = self.last_post or return nil |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
191 |
return mail.from |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
192 |
end |
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
193 |
|
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
194 |
|
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
195 |
### Returns +true+ if subscription to the list is moderated. |
13 | 196 |
### |
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
197 |
def closed? |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
198 |
return (self.listdir + 'modsub').exist? || (self.listdir + 'remote').exist? |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
199 |
end |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
200 |
|
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
201 |
|
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
202 |
### Returns +true+ if posting to the list is moderated. |
13 | 203 |
### |
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
204 |
def moderated? |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
205 |
return (self.listdir + 'modpost').exist? |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
206 |
end |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
207 |
|
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
208 |
|
13 | 209 |
### Return a Mail::Message object loaded from the last post to the list. Returns |
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
210 |
### +nil+ if there are no archived posts. |
13 | 211 |
### |
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
212 |
def last_post |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
213 |
archivedir = self.listdir + 'archive' |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
214 |
return nil unless archivedir.exist? |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
215 |
|
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
216 |
# Find the last numbered directory under the archive dir |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
217 |
last_archdir = Pathname.glob( archivedir + '[0-9]*' ). |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
218 |
sort_by {|pn| Integer(pn.basename.to_s) }.last |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
219 |
|
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
220 |
return nil unless last_archdir |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
221 |
|
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
222 |
# Find the last numbered file under the last numbered directory we found |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
223 |
# above. |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
224 |
last_post_path = Pathname.glob( last_archdir + '[0-9]*' ). |
5
804e1c2b9a40
* Added rdoc-generation to the cruise task and the artifacts that get saved
Michael Granger <mgranger@laika.com>
parents:
4
diff
changeset
|
225 |
sort_by {|pn| pn.basename.to_s }.last |
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
226 |
|
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
227 |
raise RuntimeError, "unexpectedly empty archive directory '%s'" % [ last_archdir ] \ |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
228 |
unless last_post_path |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
229 |
|
13 | 230 |
require 'pry' |
231 |
binding.pry |
|
4
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
232 |
last_post = TMail::Mail.load( last_post_path.to_s ) |
8c4ae0797d5f
Added more archive-related functions:
Michael Granger <mgranger@laika.com>
parents:
2
diff
changeset
|
233 |
end |
13 | 234 |
=end |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
235 |
|
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
236 |
|
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
237 |
######### |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
238 |
protected |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
239 |
######### |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
240 |
|
13 | 241 |
### Hash an email address, using the ezmlm algorithm for |
242 |
### fast user lookups. Returns the hashed integer. |
|
243 |
### |
|
244 |
### Older ezmlm didn't lowercase addresses, anything within the last |
|
245 |
### decade did. We're not going to worry about compatibility there. |
|
246 |
### |
|
247 |
### (See subhash.c in the ezmlm source.) |
|
248 |
### |
|
249 |
def subhash( addr ) |
|
250 |
h = 5381 |
|
251 |
over = 2 ** ADDRESS_SPACE |
|
252 |
||
253 |
addr = 'T' + addr |
|
254 |
addr.each_char do |c| |
|
255 |
h = ( h + ( h << 5 ) ) ^ c.ord |
|
256 |
h = h % over if h > over # emulate integer overflow |
|
257 |
end |
|
258 |
return h % 53 |
|
259 |
end |
|
260 |
||
261 |
||
262 |
### Given an email address, return the ascii character. |
|
263 |
### |
|
264 |
def hashchar( addr ) |
|
265 |
return ( self.subhash(addr) + 64 ).chr |
|
266 |
end |
|
267 |
||
268 |
||
269 |
### Just return the contents of the provided +file+, rooted |
|
270 |
### in the list directory. |
|
271 |
### |
|
272 |
def read( file ) |
|
273 |
file = self.listdir + file unless file.is_a?( Pathname ) |
|
274 |
return file.read.chomp |
|
275 |
rescue |
|
276 |
nil |
|
277 |
end |
|
278 |
||
279 |
||
280 |
### Return a Pathname to a subscription directory. |
|
281 |
### |
|
282 |
def subscription_dir( section=nil ) |
|
283 |
section = nil if section && ! SUBSCRIPTION_DIRS.include?( section ) |
|
284 |
||
285 |
if section |
|
286 |
return self.listdir + section + 'subscribers' |
|
287 |
else |
|
288 |
return self.listdir + 'subscribers' |
|
289 |
end |
|
290 |
end |
|
291 |
||
292 |
||
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
293 |
### Read the hashed subscriber email addresses from the specified +directory+ and return them in |
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
294 |
### an Array. |
13 | 295 |
### |
296 |
def read_subscriber_dir( section=nil ) |
|
297 |
directory = self.subscription_dir( section ) |
|
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
298 |
rval = [] |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
299 |
Pathname.glob( directory + '*' ) do |hashfile| |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
300 |
rval.push( hashfile.read.scan(/T([^\0]+)\0/) ) |
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
301 |
end |
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
302 |
|
13 | 303 |
return rval.flatten.sort |
304 |
end |
|
305 |
||
306 |
||
307 |
### Return a Pathname object for the list owner's home directory. |
|
308 |
### |
|
309 |
def homedir |
|
310 |
user = Etc.getpwuid( self.listdir.stat.uid ) |
|
311 |
return Pathname( user.dir ) |
|
312 |
end |
|
313 |
||
314 |
||
315 |
### Safely make modifications to a file within a list directory. |
|
316 |
### |
|
317 |
### Mail can come in at any time. Make changes within a list |
|
318 |
### atomic -- if an incoming message hits when a sticky |
|
319 |
### is set, it is deferred to the Qmail queue. |
|
320 |
### |
|
321 |
### - Set sticky bit on the list directory owner's homedir |
|
322 |
### - Make changes with the block |
|
323 |
### - Unset sticky (just back to what it was previously) |
|
324 |
### |
|
325 |
### All writes should be wrapped in this method. |
|
326 |
### |
|
327 |
def with_safety( &block ) |
|
328 |
home = self.homedir |
|
329 |
mode = home.stat.mode |
|
330 |
||
331 |
home.chmod( mode | 01000 ) # enable sticky |
|
332 |
yield |
|
333 |
||
334 |
ensure |
|
335 |
home.chmod( mode ) |
|
2
7b5a0131d5cd
Added more list-config accessors
Michael Granger <mgranger@laika.com>
parents:
1
diff
changeset
|
336 |
end |
1
1d3cfd4837a8
Filled out the project, added Ezmlm module + spec.
Michael Granger <mgranger@laika.com>
parents:
diff
changeset
|
337 |
|
12
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
338 |
end # class Ezmlm::List |
3cc813140c80
First round of modernizing after a long absence.
Mahlon E. Smith <mahlon@martini.nu>
parents:
5
diff
changeset
|
339 |