Initial revision
[python-rwhoisd.git] / rwhoisd / DirectiveProcessor.py
1 import re
2 import Rwhois, config
3
4 class DirectiveProcessor:
5
6     rwhois_dir_exp = re.compile(r"V-(\d+\.\d+)", re.I)
7
8     def __init__(self, db):
9         self.db = db
10         self.directives = {
11             "rwhois" : self.rwhois_directive,
12             "limit"  : self.limit_directive,
13             "holdconnect" : self.hold_directive,
14             "directive" : self.directive_directive,
15             "xfer" : self.xfer_directive
16             }
17
18     def process_directive(self, session, line):
19         d_args = line.lstrip("-").split()
20
21         if not self.directives.has_key(d_args[0]):
22             session.wfile.write(Rwhois.error_message(400))
23             return
24
25         self.directives[d_args[0]](session, d_args[1:])
26
27
28     def rwhois_directive(self, session, arglist):
29         if not arglist:
30             session.wfile.write(Rwhois.error_message(338))
31             return
32         
33         mo = DirectiveProcessor.rwhois_dir_exp.match(arglist[0])
34         if not mo:
35             session.wfile.write(Rwhois.error_message(338))
36             return
37
38         # normally we would make sure that the version given was
39         # sufficiently great.
40
41         session.wfile.write(config.banner_string)
42         session.wfile.write("\r\n")
43
44     def limit_directive(self, session, arglist):
45         try:
46             limit = int(arglist[0])
47         except (IndexError, ValueError):
48             session.wfile.write(Rwhois.error_message(338))
49             return
50         
51         if limit > config.max_limit:
52             limit = config.max_limit
53         elif limit < config.min_limit:
54             limit = config.min_limit
55         session.limit = limit
56
57         session.wfile.write(Rwhois.ok())
58
59     def hold_directive(self, session, arglist):
60         if not arglist:
61             session.wfile.write(Rwhois.error_message(338))
62             return
63         
64         arg = arglist[0].lower()
65         if arg == "on":
66             session.holdconnect = True
67         elif arg == "off":
68             session.holdconnect = False
69         else:
70             session.wfile.write(Rwhois.error_message(338))
71             return
72         
73         session.wfile.write(Rwhois.ok())
74
75     def directive_directive(self, session, arglist):
76         if not arglist:
77             reslist = []
78             dirs = self.directives.keys()
79             dirs.sort()
80             for dir in dirs:
81                 desc = dir.capitalize()
82                 reslist.append("%%directive directive:%s" % dir)
83                 reslist.append("%%directive description:%s directive" % desc)
84             session.wfile.write("\r\n".join(reslist))
85             session.wfile.write("\r\n")
86             session.wfile.write(Rwhois.ok())
87             return
88         if self.directives.has_key(arglist[0]):
89             dir = arglist[0]
90             desc = dir.capitalize()
91             session.wfile.write("%%directive directive:%s\r\n" % dir)
92             session.wfile.write("%%directive description:%s directive\r\n"
93                                 % desc)
94         else:
95             session.wfile.write(Rwhois.error_message(400))
96             return
97         session.wfile.write(Rwhois.ok())
98
99
100     def xfer_directive(self, session, arglist):
101         if not arglist:
102             session.wfile.write(Rwhois.error_message(338))
103             return
104         
105         aa = arglist[0].lower()
106
107         oc = None
108         attr_list = []
109         for arg in arglist[1:]:
110             if arg.startswith("class="):
111                 oc = arg[6:].lower()
112             elif arg.startswith("attribute="):
113                 attr = arg[10:].lower()
114                 if attr: attr_list.append(attr)
115
116         # check the constraints
117         if not self.db.is_autharea(aa):
118             session.wfile.write(Rwhois.error_message((340, aa)))
119             return
120         if oc and not self.db.is_objectclass(oc):
121             session.wfile.write(Rwhois.error_message((341, oc)))
122             return
123
124         for attr in attr_list:
125             if not self.db.is_attribute(attr):
126                 session.wfile.write(Rwhois.error_message((342, attr)))
127                 return
128
129         # now iterate over the entire dataset looking for objects that
130         # match our criteria.
131
132         objs = self.db.object_iterator()
133
134         for obj in objs:
135             # Note: in theory, we should leverage QueryProcessors
136             # filtering code.
137             if obj.get_attr_value("auth-area").lower() != aa:
138                 continue
139             if oc and obj.get_attr_value("class-name").lower() != oc:
140                 continue
141
142             if attr_list:
143                 session.wfile.write(obj.attrs_to_wire_str(attr_list, "%xfer "))
144             else:
145                 session.wfile.write(obj.to_wire_str("%xfer "))
146             session.wfile.write("\r\n%xfer \r\n");
147             
148         session.wfile.write(Rwhois.ok())
149         
150
151 if __name__ == '__main__':
152
153     import sys
154     import MemDB
155     
156     session = Session.Context()
157     session.wfile = sys.stdout
158
159     db = MemDB.MemDB()
160
161     db.init_schema(sys.argv[1])
162     for data_file in sys.argv[2:]:
163         db.load_data(data_file)
164     db.index_data()
165
166     dp = DirectiveProcessor(db)
167
168     directives = [ "-rwhois",
169                    "-rwhois foo bar baz",
170                    "-rwhois V-1.6 noise blah",
171                    "-limit",
172                    "-limit a",
173                    "-limit 20",
174                    "-holdconnect",
175                    "-holdconnect on",
176                    "-holdconnect foo",
177                    "-directive",
178                    "-directive limit",
179                    "-directive foo",
180                    "-xfer",
181                    "-xfer a.com",
182                    "-xfer a.com class=contact",
183                    "-xfer a.com class=domain attribute=domain-name",
184                    "-xfer foo class=bar",
185                    "-xfer foo class=bar attribute=baz attribute=boo",
186                    "-foo baz bar" ]
187
188     for dir in directives:
189         print "trying %r:" % dir
190         print dp.process_directive(session, dir)
191