copyright and license notices; added -status directive
[python-rwhoisd.git] / rwhoisd / DirectiveProcessor.py
1 # This file is part of python-rwhoisd
2 #
3 # Copyright (C) 2003, David E. Blacka
4 #
5 # $Id: DirectiveProcessor.py,v 1.2 2003/04/28 16:43:37 davidb Exp $
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 # USA
21
22 import re
23 import Rwhois, config
24
25 class DirectiveProcessor:
26
27     rwhois_dir_exp = re.compile(r"V-(\d+\.\d+)", re.I)
28
29     def __init__(self, db):
30         self.db = db
31         self.directives = {
32             "rwhois" : self.rwhois_directive,
33             "limit"  : self.limit_directive,
34             "holdconnect" : self.hold_directive,
35             "directive" : self.directive_directive,
36             "xfer" : self.xfer_directive,
37             "status" : self.status_directive
38             }
39
40     def process_directive(self, session, line):
41         d_args = line.lstrip("-").split()
42
43         if not self.directives.has_key(d_args[0]):
44             session.wfile.write(Rwhois.error_message(400))
45             return
46
47         self.directives[d_args[0]](session, d_args[1:])
48
49
50     def rwhois_directive(self, session, arglist):
51         if not arglist:
52             session.wfile.write(Rwhois.error_message(338))
53             return
54         
55         mo = DirectiveProcessor.rwhois_dir_exp.match(arglist[0])
56         if not mo:
57             session.wfile.write(Rwhois.error_message(338))
58             return
59
60         # normally we would make sure that the version given was
61         # sufficiently great.
62
63         session.wfile.write(config.banner_string)
64         session.wfile.write("\r\n")
65
66     def limit_directive(self, session, arglist):
67         try:
68             limit = int(arglist[0])
69         except (IndexError, ValueError):
70             session.wfile.write(Rwhois.error_message(338))
71             return
72         
73         if limit > config.max_limit:
74             limit = config.max_limit
75         elif limit < config.min_limit:
76             limit = config.min_limit
77         session.limit = limit
78
79         session.wfile.write(Rwhois.ok())
80
81     def hold_directive(self, session, arglist):
82         if not arglist:
83             session.wfile.write(Rwhois.error_message(338))
84             return
85         
86         arg = arglist[0].lower()
87         if arg == "on":
88             session.holdconnect = True
89         elif arg == "off":
90             session.holdconnect = False
91         else:
92             session.wfile.write(Rwhois.error_message(338))
93             return
94         
95         session.wfile.write(Rwhois.ok())
96
97     def directive_directive(self, session, arglist):
98         if not arglist:
99             reslist = []
100             dirs = self.directives.keys()
101             dirs.sort()
102             for dir in dirs:
103                 desc = dir.capitalize()
104                 reslist.append("%%directive directive:%s" % dir)
105                 reslist.append("%%directive description:%s directive" % desc)
106             session.wfile.write("\r\n".join(reslist))
107             session.wfile.write("\r\n")
108             session.wfile.write(Rwhois.ok())
109             return
110         if self.directives.has_key(arglist[0]):
111             dir = arglist[0]
112             desc = dir.capitalize()
113             session.wfile.write("%%directive directive:%s\r\n" % dir)
114             session.wfile.write("%%directive description:%s directive\r\n"
115                                 % desc)
116         else:
117             session.wfile.write(Rwhois.error_message(400))
118             return
119         session.wfile.write(Rwhois.ok())
120
121
122     def status_directive(self, session, arglist):
123         if session.holdconnect:
124             hc_str = "on"
125         else:
126             hc_str = "off"
127
128         session.wfile.write("%%status limit: %d\r\n" % session.limit)
129         session.wfile.write("%%status holdconnect: %s\r\n" % hc_str)
130         session.wfile.write("%status forward: off\r\n")
131         session.wfile.write("%%status objects: %d\r\n" 
132                             % len(self.db.main_index))
133         session.wfile.write("%status display: dump\r\n")
134         session.wfile.write("%status contact: N/A\r\n")
135         session.wfile.write(Rwhois.ok())
136         
137     def xfer_directive(self, session, arglist):
138         if not arglist:
139             session.wfile.write(Rwhois.error_message(338))
140             return
141         
142         aa = arglist[0].lower()
143
144         oc = None
145         attr_list = []
146         for arg in arglist[1:]:
147             if arg.startswith("class="):
148                 oc = arg[6:].lower()
149             elif arg.startswith("attribute="):
150                 attr = arg[10:].lower()
151                 if attr: attr_list.append(attr)
152
153         # check the constraints
154         if not self.db.is_autharea(aa):
155             session.wfile.write(Rwhois.error_message((340, aa)))
156             return
157         if oc and not self.db.is_objectclass(oc):
158             session.wfile.write(Rwhois.error_message((341, oc)))
159             return
160
161         for attr in attr_list:
162             if not self.db.is_attribute(attr):
163                 session.wfile.write(Rwhois.error_message((342, attr)))
164                 return
165
166         # now iterate over the entire dataset looking for objects that
167         # match our criteria.
168
169         objs = self.db.object_iterator()
170
171         for obj in objs:
172             # Note: in theory, we should leverage QueryProcessors
173             # filtering code.
174             if obj.get_attr_value("auth-area").lower() != aa:
175                 continue
176             if oc and obj.get_attr_value("class-name").lower() != oc:
177                 continue
178
179             if attr_list:
180                 session.wfile.write(obj.attrs_to_wire_str(attr_list, "%xfer "))
181             else:
182                 session.wfile.write(obj.to_wire_str("%xfer "))
183             session.wfile.write("\r\n%xfer \r\n");
184             
185         session.wfile.write(Rwhois.ok())
186         
187
188 if __name__ == '__main__':
189
190     import sys
191     import MemDB
192     
193     session = Session.Context()
194     session.wfile = sys.stdout
195
196     db = MemDB.MemDB()
197
198     db.init_schema(sys.argv[1])
199     for data_file in sys.argv[2:]:
200         db.load_data(data_file)
201     db.index_data()
202
203     dp = DirectiveProcessor(db)
204
205     directives = [ "-rwhois",
206                    "-rwhois foo bar baz",
207                    "-rwhois V-1.6 noise blah",
208                    "-limit",
209                    "-limit a",
210                    "-limit 20",
211                    "-holdconnect",
212                    "-holdconnect on",
213                    "-holdconnect foo",
214                    "-directive",
215                    "-directive limit",
216                    "-directive foo",
217                    "-xfer",
218                    "-xfer a.com",
219                    "-xfer a.com class=contact",
220                    "-xfer a.com class=domain attribute=domain-name",
221                    "-xfer foo class=bar",
222                    "-xfer foo class=bar attribute=baz attribute=boo",
223                    "-foo baz bar" ]
224
225     for dir in directives:
226         print "trying %r:" % dir
227         print dp.process_directive(session, dir)
228