#-*- perl -*- # # Copyright (C) 2004,2005,2006 Ken'ichi Fukamachi # All rights reserved. This program is free software; you can # redistribute it and/or modify it under the same terms as Perl itself. # # $FML: config_ph.pm,v 1.25 2006/05/17 12:23:54 fukachan Exp $ # package FML::Merge::FML4::config_ph; use strict; use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD $count $default_config_ph $result %diff_result %config_result %config_default); use Carp; my $debug = 0; =head1 NAME FML::Merge::FML4::config_ph - handle fml4's config.ph file. =head1 SYNOPSIS =head1 DESCRIPTION =head1 METHODS =head2 new() constructor. =cut # Descriptions: constructor. # Arguments: OBJ($self) # Side Effects: none # Return Value: OBJ sub new { my ($self) = @_; my ($type) = ref($self) || $self; my $me = {}; return bless $me, $type; } # Descriptions: set default_config.ph path. # Arguments: OBJ($self) STR($file) # Side Effects: none # Return Value: STR sub set_default_config_ph { my ($self, $file) = @_; $default_config_ph = $file; } # Descriptions: diff config.ph and return it as HASH_REF. # Arguments: OBJ($self) STR($file) # Side Effects: none # Return Value: ARRAY(HASH_REF, HASH_REF) sub diff { my ($self, $file) = @_; # reset always %diff_result = (); %config_result = (); $self->_load_default_config_ph(); my $s = $self->_gen_eval_string($file); eval($s); print "error: $@\n" if $@; # print $result if defined $result; return( \%config_result, \%diff_result ); } # Descriptions: load default_config.ph into "default" name space. # Arguments: none # Side Effects: default name space filled up by default_config.ph content. # Return Value: none sub _load_default_config_ph { package default; no strict; $DIR = '$DIR'; $DOMAINNAME = '$ml_domain'; $MAIL_LIST = '$ml_name@$ml_domain'; $CONTROL_ADDRESS = '$ml_name-ctl@$ml_domain'; $OUTGOING_ADDRESS = '$ml_name-outgoing@$ml_domain'; $MAINTAINER = '$ml_name-admin@$ml_domain'; $ERRORS_TO = '$ml_name-admin@$ml_domain'; $BRACKET = '$ml_name'; $ML_FN = '($ml_name ML)'; $XMLNAME = ''; $GOOD_BYE_PHRASE = ''; $WELCOME_STATEMENT = ''; require $FML::Merge::FML4::config_ph::default_config_ph; $DIR = '$DIR'; $DOMAINNAME = '$ml_domain'; $MAIL_LIST = '$ml_name@$ml_domain'; $CONTROL_ADDRESS = '$ml_name-ctl@$ml_domain'; $OUTGOING_ADDRESS = '$ml_name-outgoing@$ml_domain'; $MAINTAINER = '$ml_name-admin@$ml_domain'; $ERRORS_TO = '$ml_name-admin@$ml_domain'; $BRACKET = '$ml_name'; $ML_FN = '($ml_name ML)'; $GOOD_BYE_PHRASE = '--$ml_name@$ml_domain, Be Seeing You!'; $XMLNAME = 'X-ML-Name: $ml_name'; $WELCOME_STATEMENT =~ s/our /our \(\$ml_name ML\)/; package main; } # Descriptions: generate string to evaluate to load config.ph. # Arguments: OBJ($self) STR($f) # Side Effects: none # Return Value: STR sub _gen_eval_string { my ($self, $f) = @_; my $package = 'FML::Merge::FML4::config_ph'; my $s = ''; $count++; $s = "no strict;\n"; $s .= sprintf("package config%03d;\n", $count); $s .= sprintf("\$DIR = \'\$DIR\';\n"); $s .= sprintf("\$s = &%s::gen_dummy_macros();\n", $package); $s .= sprintf("eval \$s;\n"); $s .= sprintf("print STDERR \$\@ if \$\@;\n"); $s .= sprintf("require \"%s\";\n", $f); $s .= sprintf("package main;\n"); $s .= sprintf("*stab = *{\"config%03d::\"};\n", $count); $s .= sprintf("&%s::dump_variable('config%03d', \\%%stab);\n", $package, $count); $s .= "use strict;\n"; return $s; } # Descriptions: generate diff config.ph against defualt_config.ph and # save it at %diff_result (global variable). # Arguments: STR($package) HASH_REF($stab) # Side Effects: none # Return Value: none sub dump_variable { my ($package, $stab) = @_; my ($key, $val, $def, $x, $rbuf); # resolv eval "\$x = \$${package}::MAIL_LIST;\n"; my ($ml_name, $ml_domain) = split(/\@/, $x); while (($key, $val) = each(%$stab)) { next if $key =~ /^(STRUCT_SOCKADDR|CFVersion|CPU_TYPE_MANUFACTURER_OS|HTML_THREAD_REF_TYPE|FQDN)/; eval "\$val = \$${package}::$key;\n"; eval "\$def = \$default::$key;\n"; $def ||= 0; $val ||= 0; if (defined $val) { $val =~ s/$ml_name/\$ml_name/g; $val =~ s/$ml_domain/\$ml_domain/g; if ($val ne $def) { $rbuf .= "# $key => $val\n"; $diff_result{ $key } = $val || "___nil___"; } # save all values. $config_default{ $key } = $def; $config_result{ $key } = $val; if ($debug) { print "CONFIG: $key => $val\n"; if ($diff_result{ $key }) { print " DIFF: $diff_result{$key}\n"; } } } } $result = $rbuf; } # Descriptions: generate macro definitions used in fml4 config. # Arguments: none # Side Effects: none # Return Value: STR sub gen_dummy_macros { my $s = ''; $s .= "sub GET_HEADER_FIELD_VALUE { \$PROC__GET_HEADER_FIELD_VALUE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub GET_ORIGINAL_HEADER_FIELD_VALUE { \$PROC__GET_ORIGINAL_HEADER_FIELD_VALUE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub SET_HEADER_FIELD_VALUE { \$PROC__SET_HEADER_FIELD_VALUE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub GET_ENVELOPE_VALUE { \$PROC__GET_ENVELOPE_VALUE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub SET_ENVELOPE_VALUE { \$PROC__SET_ENVELOPE_VALUE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub ENVELOPE_APPEND { \$PROC__ENVELOPE_APPEND .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub ENVELOPE_PREPEND { \$PROC__ENVELOPE_PREPEND .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub GET_BUFFER_FROM_FILE { \$PROC__GET_BUFFER_FROM_FILE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub STR2JIS { \$PROC__STR2JIS .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub STR2EUC { \$PROC__STR2EUC .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub JSTR { \$PROC__JSTR .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_SUBJECT_TAG { \$PROC__DEFINE_SUBJECT_TAG .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_MODE { \$PROC__DEFINE_MODE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_FIELD_FORCED { \$PROC__DEFINE_FIELD_FORCED .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_FIELD_ORIGINAL { \$PROC__DEFINE_FIELD_ORIGINAL .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_FIELD_OF_REPORT_MAIL { \$PROC__DEFINE_FIELD_OF_REPORT_MAIL .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_FIELD_PAT_TO_REJECT { \$PROC__DEFINE_FIELD_PAT_TO_REJECT .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_FIELD_LOOP_CHECKED { \$PROC__DEFINE_FIELD_LOOP_CHECKED .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub UNDEF_FIELD_LOOP_CHECKED { \$PROC__UNDEF_FIELD_LOOP_CHECKED .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub ADD_FIELD { \$PROC__ADD_FIELD .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DELETE_FIELD { \$PROC__DELETE_FIELD .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub COPY_FIELD { \$PROC__COPY_FIELD .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub MOVE_FIELD { \$PROC__MOVE_FIELD .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub ADD_CONTENT_HANDLER { \$PROC__ADD_CONTENT_HANDLER .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_MAILER { \$PROC__DEFINE_MAILER .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub PERMIT_PROCEDURE { \$PROC__PERMIT_PROCEDURE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DENY_PROCEDURE { \$PROC__DENY_PROCEDURE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_PROCEDURE { \$PROC__DEFINE_PROCEDURE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub PERMIT_ADMIN_PROCEDURE { \$PROC__PERMIT_ADMIN_PROCEDURE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DENY_ADMIN_PROCEDURE { \$PROC__DENY_ADMIN_PROCEDURE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_ADMIN_PROCEDURE { \$PROC__DEFINE_ADMIN_PROCEDURE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_MAXNUM_OF_PROCEDURE_IN_ONE_MAIL { \$PROC__DEFINE_MAXNUM_OF_PROCEDURE_IN_ONE_MAIL .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DEFINE_MAXNUM_OF_ADMIN_PROCEDURE_IN_ONE_MAIL { \$PROC__DEFINE_MAXNUM_OF_ADMIN_PROCEDURE_IN_ONE_MAIL .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub SIZE { \$PROC__SIZE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub DUMMY { \$PROC__DUMMY .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub TRUE { \$PROC__TRUE .= join(\" \", \@_ ). \" \"; }\n"; $s .= "sub FALSE { \$PROC__FALSE .= join(\" \", \@_ ). \" \"; }\n"; return $s; } =head1 TRANSLATION FROM 4 TO 8 =head2 translate($config, $diff, $key, $value) translate fml4 config {$key => $value } to fml8 one if could. =cut # Descriptions: translate fml4 config {$key => $value } to fml8 one if could. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub translate { my ($self, $config, $diff, $key, $value) = @_; my $dispatch = { rule_convert => \&translate_xxx, rule_ignore => \&translate_ignore, rule_not_yet_implemented => \&translate_not_yet_implemented, rule_prefer_fml4_value => \&translate_xxx, rule_prefer_fml8_value => \&translate_use_fml8_value, }; use FML::Merge::FML4::Rules; my $s = FML::Merge::FML4::Rules::translate($self, $dispatch, $config, $diff, $key, $value); return $s; } # Descriptions: translate fml4 config {$key => $value } to fml8 one if could. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub translate_xxx { my ($self, $config, $diff, $key, $value) = @_; if ($key eq 'SUBJECT_TAG_TYPE' || $key eq 'SUBJECT_HML_FORM' || $key eq 'HML_FORM_LONG_ID') { return $self->_fix_subject_tag($config, $diff, $key, $value); } elsif ($key eq 'PERMIT_POST_FROM' || $key eq 'REJECT_POST_HANDLER' || $key eq 'PERMIT_COMMAND_FROM' || $key eq 'REJECT_COMMAND_HANDLER') { return $self->_fix_restrictions($config, $diff, $key, $value); } elsif ($key eq 'MAINTAINER') { my $value = $self->_fix_address($config, $diff, $key, $value); return "maintainer = $value"; } elsif ($key eq 'MAIL_LIST') { my $value = $self->_fix_address($config, $diff, $key, $value); return "article_post_address = $value"; } elsif ($key eq 'CONTROL_ADDRESS') { my $value = $self->_fix_address($config, $diff, $key, $value); return "command_mail_address = $value"; } elsif ($key eq 'OUTGOING_ADDRESS') { my $value = $self->_fix_address($config, $diff, $key, $value); return ""; return "# WARNING outgoing_address = $value"; } elsif ($key eq 'SMTP_SENDER') { my $value = $self->_fix_address($config, $diff, $key, $value); return "smtp_sender = $value"; } elsif ($key eq 'ERRORS_TO') { my $value = $self->_fix_address($config, $diff, $key, $value); return "mail_header_default_errors_to = $value"; } elsif ($key eq 'LIST_POST' || $key eq 'LIST_OWNER' || $key eq 'LIST_HELP' || $key eq 'LIST_SUBSCRIBE' || $key eq 'LIST_UNSUBSCRIBE' || $key eq 'LIST_ID' ) { my $value = $self->_fix_address($config, $diff, $key, $value); my $var_name = sprintf("mail_header_default_%s", lc($key)); return "$var_name = $value"; } elsif ($key eq 'REJECT_ADDR') { my ($list) = join(" ", split(/\|/, $value)); return "system_special_accounts = $list"; } elsif ($key eq 'HOST' || $key eq 'PORT') { my $host = $diff->{ 'HOST' } || '127.0.0.1'; my $port = $diff->{ 'PORT' } || 25; $host = $host eq '___nil___' ? '127.00.1' : $host; $port = $port eq '___nil___' ? 25 : $port; return "smtp_servers = $host:$port"; } elsif ($key eq 'SPOOL_DIR' || $key eq 'TMP_DIR') { my $v = $self->_fix_path($config, $diff, $key, $value); if ($v) { $key =~ tr/A-Z/a-z/; return "$key = $v"; } else { return ""; } } elsif ($key eq 'ADMIN_MEMBER_LIST') { $value = $self->_fix_path($config, $diff, $key, $value); return "primary_admin_member_map = $value"; } elsif ($key eq 'MEMBER_LIST') { $value = $self->_fix_path($config, $diff, $key, $value); return "primary_member_map = $value"; } elsif ($key eq 'ACTIVE_LIST') { $value = $self->_fix_path($config, $diff, $key, $value); return "primary_recipient_map = $value"; } elsif ($key eq 'MODERATOR_MEMBER_LIST') { $value = $self->_fix_path($config, $diff, $key, $value); my $r1 = "primary_moderator_member_map = $value"; my $r2 = "primary_moderator_recipient_map = $value"; return "$r1\n\n$r2"; } elsif ($key eq 'PASSWD_FILE') { $value = $self->_fix_path($config, $diff, $key, $value); return "primary_admin_member_password_map = $value"; } elsif ($key eq 'LOGFILE') { $value = $self->_fix_path($config, $diff, $key, $value); return "log_file = $value"; } elsif ($key eq 'GUIDE_FILE') { $value = $self->_fix_path($config, $diff, $key, $value); return "guide_file = $value"; } elsif ($key eq 'OBJECTIVE_FILE') { $value = $self->_fix_path($config, $diff, $key, $value); return "objective_file = $value"; } elsif ($key eq 'WELCOME_FILE') { $value = $self->_fix_path($config, $diff, $key, $value); return "welcome_file = $value"; } elsif ($key eq 'DENY_FILE') { $value = $self->_fix_path($config, $diff, $key, $value); return "deny_file = $value"; } elsif ($key eq 'SEQUENCE_FILE') { $value = $self->_fix_path($config, $diff, $key, $value); return "article_sequence_file = $value"; } elsif ($key eq 'SUMMARY_FILE') { $value = $self->_fix_path($config, $diff, $key, $value); return "summary_file = $value"; } elsif ($key eq 'REJECT_ADDR_LIST') { $value = $self->_fix_path($config, $diff, $key, $value); return "primary_spammer_map = $value"; } elsif ($key eq 'SKIP_FIELDS') { return $self->_fix_skip_fields($config, $diff, $key, $value); } elsif ($key eq 'FILE_TO_REGIST') { $value = $self->_fix_path($config, $diff, $key, $value); my $s = ''; $s .= "primary_member_map = $value\n"; $s .= "primary_recipient_map = $value\n"; return $s; } elsif ($key eq 'ML_MEMBER_CHECK') { return $self->_fix_acl_policy($config, $diff, $key, $value); } elsif ($key eq 'LOAD_LIBRARY') { return $self->_fix_module_definition($config, $diff, $key, $value); } elsif ($key eq 'TZone') { return $self->_fix_time_zone($config, $diff, $key, $value); } elsif ($key eq 'INCOMING_MAIL_SIZE_LIMIT') { my ($s, $v); $v = $self->_fix_atoi($config, $diff, $key, $value); $s .= sprintf("incoming_article_body_size_limit = %d\n\n", $v); $s .= sprintf("incoming_command_mail_body_size_limit = %d\n\n", $v); return $s; } elsif ($key eq 'LOGFILE_NEWSYSLOG_LIMIT') { my ($s, $v); $v = $self->_fix_atoi($config, $diff, $key, $value); $s .= sprintf("use_log_rotate = yes\n\n"); $s .= sprintf("log_rotate_size_limit = %d\n\n", $v); return $s; } elsif ($key eq 'XMLNAME') { my ($s, $v); $v = $value; $v =~ s/X-ML-Name:\s+//g; $s .= sprintf("outgoing_mail_header_x_ml_name = %s\n\n", $v); return $s; } elsif ($key eq 'LOGFILE_SUFFIX') { if ($diff->{ LOGFILE }) { my $old = $config->{ LOGFILE }; my $log = $self->_fix_path($config, $diff, "LOGFILE", $old); my $s = sprintf("log_file = %s%s\n\n", $log, $value); return $s; } else { my $s = sprintf("log_file = \$ml_home_dir/log%s\n\n", $value); return $s; } } elsif ($key eq 'MAX_MEMBER_LIMIT') { my $s = ''; $s .= sprintf("use_recipient_total_limit = yes\n\n"); $s .= sprintf("recipient_total_limit = %d\n\n", $value); return $s; } return '# ***ERROR*** UNKNOWN TRANSLATION RULE'; } # Descriptions: restrictions # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_restrictions { my ($self, $config, $diff, $key, $value) = @_; my $p_result = ''; my $c_result = ''; unless ( $self->{ _cache }->{ restrictions } ) { my $permit_post_from = $config->{ PERMIT_POST_FROM } || ''; my $reject_post_handler = $config->{ REJECT_POST_HANDLER } || ''; my $permit_command_from = $config->{ PERMIT_COMMAND_FROM } || ''; my $reject_command_handler = $config->{ REJECT_COMMAND_HANDLER } || ''; # flags my $mode = 'manual'; my $symmetric = 1; # # permit_*_from based # if ($permit_post_from eq 'anyone') { $p_result .= "article_post_restrictions = "; $p_result .= "reject_system_special_accounts "; $p_result .= "reject_spammer_maps "; $p_result .= "permit_anyone "; $p_result .= "reject\n"; } elsif ($permit_post_from eq 'members_only') { # fml8 default $p_result .= "article_post_restrictions = "; $p_result .= "reject_system_special_accounts "; $p_result .= "reject_spammer_maps "; $p_result .= "permit_member_maps "; $p_result .= "reject\n"; ; } elsif ($permit_post_from eq 'moderator') { $p_result .= "article_post_restrictions = "; $p_result .= "reject_system_special_accounts "; $p_result .= "reject_spammer_maps "; $p_result .= "permit_forward_to_moderator "; $p_result .= "reject\n"; } # # handler based # if ($reject_post_handler =~ /auto_regist|autoregist|auto_subscribe/) { $mode = "automatic"; $symmetric = 1; } elsif ($reject_post_handler =~ /auto_asymmetric_regist/) { $mode = "automatic"; $symmetric = 0; } elsif ($reject_post_handler eq 'ignore') { if ($p_result =~ /article_post_restrictions/) { $p_result =~ s/\s+reject\s*$/ ignore/g; } else { $c_result .= "\n"; $p_result .= "article_post_restrictions = "; $p_result .= "reject_system_special_accounts "; $p_result .= "permit_member_maps "; $p_result .= "ignore\n"; } } elsif ($reject_post_handler eq 'reject') { } # # permit_*_from based # if ($permit_command_from eq 'anyone') { $c_result .= "command_mail_restrictions = "; $c_result .= "reject_system_special_accounts "; $c_result .= "reject_spammer_maps "; $c_result .= "permit_anyone "; $c_result .= "reject\n"; } elsif ($permit_command_from eq 'members_only') { # fml8 default $c_result .= "command_mail_restrictions = "; $c_result .= "reject_system_special_accounts "; $c_result .= "reject_spammer_maps "; $c_result .= "permit_anonymous_command "; $c_result .= "permit_user_command "; $c_result .= "reject\n"; } elsif ($permit_command_from eq 'moderator') { $c_result .= "command_mail_restrictions = "; $c_result .= "reject_system_special_accounts "; $c_result .= "reject_spammer_maps "; $c_result .= "permit_forward_to_moderator "; $c_result .= "reject\n"; } if ($reject_command_handler eq 'ignore') { if ($c_result =~ /command_mail_restrictions/) { $c_result =~ s/\s+reject\s*$/ ignore/g; } else { $c_result .= "\n"; $c_result .= "command_mail_restrictions = "; $c_result .= "reject_system_special_accounts "; $c_result .= "reject_spammer_maps "; $c_result .= "permit_anonymous_command "; $c_result .= "permit_user_command "; $c_result .= "ignore\n"; } } elsif ($reject_command_handler =~ /auto_regist|autoregist|auto_subscribe/) { $mode = "automatic"; $symmetric = 1; } elsif ($reject_command_handler =~ /auto_asymmetric_regist/) { $mode = "automatic"; $symmetric = 0; } elsif ($reject_command_handler eq "reject") { ; } unless ($symmetric) { ; # ? } if ($mode eq 'manual') { $c_result .= "\nsubscribe_command_operation_mode = manual\n"; } elsif ($mode eq 'automatic') { $c_result .= "\nsubscribe_command_operation_mode = automatic\n"; } else { $c_result .= "\n# unknown operation mode = $mode\n"; } $self->{ _cache }->{ restrictions } = 1; return "$p_result\n$c_result\n"; } else { return "# OK (already translated)\n"; } } # Descriptions: convert address related parameters. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_address { my ($self, $config, $diff, $key, $value) = @_; my $address = $value; my $fqdn = `hostname`; $fqdn =~ s/\s*$//; $address =~ s/\$DOMAINNAME/\$ml_domain/g; $address =~ s/\$FQDN/$fqdn/g; return $address; } # Descriptions: handle map info. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_path { my ($self, $config, $diff, $key, $value) = @_; # 1. $value is either of ^$DIR or ^./ directory. if ($self->_is_relative_to_fml4_home_dir($value)) { my $relative_path = $self->_cutoff_fml4_home_dir_prefix($value); return $self->_fml8_absolete_path($relative_path); } # 2. $value is absolute path. elsif ($self->_is_absolute_path($value)) { return $value; } # 3. $value is a file name only (must be relative to $DIR or ./ directory). else { return $self->_fml8_absolete_path($value); } } # Descriptions: check if $path is relative to fml4 $DIR. # Arguments: OBJ($self) STR($path) # Side Effects: none # Return Value: NUM sub _is_relative_to_fml4_home_dir { my ($self, $path) = @_; if ($path =~ /^\$DIR/ || $path =~ /^\.\//) { return 1; } else { return 0; } } # Descriptions: check if $path is absolute. # Arguments: OBJ($self) STR($path) # Side Effects: none # Return Value: NUM sub _is_absolute_path { my ($self, $path) = @_; use File::Spec; return File::Spec->file_name_is_absolute($path); } # Descriptions: check if $path is relative to fml4 $DIR. # Arguments: OBJ($self) STR($path) # Side Effects: none # Return Value: NUM sub _cutoff_fml4_home_dir_prefix { my ($self, $path) = @_; $path =~ s/^\$DIR//; $path =~ s/^\.//; $path =~ s/^\///; return $path; } # Descriptions: relative path-ify. # Arguments: OBJ($self) STR($path) # Side Effects: none # Return Value: STR sub _split_path { my ($self, $path) = @_; use File::Spec; my ($volume, $directories, $file) = File::Spec->splitpath( $path ); return $file; } # Descriptions: be absolete path. # Arguments: OBJ($self) STR($x) # Side Effects: none # Return Value: STR sub _fml8_absolete_path { my ($self, $x) = @_; use File::Spec; return File::Spec->catfile('$ml_home_dir', $x); } # Descriptions: acl policy. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_acl_policy { my ($self, $config, $diff, $key, $value) = @_; if ($key eq 'ML_MEMBER_CHECK') { if ($value) { return '# same as fml8 default'; } else { # post = auto_regist, command = auto_regist return '# same as fml8 default'; } } return '# ***ERROR*** UNKNOWN TRANSLATION POLICY'; } # Descriptions: acl policy. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_module_definition { my ($self, $config, $diff, $key, $value) = @_; if ($key eq 'LOAD_LIBRARY') { if ($value eq 'libfml.pl') { return '# same as fml8 default'; } } return '# ***ERROR*** UNKNOWN TRANSLATION POLICY'; } # Descriptions: fix time zone. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_time_zone { my ($self, $config, $diff, $key, $value) = @_; if ($value eq ' JST') { return "system_timezone = +0900"; } return "# ***ERROR*** UNKNOWN TIME ZONE"; } # Descriptions: handle subject tag related conversion. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_skip_fields { my ($self, $config, $diff, $key, $value) = @_; my (@fields) = split(/\|/, $value); return "unsafe_header_fields = @fields"; } # # FYI: [fml4 conversion logic] # # if ($SUBJECT_HML_FORM) { # if ($HML_FORM_LONG_ID || $SUBJECT_FORM_LONG_ID) { # LONG ID # } # "[BRACKET:ID]"; # } # elsif ($SUBJECT_FREE_FORM) { # if ($SUBJECT_FORM_LONG_ID) { # LONG ID # } # # if ($BRACKET_SEPARATOR ne '') { # $BEGIN_BRACKET.$BRACKET.$BRACKET_SEPARATOR.$id.$END_BRACKET; # } # else { # if ($BRACKET) { # $BEGIN_BRACKET.$BRACKET.$END_BRACKET; # } # else { # $BEGIN_BRACKET.$id.$END_BRACKET; # } # } # } # Descriptions: handle subject tag related conversion. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_subject_tag { my ($self, $config, $diff, $key, $value) = @_; my $s = "article_header_rewrite_rules += rewrite_article_subject_tag\n\n"; # ensure uniqueness return '# ALREADY TRANSLATED' if $self->{ _subject_tag_fixed }; $self->{ _subject_tag_fixed } = 1; # variables my $type = $diff->{ 'SUBJECT_TAG_TYPE' } || ''; my $bracket = $diff->{ 'BRACKET' } || ''; my $bracket_sep = $diff->{ 'BRACKET_SEPARATOR' } || ''; my $free_form = $diff->{ 'SUBJECT_FREE_FORM' } || ''; my $free_form_regexp = $diff->{ 'SUBJECT_FREE_FORM_REGEXP' } || ''; my $free_long_id = $diff->{ 'SUBJECT_FORM_LONG_ID' } || 5; # fml2 compatible if ($diff->{ 'SUBJECT_HML_FORM' }) { $type = '[:]'; } if ($diff->{ 'HML_FORM_LONG_ID' }) { $free_long_id = $diff->{ 'HML_FORM_LONG_ID' }; } if ($type eq '[:]') { $s .= "article_subject_tag = [\$ml_name:\%05d]\n"; } elsif ($type eq '[,]') { $s .= "article_subject_tag = [\$ml_name,\%05d]\n"; } elsif ($type eq '[ ]') { $s .= "article_subject_tag = [\$ml_name \%05d]\n"; } elsif ($type eq '(:)') { $s .= "article_subject_tag = (\$ml_name:\%05d)\n"; } elsif ($type eq '(,)') { $s .= "article_subject_tag = (\$ml_name,\%05d)\n"; } elsif ($type eq '( )') { $s .= "article_subject_tag = (\$ml_name \%05d)\n"; } elsif ($type eq '()') { $s .= "article_subject_tag = (\$ml_name)\n"; } elsif ($type eq '[]') { $s .= "article_subject_tag = [\$ml_name]\n"; } elsif ($type eq '(ID)') { $s .= "article_subject_tag = (\%05d)\n"; } elsif ($type eq '[ID]') { $s .= "article_subject_tag = [\%05d]\n"; } else { $s .= "article_subject_tag = [\%05d]\n"; } if ($free_long_id != 5) { my $r = sprintf("%%0%dd", $free_long_id); $s =~ s/\%05d/$r/g; } return $s; } # Descriptions: convert from ascii to number. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub _fix_atoi { my ($self, $config, $diff, $key, $value) = @_; my $x = $value; if ($x =~ /^(\d+)$/) { ; } elsif ($x =~ /^(\d+)K$/i) { $x *= 1024; } elsif ($x =~ /^(\d+)M$/i) { $x *= 1024*1024; } return $x; } # Descriptions: ignore translation since this variable uses fml8 value. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub translate_use_fml8_value { my ($self, $config, $diff, $key, $value) = @_; return "# IGNORED since \$$key prefers fml8 value."; } # Descriptions: ignore translation since this variable uses fml8 value. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub translate_ignore { my ($self, $config, $diff, $key, $value) = @_; return "# IGNORED since \$$key is of no means."; } # Descriptions: show this variable is not yet implemented. # Arguments: OBJ($self) # HASH_REF($config) HASH_REF($diff) STR($key) STR($value) # Side Effects: none # Return Value: STR sub translate_not_yet_implemented { my ($self, $config, $diff, $key, $value) = @_; return "# ERROR. SORRY \$$key IS NOT YET IMPLEMENTED."; } =head1 CODING STYLE See C on fml coding style guide. =head1 AUTHOR Ken'ichi Fukamachi =head1 COPYRIGHT Copyright (C) 2004,2005,2006 Ken'ichi Fukamachi All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 HISTORY FML::Merge::FML4::config_ph appeared in fml8 mailing list driver package. See C for more details. =cut 1;