Rev 1209 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1209 | Rev 1210 | ||
---|---|---|---|
1 | #!/usr/bin/perl -w |
1 | #!/usr/bin/perl -w |
2 | 2 | ||
3 | # |
3 | # |
4 | # Sample backend for HostAdmiral |
4 | # Sample backend for HostAdmiral |
5 | # (copyleft) Anatoli Klassen |
5 | # (copyleft) Anatoli Klassen |
6 | # |
6 | # |
7 | 7 | ||
8 | # FIXME use transactions |
8 | # FIXME use transactions |
9 | 9 | ||
10 | use strict; |
10 | use strict; |
11 | use vars; |
11 | use vars; |
12 | use subs; |
12 | use subs; |
13 | use Socket; |
13 | use Socket; |
14 | use DBI; |
14 | use DBI; |
15 | use Time::HiRes qw( gettimeofday tv_interval ); |
15 | use Time::HiRes qw( gettimeofday tv_interval ); |
16 | 16 | ||
17 | # == configuration ============================= |
17 | # == configuration ============================= |
18 | 18 | ||
19 | my $host = '127.0.0.1'; |
19 | my $host = '127.0.0.1'; |
20 | my $port = 9097; |
20 | my $port = 9097; |
21 | my $password = '0123456789ABCDEF'; |
21 | my $password = '0123456789ABCDEF'; |
22 | my $db_url = 'DBI:mysql:database=mail;host=localhost;port=3306'; |
22 | my $db_url = 'DBI:mysql:database=mail;host=localhost;port=3306'; |
23 | my $db_user = 'root'; |
23 | my $db_user = 'root'; |
24 | my $db_password = ''; |
24 | my $db_password = ''; |
25 | my $log_level = 9; # 0 - none, 9 - all |
25 | my $log_level = 9; # 0 - none, 9 - all |
26 | 26 | ||
27 | # == constants ================================= |
27 | # == constants ================================= |
28 | 28 | ||
29 | my $protocol_ver_maj = "1"; |
29 | my $protocol_ver_maj = "1"; |
30 | my $protocol_ver_min = "0"; |
30 | my $protocol_ver_min = "0"; |
31 | my $protocol_header = "HostAdmiral_TcpListener"; |
31 | my $protocol_header = "HostAdmiral_TcpListener"; |
32 | my $password_header = "password="; |
32 | my $password_header = "password="; |
33 | my $domain_header = "inetDomain"; |
33 | my $domain_header = "inetDomain"; |
34 | my $user_header = "user"; |
34 | my $user_header = "user"; |
35 | my $system_user_header = "systemUser"; |
35 | my $system_user_header = "systemUser"; |
36 | my $mailbox_header = "mailbox"; |
36 | my $mailbox_header = "mailbox"; |
37 | my $mail_alias_header = "mailAlias"; |
37 | my $mail_alias_header = "mailAlias"; |
38 | my $create_action = "create"; |
38 | my $create_action = "create"; |
39 | my $modify_action = "modify"; |
39 | my $modify_action = "modify"; |
40 | my $delete_action = "delete"; |
40 | my $delete_action = "delete"; |
41 | 41 | ||
42 | # response codes |
42 | # response codes |
43 | my $code_ok = 200; |
43 | my $code_ok = 200; |
44 | my $code_ok_but = 201; |
44 | my $code_ok_but = 201; |
45 | my $code_ignored = 202; |
45 | my $code_ignored = 202; |
46 | my $code_no_body = 400; |
46 | my $code_no_body = 400; |
47 | my $code_protocol_header = 401; |
47 | my $code_protocol_header = 401; |
48 | my $code_no_end_lines = 402; |
48 | my $code_no_end_lines = 402; |
49 | my $code_no_password = 403; |
49 | my $code_no_password = 403; |
50 | my $code_wrong_password = 404; |
50 | my $code_wrong_password = 404; |
51 | my $code_no_command = 405; |
51 | my $code_no_command = 405; |
52 | my $code_wrong_command = 406; |
52 | my $code_wrong_command = 406; |
53 | my $code_unknown_command = 407; |
53 | my $code_unknown_command = 407; |
54 | my $code_wrong_params = 408; |
54 | my $code_wrong_params = 408; |
55 | my $code_db_connect_error = 501; |
55 | my $code_db_connect_error = 501; |
56 | my $code_db_error = 502; |
56 | my $code_db_error = 502; |
57 | my $code_db_close_error = 503; |
57 | my $code_db_close_error = 503; |
58 | 58 | ||
59 | # == internal global variables ================= |
59 | # == internal global variables ================= |
60 | 60 | ||
61 | my %handlers; |
61 | my %handlers; |
62 | 62 | ||
63 | sub connection_loop |
63 | sub connection_loop |
64 | { |
64 | { |
65 | # listen for connections |
65 | # listen for connections |
66 | socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "$!\n"; |
66 | socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "$!\n"; |
67 | setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1) or die "$!\n"; |
67 | setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1) or die "$!\n"; |
68 | bind(SERVER, sockaddr_in($port, inet_aton($host))) or die "$!\n"; |
68 | bind(SERVER, sockaddr_in($port, inet_aton($host))) or die "$!\n"; |
69 | listen(SERVER, 1); |
69 | listen(SERVER, 1); |
70 | 70 | ||
71 | while(1) { |
71 | while(1) { |
72 | # get connection |
72 | # get connection |
73 | my $rem_addr = accept(CLIENT, SERVER); |
73 | my $rem_addr = accept(CLIENT, SERVER); |
74 | my $buf; |
74 | my $buf; |
75 | my $body = ""; |
75 | my $body = ""; |
76 | my %request = (); |
76 | my %request = (); |
77 | #log_debug("Remote: $rem_addr"); |
77 | #log_debug("Remote: $rem_addr"); |
78 | $request{'start_timestamp'} = [gettimeofday]; |
78 | $request{'start_timestamp'} = [gettimeofday]; |
79 | 79 | ||
80 | # receive request body |
80 | # receive request body |
81 | while((my $size = sysread CLIENT, $buf, 65536) > 0) { |
81 | while((my $size = sysread CLIENT, $buf, 65536) > 0) { |
82 | $body .= $buf; |
82 | $body .= $buf; |
83 | } |
83 | } |
84 | $request{'body'} = $body; |
84 | $request{'body'} = $body; |
85 | $request{'body_timestamp'} = [gettimeofday]; |
85 | $request{'body_timestamp'} = [gettimeofday]; |
86 | 86 | ||
87 | # call handler |
87 | # call handler |
88 | handle_request(\%request); |
88 | handle_request(\%request); |
89 | $request{'done_timestamp'} = [gettimeofday]; |
89 | $request{'done_timestamp'} = [gettimeofday]; |
90 | 90 | ||
91 | # print out response |
91 | # print out response |
92 | print CLIENT "$protocol_header $protocol_ver_maj.$protocol_ver_min" |
92 | print CLIENT "$protocol_header $protocol_ver_maj.$protocol_ver_min" |
93 | . "\n$request{'code'} $request{'response'}\n\n"; |
93 | . "\n$request{'code'} $request{'response'}\n\n"; |
94 | close CLIENT; |
94 | close CLIENT; |
95 | $request{'stop_timestamp'} = [gettimeofday]; |
95 | $request{'stop_timestamp'} = [gettimeofday]; |
96 | log_debug("Duration: " . tv_interval($request{'start_timestamp'}, |
96 | log_debug("Duration: " . tv_interval($request{'start_timestamp'}, |
97 | $request{'stop_timestamp'}) . " sec"); |
97 | $request{'stop_timestamp'}) . " sec"); |
98 | } |
98 | } |
99 | 99 | ||
100 | # close the port |
100 | # close the port |
101 | close SERVER; |
101 | close SERVER; |
102 | } |
102 | } |
103 | 103 | ||
104 | sub handle_request |
104 | sub handle_request |
105 | { |
105 | { |
106 | my $request = shift @_; |
106 | my $request = shift @_; |
107 | 107 | ||
108 | log_debug("Handle request [\n$request->{'body'}]"); |
108 | log_debug("Handle request [\n$request->{'body'}]"); |
109 | 109 | ||
110 | my @lines = split /\n/, $request->{'body'}, -1; |
110 | my @lines = split /\n/, $request->{'body'}, -1; |
111 | my $cur = 0; |
111 | my $cur = 0; |
112 | 112 | ||
113 | # check header |
113 | # check header |
114 | if($#lines < $cur) { |
114 | if($#lines < $cur) { |
115 | set_request_code($request, $code_no_body, "Request without body"); |
115 | set_request_code($request, $code_no_body, "Request without body"); |
116 | return; |
116 | return; |
117 | } |
117 | } |
118 | unless($lines[$cur] =~ /^$protocol_header $protocol_ver_maj\.\d+$/) { |
118 | unless($lines[$cur] =~ /^$protocol_header $protocol_ver_maj\.\d+$/) { |
119 | set_request_code($request, $code_protocol_header, "Request must start" |
119 | set_request_code($request, $code_protocol_header, "Request must start" |
120 | . "with [$protocol_header $protocol_ver_maj.minor]," |
120 | . "with [$protocol_header $protocol_ver_maj.minor]," |
121 | . " but [$lines[$cur]] found"); |
121 | . " but [$lines[$cur]] found"); |
122 | return; |
122 | return; |
123 | } |
123 | } |
124 | $cur++; |
124 | $cur++; |
125 | 125 | ||
126 | # check end lines |
126 | # check end lines |
127 | if($#lines < $cur+1 || $lines[$#lines-1] ne "" || $lines[$#lines] ne "") { |
127 | if($#lines < $cur+1 || $lines[$#lines-1] ne "" || $lines[$#lines] ne "") { |
128 | set_request_code($request, $code_no_end_lines, |
128 | set_request_code($request, $code_no_end_lines, |
129 | "Request doesn't end with \\n\\n"); |
129 | "Request doesn't end with \\n\\n"); |
130 | return; |
130 | return; |
131 | } |
131 | } |
132 | 132 | ||
133 | # check password |
133 | # check password |
134 | if($password) { |
134 | if($password) { |
135 | if($#lines < $cur || !($lines[$cur] =~ /^$password_header/)) { |
135 | if($#lines < $cur || !($lines[$cur] =~ /^$password_header/)) { |
136 | set_request_code($request, $code_no_password, |
136 | set_request_code($request, $code_no_password, |
137 | "Password not specified"); |
137 | "Password not specified"); |
138 | return; |
138 | return; |
139 | } |
139 | } |
140 | 140 | ||
141 | unless($lines[$cur] =~ /^$password_header$password$/) { |
141 | unless($lines[$cur] =~ /^$password_header$password$/) { |
142 | set_request_code($request, $code_wrong_password, |
142 | set_request_code($request, $code_wrong_password, |
143 | "Wrong password"); |
143 | "Wrong password"); |
144 | return; |
144 | return; |
145 | } |
145 | } |
146 | 146 | ||
147 | $cur++; |
147 | $cur++; |
148 | } |
148 | } |
149 | 149 | ||
150 | # get command handler |
150 | # get command handler |
151 | if($#lines < $cur) { |
151 | if($#lines < $cur) { |
152 | set_request_code($request, $code_no_command, "Empty command"); |
152 | set_request_code($request, $code_no_command, "Empty command"); |
153 | return; |
153 | return; |
154 | } |
154 | } |
155 | unless($lines[$cur] =~ /^(\S+)\t(\S+)/) { |
155 | unless($lines[$cur] =~ /^(\S+)\t(\S+)/) { |
156 | set_request_code($request, $code_wrong_command, "Can not get command"); |
156 | set_request_code($request, $code_wrong_command, "Can not get command"); |
157 | return; |
157 | return; |
158 | } |
158 | } |
159 | 159 | ||
160 | $request->{'command'} = $1; |
160 | $request->{'command'} = $1; |
161 | $request->{'subcommand'} = $2; |
161 | $request->{'subcommand'} = $2; |
162 | $request->{'handler'} = $handlers{"$1_$2"}; |
162 | $request->{'handler'} = $handlers{"$1_$2"}; |
163 | 163 | ||
164 | unless($request->{'handler'}) { |
164 | unless($request->{'handler'}) { |
165 | set_request_code($request, $code_unknown_command, |
165 | set_request_code($request, $code_unknown_command, |
166 | "Unknown command [$request->{'command'} $request->{'subcommand'}]"); |
166 | "Unknown command [$request->{'command'} $request->{'subcommand'}]"); |
167 | return; |
167 | return; |
168 | } |
168 | } |
169 | 169 | ||
170 | # call |
170 | # call |
171 | log_debug("call $request->{'command'}_$request->{'subcommand'}"); |
171 | log_debug("call $request->{'command'}_$request->{'subcommand'}"); |
172 | my @params = @lines[$cur..$#lines-2]; |
172 | my @params = @lines[$cur..$#lines-2]; |
173 | &{$request->{'handler'}}($request, @params); |
173 | &{$request->{'handler'}}($request, @params); |
174 | } |
174 | } |
175 | 175 | ||
176 | sub handle_user_create |
176 | sub handle_user_create |
177 | { |
177 | { |
178 | my $request = shift @_; |
178 | my $request = shift @_; |
179 | 179 | ||
180 | set_request_code($request, $code_ignored, "Not interesting in users"); |
180 | set_request_code($request, $code_ignored, "Not interesting in users"); |
181 | } |
181 | } |
182 | 182 | ||
183 | sub handle_user_modify |
183 | sub handle_user_modify |
184 | { |
184 | { |
185 | my $request = shift @_; |
185 | my $request = shift @_; |
186 | 186 | ||
187 | set_request_code($request, $code_ignored, "Not interesting in users"); |
187 | set_request_code($request, $code_ignored, "Not interesting in users"); |
188 | } |
188 | } |
189 | 189 | ||
190 | sub handle_user_delete |
190 | sub handle_user_delete |
191 | { |
191 | { |
192 | my $request = shift @_; |
192 | my $request = shift @_; |
193 | 193 | ||
194 | set_request_code($request, $code_ignored, "Not interesting in users"); |
194 | set_request_code($request, $code_ignored, "Not interesting in users"); |
195 | } |
195 | } |
196 | 196 | ||
197 | sub handle_domain_create |
197 | sub handle_domain_create |
198 | { |
198 | { |
199 | my $request = shift @_; |
199 | my $request = shift @_; |
200 | my %params = parse_command_params($request, shift @_, ("name")); |
200 | my %params = parse_command_params($request, shift @_, ("name")); |
201 | return unless(%params); |
201 | return unless(%params); |
202 | 202 | ||
203 | my $res_action = save_to_db($request, "transport", |
203 | my $res_action = save_to_db($request, "transport", |
204 | { domain => $params{"name"} }, |
204 | { domain => $params{"name"} }, |
205 | { domain => $params{"name"}, comment => $params{"comment"}, |
205 | { domain => $params{"name"}, comment => $params{"comment"}, |
206 | transport => 'virtual:' } ); |
206 | transport => 'virtual:' } ); |
207 | 207 | ||
208 | if($res_action eq 'update') { |
208 | if($res_action eq 'update') { |
209 | return unless(restart_mail_system()); |
209 | return unless(restart_mail_system()); |
210 | set_request_code($request, $code_ok_but, "Domain exists, modified"); |
210 | set_request_code($request, $code_ok_but, "Domain exists, modified"); |
211 | } |
211 | } |
212 | elsif($res_action eq 'insert') { |
212 | elsif($res_action eq 'insert') { |
213 | return unless(restart_mail_system()); |
213 | return unless(restart_mail_system()); |
214 | set_request_code($request, $code_ok, "Domain created"); |
214 | set_request_code($request, $code_ok, "Domain created"); |
215 | } |
215 | } |
216 | } |
216 | } |
217 | 217 | ||
218 | sub handle_domain_modify |
218 | sub handle_domain_modify |
219 | { |
219 | { |
220 | my $request = shift @_; |
220 | my $request = shift @_; |
221 | my %params = parse_command_params($request, shift @_, ("oldName", "name")); |
221 | my %params = parse_command_params($request, shift @_, ("oldName", "name")); |
222 | return unless(%params); |
222 | return unless(%params); |
223 | 223 | ||
224 | my $res_action = save_to_db($request, "transport", |
224 | my $res_action = save_to_db($request, "transport", |
225 | { domain => $params{"oldName"} }, |
225 | { domain => $params{"oldName"} }, |
226 | { domain => $params{"name"}, comment => $params{"comment"}, |
226 | { domain => $params{"name"}, comment => $params{"comment"}, |
227 | transport => 'virtual:' } ); |
227 | transport => 'virtual:' } ); |
228 | 228 | ||
229 | if($res_action eq 'update') { |
229 | if($res_action eq 'update') { |
230 | return unless(restart_mail_system()); |
230 | return unless(restart_mail_system()); |
231 | set_request_code($request, $code_ok, "Domain modified"); |
231 | set_request_code($request, $code_ok, "Domain modified"); |
232 | } |
232 | } |
233 | elsif($res_action eq 'insert') { |
233 | elsif($res_action eq 'insert') { |
234 | return unless(restart_mail_system()); |
234 | return unless(restart_mail_system()); |
235 | set_request_code($request, $code_ok_but, "Domain not found, created"); |
235 | set_request_code($request, $code_ok_but, "Domain not found, created"); |
236 | } |
236 | } |
237 | } |
237 | } |
238 | 238 | ||
239 | sub handle_domain_delete |
239 | sub handle_domain_delete |
240 | { |
240 | { |
241 | my $request = shift @_; |
241 | my $request = shift @_; |
242 | my %params = parse_command_params($request, shift @_, ("name")); |
242 | my %params = parse_command_params($request, shift @_, ("name")); |
243 | return unless(%params); |
243 | return unless(%params); |
244 | 244 | ||
245 | my $res_action = delete_from_db($request, "transport", |
245 | my $res_action = delete_from_db($request, "transport", |
246 | { domain => $params{"name"} } ); |
246 | { domain => $params{"name"} } ); |
247 | 247 | ||
248 | if($res_action eq 'delete') { |
248 | if($res_action eq 'delete') { |
249 | return unless(restart_mail_system()); |
249 | return unless(restart_mail_system()); |
250 | set_request_code($request, $code_ok, "Domain deleted"); |
250 | set_request_code($request, $code_ok, "Domain deleted"); |
251 | } |
251 | } |
252 | elsif($res_action eq 'not found') { |
252 | elsif($res_action eq 'not found') { |
253 | set_request_code($request, $code_ok_but, "Domain not found"); |
253 | set_request_code($request, $code_ok_but, "Domain not found"); |
254 | } |
254 | } |
255 | } |
255 | } |
256 | 256 | ||
257 | sub handle_system_user_create |
257 | sub handle_system_user_create |
258 | { |
258 | { |
259 | } |
259 | } |
260 | 260 | ||
261 | sub handle_system_user_modify |
261 | sub handle_system_user_modify |
262 | { |
262 | { |
263 | } |
263 | } |
264 | 264 | ||
265 | sub handle_system_user_delete |
265 | sub handle_system_user_delete |
266 | { |
266 | { |
267 | } |
267 | } |
268 | 268 | ||
269 | sub handle_mailbox_create |
269 | sub handle_mailbox_create |
270 | { |
270 | { |
271 | my $request = shift @_; |
271 | my $request = shift @_; |
272 | my %params = parse_command_params($request, shift @_, |
272 | my %params = parse_command_params($request, shift @_, |
273 | ("login", "password", "domain")); |
273 | ("login", "password", "domain")); |
274 | return unless(%params); |
274 | return unless(%params); |
275 | 275 | ||
276 | my $res_action = save_to_db($request, "users", |
276 | my $res_action = save_to_db($request, "users", |
277 | { login => "$params{'login'}\@$params{'domain'}" }, |
277 | { login => "$params{'login'}\@$params{'domain'}" }, |
278 | { login => "$params{'login'}\@$params{'domain'}", |
278 | { login => "$params{'login'}\@$params{'domain'}", |
279 | password => $params{"password"}, |
279 | password => $params{"password"}, |
280 | maildir => "$params{'domain'}/$params{'login'}/", |
280 | maildir => "$params{'domain'}/$params{'login'}/", |
281 | expired => ($params{"enabled"} eq "true" ? 0 : 1), |
281 | expired => ($params{"enabled"} eq "true" ? 0 : 1), |
282 | comment => $params{"comment"}, |
282 | comment => $params{"comment"}, |
283 | uid => ($params{"systemUser"} ? $params{"systemUser"} : undef) } ); |
283 | uid => ($params{"systemUser"} ? $params{"systemUser"} : undef) } ); |
284 | 284 | ||
285 | if($res_action eq 'update') { |
285 | if($res_action eq 'update') { |
286 | set_request_code($request, $code_ok_but, "Mailbox exists, modified"); |
286 | set_request_code($request, $code_ok_but, "Mailbox exists, modified"); |
287 | } |
287 | } |
288 | elsif($res_action eq 'insert') { |
288 | elsif($res_action eq 'insert') { |
289 | set_request_code($request, $code_ok, "Mailbox created"); |
289 | set_request_code($request, $code_ok, "Mailbox created"); |
290 | } |
290 | } |
291 | } |
291 | } |
292 | 292 | ||
293 | sub handle_mailbox_modify |
293 | sub handle_mailbox_modify |
294 | { |
294 | { |
295 | my $request = shift @_; |
295 | my $request = shift @_; |
296 | my %params = parse_command_params($request, shift @_, |
296 | my %params = parse_command_params($request, shift @_, |
297 | ("oldLogin", "oldDomain", "login", "domain")); |
297 | ("oldLogin", "oldDomain", "login", "domain")); |
298 | return unless(%params); |
298 | return unless(%params); |
299 | 299 | ||
300 | # FIXME move the old maildir |
300 | # FIXME move the old maildir |
301 | 301 | ||
302 | my $res_action = save_to_db($request, "users", |
302 | my $res_action = save_to_db($request, "users", |
303 | { login => "$params{'oldLogin'}\@$params{'oldDomain'}" }, |
303 | { login => "$params{'oldLogin'}\@$params{'oldDomain'}" }, |
304 | { login => "$params{'login'}\@$params{'domain'}", |
304 | { login => "$params{'login'}\@$params{'domain'}", |
305 | password => $params{"password"}, |
305 | password => $params{"password"}, |
306 | maildir => "$params{'domain'}/$params{'login'}/", |
306 | maildir => "$params{'domain'}/$params{'login'}/", |
307 | expired => ($params{"enabled"} eq "true" ? "0" : "1"), |
307 | expired => ($params{"enabled"} eq "true" ? "0" : "1"), |
308 | comment => $params{"comment"}, |
308 | comment => $params{"comment"}, |
309 | uid => ($params{"systemUser"} ? $params{"systemUser"} : undef) } ); |
309 | uid => ($params{"systemUser"} ? $params{"systemUser"} : undef) } ); |
310 | 310 | ||
311 | if($res_action eq 'update') { |
311 | if($res_action eq 'update') { |
312 | set_request_code($request, $code_ok, "Mailbox modified"); |
312 | set_request_code($request, $code_ok, "Mailbox modified"); |
313 | } |
313 | } |
314 | elsif($res_action eq 'insert') { |
314 | elsif($res_action eq 'insert') { |
315 | set_request_code($request, $code_ok_but, "Mailbox not found, created"); |
315 | set_request_code($request, $code_ok_but, "Mailbox not found, created"); |
316 | } |
316 | } |
317 | } |
317 | } |
318 | 318 | ||
319 | sub handle_mailbox_delete |
319 | sub handle_mailbox_delete |
320 | { |
320 | { |
321 | my $request = shift @_; |
321 | my $request = shift @_; |
322 | my %params = parse_command_params($request, shift @_, ("login", "domain")); |
322 | my %params = parse_command_params($request, shift @_, ("login", "domain")); |
323 | return unless(%params); |
323 | return unless(%params); |
324 | 324 | ||
325 | # FIXME remove the maildir |
325 | # FIXME remove the maildir |
326 | 326 | ||
327 | my $res_action = delete_from_db($request, "users", |
327 | my $res_action = delete_from_db($request, "users", |
328 | { login => "$params{'login'}\@$params{'domain'}" } ); |
328 | { login => "$params{'login'}\@$params{'domain'}" } ); |
329 | 329 | ||
330 | if($res_action eq 'delete') { |
330 | if($res_action eq 'delete') { |
331 | set_request_code($request, $code_ok, "Mailbox deleted"); |
331 | set_request_code($request, $code_ok, "Mailbox deleted"); |
332 | } |
332 | } |
333 | elsif($res_action eq 'not found') { |
333 | elsif($res_action eq 'not found') { |
334 | set_request_code($request, $code_ok_but, "Mailbox not found"); |
334 | set_request_code($request, $code_ok_but, "Mailbox not found"); |
335 | } |
335 | } |
336 | } |
336 | } |
337 | 337 | ||
338 | sub handle_mail_alias_create |
338 | sub handle_mail_alias_create |
339 | { |
339 | { |
340 | my $request = shift @_; |
340 | my $request = shift @_; |
341 | my %params = parse_command_params($request, shift @_, ("address", "domain")); |
341 | my %params = parse_command_params($request, shift @_, ("address", "domain")); |
342 | return unless(%params); |
342 | return unless(%params); |
343 | my @rcpts = parse_command_array($request, @_); |
343 | my @rcpts = parse_command_array($request, @_); |
344 | 344 | ||
345 | my $del_action = delete_from_db($request, "aliases", |
345 | my $del_action = delete_from_db($request, "aliases", |
346 | { alias => "$params{'address'}\@$params{'domain'}" } ); |
346 | { alias => "$params{'address'}\@$params{'domain'}" } ); |
347 | return if($del_action eq "error"); |
347 | return if($del_action eq "error"); |
348 | 348 | ||
349 | foreach my $rcpt (@rcpts) { |
349 | foreach my $rcpt (@rcpts) { |
350 | log_debug("save $rcpt"); |
350 | log_debug("save $rcpt"); |
351 | my $res_action = save_to_db($request, "aliases", |
351 | my $res_action = save_to_db($request, "aliases", |
352 | undef, |
352 | undef, |
353 | { alias => "$params{'address'}\@$params{'domain'}", |
353 | { alias => "$params{'address'}\@$params{'domain'}", |
354 | rcpt => $rcpt, comment => $params{"comment"} } ); |
354 | rcpt => $rcpt, comment => $params{"comment"} } ); |
355 | return if($res_action eq "error"); |
355 | return if($res_action eq "error"); |
356 | } |
356 | } |
357 | 357 | ||
358 | if($del_action eq 'delete') { |
358 | if($del_action eq 'delete') { |
359 | set_request_code($request, $code_ok_but, "Mail alias exists, modified"); |
359 | set_request_code($request, $code_ok_but, "Mail alias exists, modified"); |
360 | } |
360 | } |
361 | elsif($del_action eq 'not found') { |
361 | elsif($del_action eq 'not found') { |
362 | set_request_code($request, $code_ok, "Mail alias created"); |
362 | set_request_code($request, $code_ok, "Mail alias created"); |
363 | } |
363 | } |
364 | } |
364 | } |
365 | 365 | ||
366 | sub handle_mail_alias_modify |
366 | sub handle_mail_alias_modify |
367 | { |
367 | { |
368 | my $request = shift @_; |
368 | my $request = shift @_; |
369 | my %params = parse_command_params($request, shift @_, ("address", "domain")); |
369 | my %params = parse_command_params($request, shift @_, ("address", "domain")); |
370 | return unless(%params); |
370 | return unless(%params); |
371 | my @rcpts = parse_command_array($request, @_); |
371 | my @rcpts = parse_command_array($request, @_); |
372 | 372 | ||
373 | my $del_action = delete_from_db($request, "aliases", |
373 | my $del_action = delete_from_db($request, "aliases", |
374 | { alias => "$params{'address'}\@$params{'domain'}" } ); |
374 | { alias => "$params{'address'}\@$params{'domain'}" } ); |
375 | return if($del_action eq "error"); |
375 | return if($del_action eq "error"); |
376 | 376 | ||
377 | foreach my $rcpt (@rcpts) { |
377 | foreach my $rcpt (@rcpts) { |
378 | log_debug("save $rcpt"); |
378 | log_debug("save $rcpt"); |
379 | my $res_action = save_to_db($request, "aliases", |
379 | my $res_action = save_to_db($request, "aliases", |
380 | undef, |
380 | undef, |
381 | { alias => "$params{'address'}\@$params{'domain'}", |
381 | { alias => "$params{'address'}\@$params{'domain'}", |
382 | rcpt => $rcpt, comment => $params{"comment"} } ); |
382 | rcpt => $rcpt, comment => $params{"comment"} } ); |
383 | return if($res_action eq "error"); |
383 | return if($res_action eq "error"); |
384 | } |
384 | } |
385 | # FIXME add the loopback destination? handle "a@domain.com => a@domain.com" |
385 | # FIXME add the loopback destination? handle "a@domain.com => a@domain.com" |
386 | # as "a@domain.com => _something_@domain.com + _something_@domain.com => _something_@domain.com" ? |
386 | # as "a@domain.com => _something_@domain.com + _something_@domain.com => _something_@domain.com" ? |
387 | 387 | ||
388 | if($del_action eq 'delete') { |
388 | if($del_action eq 'delete') { |
389 | set_request_code($request, $code_ok, "Mail alias modified"); |
389 | set_request_code($request, $code_ok, "Mail alias modified"); |
390 | } |
390 | } |
391 | elsif($del_action eq 'not found') { |
391 | elsif($del_action eq 'not found') { |
392 | set_request_code($request, $code_ok_but, "Mail alias not found, created"); |
392 | set_request_code($request, $code_ok_but, "Mail alias not found, created"); |
393 | } |
393 | } |
394 | } |
394 | } |
395 | 395 | ||
396 | sub handle_mail_alias_delete |
396 | sub handle_mail_alias_delete |
397 | { |
397 | { |
398 | my $request = shift @_; |
398 | my $request = shift @_; |
399 | my %params = parse_command_params($request, shift @_, ("address", "domain")); |
399 | my %params = parse_command_params($request, shift @_, ("address", "domain")); |
400 | return unless(%params); |
400 | return unless(%params); |
401 | 401 | ||
402 | my $res_action = delete_from_db($request, "aliases", |
402 | my $res_action = delete_from_db($request, "aliases", |
403 | { alias => "$params{'address'}\@$params{'domain'}" } ); |
403 | { alias => "$params{'address'}\@$params{'domain'}" } ); |
404 | 404 | ||
405 | if($res_action eq 'delete') { |
405 | if($res_action eq 'delete') { |
406 | set_request_code($request, $code_ok, "Mail alias deleted"); |
406 | set_request_code($request, $code_ok, "Mail alias deleted"); |
407 | } |
407 | } |
408 | elsif($res_action eq 'not found') { |
408 | elsif($res_action eq 'not found') { |
409 | set_request_code($request, $code_ok_but, "Mail alias not found"); |
409 | set_request_code($request, $code_ok_but, "Mail alias not found"); |
410 | } |
410 | } |
411 | } |
411 | } |
412 | 412 | ||
413 | sub decode_param |
413 | sub decode_param |
414 | { |
414 | { |
415 | my $value = shift @_; |
415 | my $value = shift @_; |
416 | 416 | ||
417 | $value =~ s/\\r/\r/g; |
417 | $value =~ s/\\r/\r/g; |
418 | $value =~ s/\\n/\n/g; |
418 | $value =~ s/\\n/\n/g; |
419 | $value =~ s/\\t/\t/g; |
419 | $value =~ s/\\t/\t/g; |
420 | $value =~ s/\\0/\000/g; |
420 | $value =~ s/\\0/\000/g; |
421 | $value =~ s/\\\\/\\/g; |
421 | $value =~ s/\\\\/\\/g; |
422 | 422 | ||
423 | return $value; |
423 | return $value; |
424 | } |
424 | } |
425 | 425 | ||
426 | sub parse_command_array |
426 | sub parse_command_array |
427 | { |
427 | { |
428 | my $request = shift @_; |
428 | my $request = shift @_; |
429 | my @params = (); |
429 | my @params = (); |
430 | 430 | ||
431 | map { |
431 | map { |
432 | if(/^\t(.*)$/) { |
432 | if(/^\t(.*)$/) { |
433 | push @params, decode_param($1); |
433 | push @params, decode_param($1); |
434 | } |
434 | } |
435 | } @_; |
435 | } @_; |
436 | 436 | ||
437 | return @params; |
437 | return @params; |
438 | } |
438 | } |
439 | 439 | ||
440 | sub parse_command_params($$@) |
440 | sub parse_command_params($$@) |
441 | { |
441 | { |
442 | my $request = shift @_; |
442 | my $request = shift @_; |
443 | my @params = split /\t/, shift @_, -1; |
443 | my @params = split /\t/, shift @_, -1; |
444 | my %required = map { $_ => 1 } @_; # convert array to hash |
444 | my %required = map { $_ => 1 } @_; # convert array to hash |
445 | my %values = (); |
445 | my %values = (); |
446 | 446 | ||
447 | @params = @params[2..$#params]; # remove handler and action |
447 | @params = @params[2..$#params]; # remove handler and action |
448 | map { |
448 | map { |
449 | my ($key, $value) = split /=/, $_; |
449 | my ($key, $value) = split /=/, $_; |
450 | $values{$key} = decode_param($value); |
450 | $values{$key} = decode_param($value); |
451 | delete($required{$key}); |
451 | delete($required{$key}); |
452 | } @params; |
452 | } @params; |
453 | 453 | ||
454 | if(%required) { |
454 | if(%required) { |
455 | set_request_code($request, $code_wrong_params, |
455 | set_request_code($request, $code_wrong_params, |
456 | "Params " . join(', ', keys %required) . " expected but not found"); |
456 | "Params " . join(', ', keys %required) . " expected but not found"); |
457 | return (); |
457 | return (); |
458 | } |
458 | } |
459 | 459 | ||
460 | return %values; |
460 | return %values; |
461 | } |
461 | } |
462 | 462 | ||
463 | sub restart_mail_system |
463 | sub restart_mail_system |
464 | { |
464 | { |
465 | my $request = shift @_; |
465 | my $request = shift @_; |
466 | 466 | ||
467 | log_debug("Mail system restarted"); |
467 | log_debug("Mail system restarted"); |
468 | 468 | ||
469 | return 1; |
469 | return 1; |
470 | } |
470 | } |
471 | 471 | ||
472 | sub db_connect |
472 | sub db_connect |
473 | { |
473 | { |
474 | my $request = shift @_; |
474 | my $request = shift @_; |
475 | my $dbh = undef; |
475 | my $dbh = undef; |
476 | 476 | ||
477 | eval { $dbh = DBI->connect($db_url, $db_user, $db_password); }; |
477 | eval { $dbh = DBI->connect($db_url, $db_user, $db_password); }; |
478 | if($@) { |
478 | if($@) { |
479 | set_request_code($request, $code_db_connect_error, $@); |
479 | set_request_code($request, $code_db_connect_error, $@); |
480 | $dbh = undef; |
480 | $dbh = undef; |
481 | } |
481 | } |
482 | 482 | ||
483 | return $dbh; |
483 | return $dbh; |
484 | } |
484 | } |
485 | 485 | ||
486 | sub db_close |
486 | sub db_close |
487 | { |
487 | { |
488 | my $request = shift @_; |
488 | my $request = shift @_; |
489 | my $dbh = shift @_; |
489 | my $dbh = shift @_; |
490 | my $error = shift @_; |
490 | my $error = shift @_; |
491 | my $no_error = 1; |
491 | my $no_error = 1; |
492 | 492 | ||
493 | if($error) { |
493 | if($error) { |
494 | set_request_code($request, $code_db_error, $error); |
494 | set_request_code($request, $code_db_error, $error); |
495 | $no_error = 0; |
495 | $no_error = 0; |
496 | } |
496 | } |
497 | 497 | ||
498 | eval { |
498 | eval { |
499 | $dbh->disconnect() if($dbh); |
499 | $dbh->disconnect() if($dbh); |
500 | }; |
500 | }; |
501 | 501 | ||
502 | if($@ && $no_error) { |
502 | if($@ && $no_error) { |
503 | set_request_code($request, $code_db_close_error, $@); |
503 | set_request_code($request, $code_db_close_error, $@); |
504 | $no_error = 0; |
504 | $no_error = 0; |
505 | } |
505 | } |
506 | 506 | ||
507 | return $no_error; |
507 | return $no_error; |
508 | } |
508 | } |
509 | 509 | ||
510 | sub delete_from_db |
510 | sub delete_from_db |
511 | { |
511 | { |
512 | my $request = shift @_; |
512 | my $request = shift @_; |
513 | my $table = shift @_; |
513 | my $table = shift @_; |
514 | my $key_columns = shift @_; |
514 | my $key_columns = shift @_; |
515 | 515 | ||
516 | my $res_action = 'none'; |
516 | my $res_action = 'none'; |
517 | my $dbh = db_connect($request); |
517 | my $dbh = db_connect($request); |
518 | 518 | ||
519 | return 'error' unless($dbh); |
519 | return 'error' unless($dbh); |
520 | 520 | ||
521 | eval { |
521 | eval { |
522 | my $sql = ""; |
522 | my $sql = ""; |
523 | while(my ($key, $value) = each(%$key_columns)) { |
523 | while(my ($key, $value) = each(%$key_columns)) { |
524 | next unless(defined $value); |
524 | next unless(defined $value); |
525 | $sql .= " and " if($sql); |
525 | $sql .= " and " if($sql); |
526 | $sql .= "$key = ?"; |
526 | $sql .= "$key = ?"; |
527 | } |
527 | } |
528 | $sql = "delete from $table where $sql"; |
528 | $sql = "delete from $table where $sql"; |
529 | 529 | ||
530 | my $sth = $dbh->prepare($sql); |
530 | my $sth = $dbh->prepare($sql); |
531 | my $count = 0; |
531 | my $count = 0; |
532 | while(my ($key, $value) = each(%$key_columns)) { |
532 | while(my ($key, $value) = each(%$key_columns)) { |
533 | next unless(defined $value); |
533 | next unless(defined $value); |
534 | $sth->bind_param(++$count, $value); |
534 | $sth->bind_param(++$count, $value); |
535 | } |
535 | } |
536 | 536 | ||
537 | my $res = $sth->execute; |
537 | my $res = $sth->execute; |
538 | 538 | ||
539 | if($res < 1) { |
539 | if($res < 1) { |
540 | $res_action = 'not found'; |
540 | $res_action = 'not found'; |
541 | } |
541 | } |
542 | else { |
542 | else { |
543 | $res_action = 'delete'; |
543 | $res_action = 'delete'; |
544 | } |
544 | } |
545 | }; |
545 | }; |
546 | 546 | ||
547 | if(db_close($request, $dbh, $@)) { |
547 | if(db_close($request, $dbh, $@)) { |
548 | return $res_action; |
548 | return $res_action; |
549 | } |
549 | } |
550 | else { |
550 | else { |
551 | return 'error'; |
551 | return 'error'; |
552 | } |
552 | } |
553 | } |
553 | } |
554 | 554 | ||
555 | sub save_to_db |
555 | sub save_to_db |
556 | { |
556 | { |
557 | my $request = shift @_; |
557 | my $request = shift @_; |
558 | my $table = shift @_; |
558 | my $table = shift @_; |
559 | my $key_columns = shift @_; |
559 | my $key_columns = shift @_; |
560 | my $value_columns = shift @_; |
560 | my $value_columns = shift @_; |
561 | 561 | ||
562 | my $error_set = 0; |
562 | my $error_set = 0; |
563 | my $res_action = 'none'; |
563 | my $res_action = 'none'; |
564 | my $dbh = db_connect($request); |
564 | my $dbh = db_connect($request); |
565 | 565 | ||
566 | return 'error' unless($dbh); |
566 | return 'error' unless($dbh); |
567 | 567 | ||
568 | eval { |
568 | eval { |
569 | my $res = 0; |
569 | my $res = 0; |
570 | 570 | ||
571 | if($key_columns) { |
571 | if($key_columns) { |
572 | my $update_sql = ""; |
572 | my $update_sql = ""; |
573 | my $where = ""; |
573 | my $where = ""; |
574 | while(my ($key, $value) = each(%$value_columns)) { |
574 | while(my ($key, $value) = each(%$value_columns)) { |
575 | next unless(defined $value); |
575 | next unless(defined $value); |
576 | $update_sql .= ", " if($update_sql); |
576 | $update_sql .= ", " if($update_sql); |
577 | $update_sql .= "$key = ?"; |
577 | $update_sql .= "$key = ?"; |
578 | } |
578 | } |
579 | while(my ($key, $value) = each(%$key_columns)) { |
579 | while(my ($key, $value) = each(%$key_columns)) { |
580 | next unless(defined $value); |
580 | next unless(defined $value); |
581 | $where .= " and " if($where); |
581 | $where .= " and " if($where); |
582 | $where .= "$key = ?"; |
582 | $where .= "$key = ?"; |
583 | } |
583 | } |
584 | $update_sql = "update $table set $update_sql where $where"; |
584 | $update_sql = "update $table set $update_sql where $where"; |
585 | 585 | ||
586 | my $update_sth = $dbh->prepare($update_sql); |
586 | my $update_sth = $dbh->prepare($update_sql); |
587 | my $count = 0; |
587 | my $count = 0; |
588 | while(my ($key, $value) = each(%$value_columns)) { |
588 | while(my ($key, $value) = each(%$value_columns)) { |
589 | next unless(defined $value); |
589 | next unless(defined $value); |
590 | $update_sth->bind_param(++$count, $value); |
590 | $update_sth->bind_param(++$count, $value); |
591 | } |
591 | } |
592 | while(my ($key, $value) = each(%$key_columns)) { |
592 | while(my ($key, $value) = each(%$key_columns)) { |
593 | next unless(defined $value); |
593 | next unless(defined $value); |
594 | $update_sth->bind_param(++$count, $value); |
594 | $update_sth->bind_param(++$count, $value); |
595 | } |
595 | } |
596 | 596 | ||
597 | $res = $update_sth->execute; |
597 | $res = $update_sth->execute; |
598 | $res_action = 'update'; |
598 | $res_action = 'update'; |
599 | } |
599 | } |
600 | 600 | ||
601 | if($res < 1) { |
601 | if($res < 1) { |
602 | my $insert_sql = ""; |
602 | my $insert_sql = ""; |
603 | my $sql_params = ""; |
603 | my $sql_params = ""; |
604 | while(my ($key, $value) = each(%$key_columns)) { |
604 | while(my ($key, $value) = each(%$key_columns)) { |
605 | next unless(defined $value); |
605 | next unless(defined $value); |
606 | next if($value_columns->{$key}); |
606 | next if($value_columns->{$key}); |
607 | if($insert_sql) { |
607 | if($insert_sql) { |
608 | $insert_sql .= ", "; |
608 | $insert_sql .= ", "; |
609 | $sql_params .= ", "; |
609 | $sql_params .= ", "; |
610 | } |
610 | } |
611 | $insert_sql .= "$key"; |
611 | $insert_sql .= "$key"; |
612 | $sql_params .= "?"; |
612 | $sql_params .= "?"; |
613 | } |
613 | } |
614 | while(my ($key, $value) = each(%$value_columns)) { |
614 | while(my ($key, $value) = each(%$value_columns)) { |
615 | next unless(defined $value); |
615 | next unless(defined $value); |
616 | if($insert_sql) { |
616 | if($insert_sql) { |
617 | $insert_sql .= ", "; |
617 | $insert_sql .= ", "; |
618 | $sql_params .= ", "; |
618 | $sql_params .= ", "; |
619 | } |
619 | } |
620 | $insert_sql .= "$key"; |
620 | $insert_sql .= "$key"; |
621 | $sql_params .= "?"; |
621 | $sql_params .= "?"; |
622 | } |
622 | } |
623 | $insert_sql = "insert into $table ($insert_sql)" |
623 | $insert_sql = "insert into $table ($insert_sql)" |
624 | . " values ($sql_params)"; |
624 | . " values ($sql_params)"; |
625 | 625 | ||
626 | my $insert_sth = $dbh->prepare($insert_sql); |
626 | my $insert_sth = $dbh->prepare($insert_sql); |
627 | my $count = 0; |
627 | my $count = 0; |
628 | while(my ($key, $value) = each(%$key_columns)) { |
628 | while(my ($key, $value) = each(%$key_columns)) { |
629 | next unless(defined $value); |
629 | next unless(defined $value); |
630 | next if($value_columns->{$key}); |
630 | next if($value_columns->{$key}); |
631 | $insert_sth->bind_param(++$count, $value); |
631 | $insert_sth->bind_param(++$count, $value); |
632 | } |
632 | } |
633 | while(my ($key, $value) = each(%$value_columns)) { |
633 | while(my ($key, $value) = each(%$value_columns)) { |
634 | next unless(defined $value); |
634 | next unless(defined $value); |
635 | $insert_sth->bind_param(++$count, $value); |
635 | $insert_sth->bind_param(++$count, $value); |
636 | } |
636 | } |
637 | 637 | ||
638 | $res = $insert_sth->execute; |
638 | $res = $insert_sth->execute; |
639 | $res_action = 'insert'; |
639 | $res_action = 'insert'; |
640 | } |
640 | } |
641 | }; |
641 | }; |
642 | # FIXME handle exceptions? |
642 | # FIXME handle exceptions? |
643 | 643 | ||
644 | if(db_close($request, $dbh, $@)) { |
644 | if(db_close($request, $dbh, $@)) { |
645 | return $res_action; |
645 | return $res_action; |
646 | } |
646 | } |
647 | else { |
647 | else { |
648 | return 'error'; |
648 | return 'error'; |
649 | } |
649 | } |
650 | } |
650 | } |
651 | 651 | ||
652 | sub set_request_code |
652 | sub set_request_code |
653 | { |
653 | { |
654 | my $request = shift @_; |
654 | my $request = shift @_; |
655 | my $code = shift @_; |
655 | my $code = shift @_; |
656 | my $message = shift @_; |
656 | my $message = shift @_; |
657 | 657 | ||
658 | $request->{'code'} = $code; |
658 | $request->{'code'} = $code; |
659 | $request->{'response'} = $message; |
659 | $request->{'response'} = $message; |
660 | 660 | ||
661 | my $error = "Error $code '$message' in request [\n$request->{'body'}]"; |
661 | my $error = "Error $code '$message' in request [\n$request->{'body'}]"; |
662 | if($code >= 500 && $code < 600) { |
662 | if($code >= 500 && $code < 600) { |
663 | log_error($error); |
663 | log_error($error); |
664 | } |
664 | } |
665 | elsif($code >= 400 && $code < 500) { |
665 | elsif($code >= 400 && $code < 500) { |
666 | log_warning($error); |
666 | log_warning($error); |
667 | } |
667 | } |
668 | elsif($code >= 200 && $code < 300) { |
668 | elsif($code >= 200 && $code < 300) { |
669 | log_info("$code $message"); |
669 | log_info("$code $message"); |
670 | } |
670 | } |
671 | else { |
671 | else { |
672 | log_error("unknown code $code"); |
672 | log_error("unknown code $code"); |
673 | } |
673 | } |
674 | } |
674 | } |
675 | 675 | ||
676 | sub log_debug |
676 | sub log_debug |
677 | { |
677 | { |
678 | log_message("DEBUG", shift @_) if ($log_level >= 9); |
678 | log_message("DEBUG", shift @_) if ($log_level >= 9); |
679 | } |
679 | } |
680 | 680 | ||
681 | sub log_info |
681 | sub log_info |
682 | { |
682 | { |
683 | log_message("INFO", shift @_) if ($log_level >= 5); |
683 | log_message("INFO", shift @_) if ($log_level >= 5); |
684 | } |
684 | } |
685 | 685 | ||
686 | sub log_warning |
686 | sub log_warning |
687 | { |
687 | { |
688 | log_message("WARN", shift @_) if ($log_level >= 3); |
688 | log_message("WARN", shift @_) if ($log_level >= 3); |
689 | } |
689 | } |
690 | 690 | ||
691 | sub log_error |
691 | sub log_error |
692 | { |
692 | { |
693 | log_message("ERROR", shift @_) if ($log_level >= 1); |
693 | log_message("ERROR", shift @_) if ($log_level >= 1); |
694 | } |
694 | } |
695 | 695 | ||
696 | sub log_message |
696 | sub log_message |
697 | { |
697 | { |
698 | print shift @_, ":\t", shift @_, "\n"; |
698 | print shift @_, ":\t", shift @_, "\n"; |
699 | } |
699 | } |
700 | 700 | ||
701 | sub init |
701 | sub init |
702 | { |
702 | { |
703 | $handlers{"${user_header}_${create_action}"} = \&handle_user_create; |
703 | $handlers{"${user_header}_${create_action}"} = \&handle_user_create; |
704 | $handlers{"${user_header}_${modify_action}"} = \&handle_user_modify; |
704 | $handlers{"${user_header}_${modify_action}"} = \&handle_user_modify; |
705 | $handlers{"${user_header}_${delete_action}"} = \&handle_user_delete; |
705 | $handlers{"${user_header}_${delete_action}"} = \&handle_user_delete; |
706 | $handlers{"${domain_header}_${create_action}"} = \&handle_domain_create; |
706 | $handlers{"${domain_header}_${create_action}"} = \&handle_domain_create; |
707 | $handlers{"${domain_header}_${modify_action}"} = \&handle_domain_modify; |
707 | $handlers{"${domain_header}_${modify_action}"} = \&handle_domain_modify; |
708 | $handlers{"${domain_header}_${delete_action}"} = \&handle_domain_delete; |
708 | $handlers{"${domain_header}_${delete_action}"} = \&handle_domain_delete; |
709 | $handlers{"${system_user_header}_${create_action}"} = \&handle_system_user_create; |
709 | $handlers{"${system_user_header}_${create_action}"} = \&handle_system_user_create; |
710 | $handlers{"${system_user_header}_${modify_action}"} = \&handle_system_user_modify; |
710 | $handlers{"${system_user_header}_${modify_action}"} = \&handle_system_user_modify; |
711 | $handlers{"${system_user_header}_${delete_action}"} = \&handle_system_user_delete; |
711 | $handlers{"${system_user_header}_${delete_action}"} = \&handle_system_user_delete; |
712 | $handlers{"${mailbox_header}_${create_action}"} = \&handle_mailbox_create; |
712 | $handlers{"${mailbox_header}_${create_action}"} = \&handle_mailbox_create; |
713 | $handlers{"${mailbox_header}_${modify_action}"} = \&handle_mailbox_modify; |
713 | $handlers{"${mailbox_header}_${modify_action}"} = \&handle_mailbox_modify; |
714 | $handlers{"${mailbox_header}_${delete_action}"} = \&handle_mailbox_delete; |
714 | $handlers{"${mailbox_header}_${delete_action}"} = \&handle_mailbox_delete; |
715 | $handlers{"${mail_alias_header}_${create_action}"} = \&handle_mail_alias_create; |
715 | $handlers{"${mail_alias_header}_${create_action}"} = \&handle_mail_alias_create; |
716 | $handlers{"${mail_alias_header}_${modify_action}"} = \&handle_mail_alias_modify; |
716 | $handlers{"${mail_alias_header}_${modify_action}"} = \&handle_mail_alias_modify; |
717 | $handlers{"${mail_alias_header}_${delete_action}"} = \&handle_mail_alias_delete; |
717 | $handlers{"${mail_alias_header}_${delete_action}"} = \&handle_mail_alias_delete; |
718 | } |
718 | } |
719 | 719 | ||
720 | sub main |
720 | sub main |
721 | { |
721 | { |
722 | #my $sth = $dbh->prepare("SELECT * FROM transport"); |
722 | #my $sth = $dbh->prepare("SELECT * FROM transport"); |
723 | #$sth->execute(); |
723 | #$sth->execute(); |
724 | #while(my $ref = $sth->fetchrow_hashref()) { |
724 | #while(my $ref = $sth->fetchrow_hashref()) { |
725 | # print "id = $ref->{'id'}\n"; |
725 | # print "id = $ref->{'id'}\n"; |
726 | #} |
726 | #} |
727 | #$sth->finish(); |
727 | #$sth->finish(); |
728 | 728 | ||
729 | init(); |
729 | init(); |
730 | connection_loop(); |
730 | connection_loop(); |
731 | } |
731 | } |
732 | 732 | ||
733 | main(); |
733 | main(); |
734 | 734 |