1 /*
2 ** Copyright 2000-2007 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5 
6 #include	"config.h"
7 #include	"cmlmsublist.h"
8 #include	<string.h>
9 
10 static const char rcsid[]="$Id: cmlmsublist.C,v 1.5 2007/12/17 12:09:18 mrsam Exp $";
11 
SubscriberList(bool wantalias)12 SubscriberList::SubscriberList( bool wantalias)
13 	: dirp(0), next_func( wantalias ? &SubscriberList::openalias:
14 			      &SubscriberList::domain )
15 {
16 }
17 
~SubscriberList()18 SubscriberList::~SubscriberList()
19 {
20 	if (dirp)	closedir(dirp);
21 }
22 
23 //
24 // Read addresses from dedicated domain files.
25 //
26 
domain(std::string & ret)27 bool SubscriberList::domain(std::string &ret)
28 {
29 	struct	dirent *de;
30 	std::string key;
31 	std::string val;
32 
33 	if (!dirp)	dirp=opendir(DOMAINS);
34 
35 	if (domain_file.IsOpen())	// A domain file is currently open
36 	{
37 		key=domain_file.FetchNextKeyVal(val);
38 
39 		if (key.size())
40 		{
41 			ret=key;
42 			sub_info=val;
43 			return (true);
44 		}
45 
46 		domain_file.Close();
47 	}
48 
49 	// Searching for the next domain file.
50 
51 	while (dirp && (de=readdir(dirp)) != 0)
52 	{
53 		if (de->d_name[0] == '.')	continue;
54 		if (strchr(de->d_name, '.') == 0)	continue;
55 
56 		std::string filename;
57 
58 		filename=DOMAINS "/";
59 		filename += de->d_name;
60 
61 		if (domain_file.Open(filename, "R") == 0)
62 		{
63 			key=domain_file.FetchFirstKeyVal(val);
64 			if (key.size())
65 			{
66 				ret=key;
67 				sub_info=val;
68 				return (true);
69 			}
70 			domain_file.Close();
71 		}
72 	}
73 	closedir(dirp);
74 	dirp=0;
75 
76 	// Now, read the miscellaneous database
77 
78 	if (domain_file.Open(MISC, "R"))	return (false);
79 
80 	key=domain_file.FetchFirstKeyVal(val);
81 	if (key.size() == 0)
82 	{
83 		domain_file.Close();
84 		return (false);
85 	}
86 
87 	splitmisc(val, misclist);
88 	next_func= &SubscriberList::shared;
89 	return (shared(ret));
90 }
91 
splitmisc(std::string s,std::list<std::string> & misclist)92 void SubscriberList::splitmisc(std::string s,
93 			       std::list<std::string> &misclist)
94 {
95 	misclist.clear();
96 
97 	std::string::iterator b=s.begin(), e=s.end(), p=b;
98 
99 	while (b != e)
100 	{
101 		if (*b == 0)
102 		{
103 			misclist.push_back(std::string(p, b));
104 			p= ++b;
105 			continue;
106 		}
107 		++b;
108 		continue;
109 	}
110 
111 	if (p != b)
112 		misclist.push_back(std::string(p, e));
113 }
114 
joinmisc(const std::list<std::string> & misclist)115 std::string SubscriberList::joinmisc(const std::list<std::string> &misclist)
116 {
117 	std::list<std::string>::const_iterator mb, me;
118 	std::string r;
119 
120 	mb=misclist.begin();
121 	me=misclist.end();
122 
123 	while (mb != me)
124 	{
125 		r += *mb++;
126 		r.push_back((char)0);
127 	}
128 
129 	return r;
130 }
131 
132 // Read the miscellaneous database file
133 
shared(std::string & ret)134 bool SubscriberList::shared(std::string &ret)
135 {
136 	while (misclist.empty())
137 	{
138 		if (!domain_file.IsOpen())
139 			return false;
140 
141 		std::string key;
142 		std::string val;
143 
144 		key=domain_file.FetchNextKeyVal(val);
145 
146 		if (key.size() == 0)
147 		{
148 			domain_file.Close();
149 			return false;
150 		}
151 
152 		splitmisc(val, misclist);
153 	}
154 
155 	ret=misclist.front();
156 	misclist.pop_front();
157 	sub_info="";
158 
159 	if (!misclist.empty())
160 	{
161 		sub_info=misclist.front();
162 		misclist.pop_front();
163 	}
164 
165 	return true;
166 }
167 
168 // Read the alias file, instead of the subscriber database.
169 
openalias(std::string & ret)170 bool SubscriberList::openalias(std::string &ret)
171 {
172 	if (domain_file.Open( ALIASES, "R" ))	return false;
173 
174 	next_func= &SubscriberList::nextalias;
175 
176 	std::string keys, vals;
177 
178 	keys=domain_file.FetchFirstKeyVal(vals);
179 
180 	if (keys.size() == 0)
181 		return false;
182 
183 	ret=keys;
184 	posting_alias=vals;
185 
186 	if (ret.substr(0, 1) == "1")
187 		return nextalias(ret);
188 	ret=ret.substr(1);
189 
190 	return true;
191 }
192 
nextalias(std::string & ret)193 bool SubscriberList::nextalias(std::string &ret)
194 {
195 	do
196 	{
197 		std::string keys, vals;
198 
199 		keys=domain_file.FetchNextKeyVal(vals);
200 
201 		if (keys.size() == 0)
202 			return false;
203 
204 		ret=keys;
205 		posting_alias=vals;
206 	} while (ret.substr(0, 1) == "1");
207 
208 	ret=ret.substr(1);
209 	return true;
210 }
211