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