summaryrefslogtreecommitdiff
path: root/fml/doc
diff options
context:
space:
mode:
authorfukachan <fukachan>2005-07-27 12:21:35 +0000
committerfukachan <fukachan>2005-07-27 12:21:35 +0000
commit02f0eb5231edfb665704bd0cfd9bfbe5ec59fae1 (patch)
treea1a9302fc1d5d74b41fe5659504c59501e2f5ab9 /fml/doc
parent1a4284d5533f07c7b4828a5283281e95b8bd3f3e (diff)
downloadfml8-02f0eb5231edfb665704bd0cfd9bfbe5ec59fae1.tar.gz
fml8-02f0eb5231edfb665704bd0cfd9bfbe5ec59fae1.tar.bz2
fml8-02f0eb5231edfb665704bd0cfd9bfbe5ec59fae1.zip
sync and translated.
Diffstat (limited to 'fml/doc')
-rw-r--r--fml/doc/en/tutorial/internals/CURPROC.sgml16
-rw-r--r--fml/doc/en/tutorial/internals/PCB.sgml64
-rw-r--r--fml/doc/en/tutorial/internals/bootloader.sgml221
-rw-r--r--fml/doc/en/tutorial/internals/cgi.examples.sgml125
-rw-r--r--fml/doc/en/tutorial/internals/config.cf.sgml16
-rw-r--r--fml/doc/en/tutorial/internals/credential.sgml4
-rw-r--r--fml/doc/en/tutorial/internals/dbms.sgml28
-rw-r--r--fml/doc/en/tutorial/internals/directory.sgml49
-rw-r--r--fml/doc/en/tutorial/internals/language.sgml224
-rw-r--r--fml/doc/en/tutorial/internals/lock.sgml83
-rw-r--r--fml/doc/en/tutorial/internals/main.cf.sgml119
-rw-r--r--fml/doc/en/tutorial/internals/merge.sgml122
-rw-r--r--fml/doc/en/tutorial/internals/restriction.sgml202
-rw-r--r--fml/doc/en/tutorial/internals/struct.sgml29
-rw-r--r--fml/doc/en/tutorial/internals/userctl.sgml57
15 files changed, 1331 insertions, 28 deletions
diff --git a/fml/doc/en/tutorial/internals/CURPROC.sgml b/fml/doc/en/tutorial/internals/CURPROC.sgml
index e6fc8f2b..8296e4c6 100644
--- a/fml/doc/en/tutorial/internals/CURPROC.sgml
+++ b/fml/doc/en/tutorial/internals/CURPROC.sgml
@@ -2,19 +2,24 @@
<screen>
__parent_args => HASH {
ARGV => ARRAY
+ ___shared_memory___ => HASH
argv => ARRAY
cf_list => ARRAY
+ curproc => FML::Process::Distribute
fml_version
main_cf => HASH
module_info => HASH
myname
need_ml_name
options => HASH
+ program_fullname
program_name
}
__print_style => SCALAR
+__start_time => SCALAR
+
article => HASH {
body => Mail::Message
header => FML::Header
@@ -31,29 +36,38 @@ incoming_message => HASH {
message => Mail::Message
}
+log_message_queue => FML::Log::Print::Simple
+
main_cf => HASH {
- _hints
+ _hints => HASH
config_dir
debug
default_command_line_option_config
default_config_cf
default_config_dir
+ default_cui_menu
default_domain
+ default_gui_menu
default_ml_home_prefix
default_module_config
default_paths_cf
domain_default_config
+ domain_default_config_cf
exec_prefix
executable_prefix
fml_group
fml_owner
fml_version
+ group_writable_config_dir
lib_dir
libexec_dir
local_lib_dir
+ ml_home_prefix_maps
prefix
prefix_dir
+ primary_ml_home_prefix_map
share_dir
+ site_default_config_cf
virtual_maps
}
diff --git a/fml/doc/en/tutorial/internals/PCB.sgml b/fml/doc/en/tutorial/internals/PCB.sgml
new file mode 100644
index 00000000..975bc3fa
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/PCB.sgml
@@ -0,0 +1,64 @@
+<para>
+<screen>
+module function category
+ <-- (get value)
+ --> (set value)
+--------------------------------------------------------------------------------
+Error run --> error
+Error finish <-- error
+Fake set_emul_domain --> faker
+Fake get_emul_domain <-- faker
+Fake set_emul_ml_list --> faker
+Fake get_emul_ml_list <-- faker
+Fake set_emul_user_list --> faker
+Fake get_emul_user_list <-- faker
+Kernel sysflow_reopen_stderr_channel --> stderr
+Kernel sysflow_reopen_stderr_channel --> stderr
+Kernel sysflow_finalize_stderr_channel <-- stderr
+Kernel sysflow_finalize_stderr_channel <-- stderr
+Kernel sysflow_finalize_stderr_channel --> stderr
+State current_process_set_ml_name <-- current_process
+State current_process_get_ml_name <-- current_process
+State restriction_state_set_deny_reason --> check_restrictions
+State restriction_state_get_deny_reason <-- check_restrictions
+State article_set_id --> article_message
+State article_get_id <-- article_message
+State command_context_set_ml_name --> process_command
+State command_context_get_ml_name <-- process_command
+State command_context_set_stop_process --> process_command
+State command_context_get_stop_process <-- process_command
+State command_context_set_normal_stop --> process_command
+State command_context_get_normal_stop <-- process_command
+State command_context_set_need_confirm --> process_command
+State command_context_get_need_confirm <-- process_command
+State command_context_set_admin_auth --> process_command
+State command_context_get_admin_auth <-- process_command
+State command_context_set_admin_password --> process_command
+State command_context_get_admin_password <-- process_command
+State command_context_set_try_admin_auth_request --> process_command
+State command_context_reset_try_admin_auth_request --> process_command
+State command_context_get_try_admin_auth_request <-- process_command
+State filter_state_set_error --> filter_state
+State filter_state_get_error <-- filter_state
+State filter_state_spam_checker_set_error --> filter_state
+State filter_state_spam_checker_get_error <-- filter_state
+State filter_state_virus_checker_set_error --> filter_state
+State filter_state_virus_checker_get_error <-- filter_state
+State filter_state_set_tempfail_request --> filter_state
+State filter_state_get_tempfail_request <-- filter_state
+State smtp_server_state_set_error --> smtp_transaction
+State smtp_server_state_get_error <-- smtp_transaction
+State error_message_set_count <-- reply_message_count
+State error_message_set_count --> reply_message_count
+State error_message_get_count <-- reply_message_count
+Utils incoming_message_set_cache_file_path --> incoming_message
+Utils incoming_message_get_cache_file_path <-- incoming_message
+Utils incoming_message_set_current_queue --> incoming_smtp_transaction
+Utils incoming_message_get_current_queue <-- incoming_smtp_transaction
+Utils set_language_hint --> language_hint
+Utils get_language_hint <-- language_hint
+Utils set_charset --> charset
+Utils get_charset <-- charset
+Utils get_charset <-- charset
+</screen>
+</para>
diff --git a/fml/doc/en/tutorial/internals/bootloader.sgml b/fml/doc/en/tutorial/internals/bootloader.sgml
new file mode 100644
index 00000000..e7c9d6b8
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/bootloader.sgml
@@ -0,0 +1,221 @@
+<!--
+ $FML: bootloader.sgml,v 1.13 2005/06/25 15:11:33 fukachan Exp $
+-->
+
+
+<chapter id="bootloader">
+ <title>
+ &fml8; boot loader to resolv version dependence dynamically
+ </title>
+
+<para>
+&fml8; provides a boot loader to resolv version dependence dynamically.
+For example, the loader boot straps &fml8; as follows:
+<screen>
+fml (libexec/distribute) boots like this ...
+
+ functions class
+ ----------------------------------------
+
+ main::Bootstrap() libexec/loader
+ |
+ V
+ main::Bootstrap2() FML::Process::Switch
+ |
+ V
+ ProcessSwitch() FML::Process::Switch
+ |
+ |
+ | switch to ($obj = FML::Process:Distribute)
+ |
+ V
+ ProcessStart($obj,$args) FML::Process::Flow
+</screen>
+</para>
+
+
+<sect1 id="bootloader.example.distribute">
+ <title>
+ Case: distribution
+ </title>
+
+<para>
+&fml8; loader boot straps like this in the case of distribution.
+</para>
+
+<para>
+/usr/local/libexec/fml/distributre (== /usr/local/libexec/fml/loader
+in fact) reads /usr/local/etc/fml/main.cf and resolvers the version it
+should use from $fml_version variable. Let $fml_version
+current-20010501. The loader uses library perl modules under
+/usr/local/lib/fml/current-20010501/.
+</para>
+
+<para>
+The loader resets @INC (perl include path).
+It loads FML::Process::Switch and checks $0 (program name in process table).
+The loader resolves from the name that the role is distribution.
+It loads FML::Process::Distribute and switches to the class.
+</para>
+
+<para>
+The relation between program name and class (perl module) is defined
+at /usr/local/etc/fml/defaults/$fml_version/modules file.
+</para>
+
+<para>
+FML::Process::Flow::ProcessStart() function drives these sequential
+steps. ProcessStart() takes FML::Process::Distribute object as an
+argument and drives the object.
+</para>
+
+</sect1>
+
+
+<sect1 id="bootloader.classes">
+ <title>
+ FML::Process:: class structure
+ </title>
+
+<para>
+<screen>
+FML::Process::Distribute >-|
+FML::Process::Command >-|-- FML::Process::Kernel
+FML::Process::Mead >-| |
+ |-use-a FML::Parse
+ |-use-a FML::Config
+ |-use-a FML::Log
+ |-use-a ... SOMETHING ...
+</screen>
+
+</para>
+</sect1>
+
+
+<sect1 id="bootloader.classes2">
+ <title>
+ Modules in process execution
+ </title>
+
+<itemizedlist>
+
+ <listitem>
+ <para>
+ libexec/loader (wrapper):
+ executes Bootstrap() runction.
+ libexec/distribute et.al. is a symlink(2) to this loader.
+ See under /usr/local/libexec/fml/ path.
+ </para>
+ </listitem>
+
+ <listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ reads /usr/local/etc/fml/main.cf and resolves $fml_version.
+ reset @INC by main.cf value.
+ Since default_config.cf is version dependent,
+ the loader should evaluate the file before it reads
+ ML specific configuration files.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Evaluate @ARGV and resolves which ML specific configuration
+ files we need to load.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ load FML::Process::Switch class which is also version dependent.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ The loader executes Bootstrap2() and ProcessSwitch()
+ to switch the context to each one such as
+ distribution, command mail et.al.
+ In this time, the loader knows the role
+ from $0 process name.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Exapmle of Polymorphyism:
+ dynamic binding of module and creation of process
+ object in starting the process.
+
+ FML::Process::Flow describes the flow of process
+ like this:
+<screen>
+$process = new FML::Process::SOMETHING;
+$process->prepare($args);
+$process->verify_request($args);
+$process->run($args);
+$process->finish($args);
+</screen>
+ Each process should probide proper methods under
+ FML::Process:: class.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+</itemizedlist>
+</sect1>
+
+
+<sect1 id="bootloader.resolv.mlxxx">
+ <title>
+ Discussion: where function should resolve $ml_name and $ml_domain.
+ </title>
+
+<para>
+Currently &fml8; resolves them in prepare() under FML::Process:: classes.
+</para>
+
+<para>
+Here is a part of background idea.
+<screen>
+main::Bootstrap()
+
+ resoles $fml_version based on main.cf information.
+
+ pass hints to some processes e.g. CGI.
+ CGI only
+ it should ignore invalid input.
+ $ml_name $and ml_domain is hard-coded in cgi scripts.
+
+
+main::Bootstrap2()
+ProcessSwitch()
+
+ resolves the module, configuration files, library path and @INC.
+
+ pass hints to some processes e.g. CGI.
+ CGI only
+
+ProcessStart($obj, $args)
+
+ main process starts
+
+ new
+
+ prepare
+ resoles $ml_name and $ml_domain.
+ parse input from CGI using hints.
+ determine ml specific configuration files.
+ parse incoming message.
+ parse command line arguments.
+</screen>
+</para>
+
+</sect1>
+
+
+</chapter>
diff --git a/fml/doc/en/tutorial/internals/cgi.examples.sgml b/fml/doc/en/tutorial/internals/cgi.examples.sgml
new file mode 100644
index 00000000..bf10702d
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/cgi.examples.sgml
@@ -0,0 +1,125 @@
+<!--
+ $FML: cgi.examples.sgml,v 1.3 2005/06/25 15:11:33 fukachan Exp $
+-->
+
+
+<sect1 id="cgi.internal.example.isa">
+ <title>
+ CGI implementation: inheritance among CGI classes
+ </title>
+
+<para>
+@ISA of config.cgi follow:
+<screen>
+FML::CGI::Menu FML::Process::CGI::Kernel FML::Process::CGI::Param
+</screen>
+In the case of thread.cgi, @ISA is
+<screen>
+FML::CGI::Thread FML::Process::CGI::Kernel FML::Process::CGI::Param
+</screen>
+</para>
+
+<para>
+.cgi specific codes locate at FML::CGI:: class layer.
+</para>
+
+<para>
+FML::Process::CGI::Kernel provides the main part of CGI process
+and CGI specific function run_cgi_XXX().
+If needed, FML::CGI:: class overloads this layer.
+Currently,
+the following methods in FML::Process::CGI::Kernel are not used.
+<screen>
+run_cgi_log
+run_cgi_dummy
+run_cgi_date
+</screen>
+</para>
+
+</sect1>
+
+
+<sect1 id="cgi.internal.example.config.cgi">
+ <title>
+ CGI Implementation: config.cgi
+ </title>
+
+<para>
+@ISA of config.cgi is as follows:
+<screen>
+FML::CGI::Menu FML::Process::CGI::Kernel FML::Process::CGI::Param
+</screen>
+Let see processing of config.cgi below.
+</para>
+
+<para>
+config.cgi process object $curproc is a
+FML::Process::CGI::Kernel class.
+<screen>
+ new()
+ prepare()
+ verify_request()
+ run()
+ finish()
+</screen>
+is sequentially called from FML::Process::CGI::Kernel class.
+</para>
+
+<para>
+run() is important. run() executes the following methods sequentially.
+<screen>
+ $curproc->html_start(); (FML::CGI::Menu)
+ $curproc->_drive_cgi_by_table(); (FML::Process::CGI::Kernel)
+ $curproc->html_end(); (FML::CGI::Menu)
+</screen>
+_drive_cgi_by_table() prepares the screen.
+This function calls the main part of CGI.
+</para>
+
+<para>
+$curproc->_drive_cgi_by_table()
+calles the following run_XXX() methods.
+<screen>
+run_cgi_main (FML::CGI::Menu)
+</screen>
+calls cgi_execute_command (FML::Process::CGI::Kernel) to
+execute FML::Command::Admin::$COMMAND via FML::Command class.
+This is the main part of command execution via CGI but
+the screen creation is a role of another part.
+</para>
+
+<para>
+For example, consider subscribe an address via CGI.
+run_cgi_main() executes the real process of subscription.
+Instead run_cgi_menu() creates input menu.
+Former calls FML::Command::Admin::subscribe::process() method,
+latter calls FML::Command::Admin::subscribe::cgi_menu() method.
+</para>
+
+<para>
+There are several other run_cgi_XXX() methods. They are optional for
+screen creation.
+</para>
+
+<para>
+The following run_cgi_XXX() uses the default method.
+<screen>
+run_cgi_title FML::Process::CGI::Kernel (show title)
+run_cgi_options FML::Process::CGI::Kernel (show language selection)
+</screen>
+.cgi specific methods are as follows:
+<screen>
+run_cgi_navigator FML::CGI::Menu
+run_cgi_help FML::CGI::Menu
+run_cgi_command_help FML::CGI::Menu
+run_cgi_menu FML::CGI::Menu
+</screen>
+</para>
+
+<para>
+run_cgi_menu() executes
+FML::Command::Admin::COMMAND::cgi_menu()
+via cgi_execute_cgi_menu() method.
+</para>
+
+</sect1>
diff --git a/fml/doc/en/tutorial/internals/config.cf.sgml b/fml/doc/en/tutorial/internals/config.cf.sgml
index 154c0db6..db55cee8 100644
--- a/fml/doc/en/tutorial/internals/config.cf.sgml
+++ b/fml/doc/en/tutorial/internals/config.cf.sgml
@@ -1,9 +1,9 @@
<!--
- $FML: config.cf.sgml,v 1.1 2003/07/27 01:29:28 fukachan Exp $
+ $FML: config.cf.sgml,v 1.2 2003/08/03 05:28:48 fukachan Exp $
$jaFML: config.cf.sgml,v 1.11 2003/06/20 22:23:14 fukachan Exp $
-->
-<chapter>
+<chapter id="internal.config.cf">
<title>
Configuration file: config.cf
</title>
@@ -21,13 +21,13 @@ You can customize each ML differently.
</para>
<para>
-In the case of &fml4;, there are $DIR and config.ph in ML home
-directory. This "config.ph" file is a perl script.
+In the case of &fml4;, there is a config.ph in ML home directory,
+$DIR (e.g. /var/spool/ml). This "config.ph" file is a perl script.
</para>
<para>
There is a config.cf file in &fmldevel;, too.
-But the format is diffrent. The format is like this:
+But the format is different. The format is like this:
<screen>
variable = value
</screen>
@@ -35,6 +35,10 @@ variable = value
It is similar to postfix or .ini files.
</para>
+<para>
+It is similar to a perl module. You can write perl codes after =cut line.
+</para>
+
<sect2>
<title>
@@ -128,7 +132,7 @@ since the last $a overwrites the previous one.
<!-- ======================================= -->
-<sect1>
+<sect1 id="config.cf.format.extension">
<title>
Extension to postfix style
</title>
diff --git a/fml/doc/en/tutorial/internals/credential.sgml b/fml/doc/en/tutorial/internals/credential.sgml
index 825b345c..e771ea31 100644
--- a/fml/doc/en/tutorial/internals/credential.sgml
+++ b/fml/doc/en/tutorial/internals/credential.sgml
@@ -1,5 +1,5 @@
<!--
- $FML: credential.sgml,v 1.1 2003/07/29 12:13:54 fukachan Exp $
+ $FML: credential.sgml,v 1.2 2003/08/03 05:28:48 fukachan Exp $
$jaFML: credential.sgml,v 1.3 2003/04/15 14:51:40 fukachan Exp $
-->
@@ -14,7 +14,7 @@ User authentication is provided by methods of FML::Credential class.
-<sect1>
+<sect1 id="credential.implementation">
<title>
Discussion: FML::Credential implementation
</title>
diff --git a/fml/doc/en/tutorial/internals/dbms.sgml b/fml/doc/en/tutorial/internals/dbms.sgml
index c608bf9e..ae23be7e 100644
--- a/fml/doc/en/tutorial/internals/dbms.sgml
+++ b/fml/doc/en/tutorial/internals/dbms.sgml
@@ -1,5 +1,5 @@
<!--
- $FML: dbms.sgml,v 1.1 2003/07/29 12:13:54 fukachan Exp $
+ $FML: dbms.sgml,v 1.2 2003/08/03 05:28:49 fukachan Exp $
$jaFML: dbms.sgml,v 1.5 2003/05/31 08:51:09 fukachan Exp $
-->
@@ -9,6 +9,16 @@
</title>
+<para>
+This chapter describes how to handle persistent data.
+You should use DBMS (DataBase Management System) for that data.
+See
+<link linkend="db.module">
+<xref linkend="db.module">
+</link>
+on the internal use database.
+</para>
+
<sect1 id="dbms.overview">
<title>
Overview
@@ -32,20 +42,4 @@ preprocessing module calling IO::Adapter should handle it.
</sect1>
-<sect1 id="dbms.todo">
- <title>
- TODO
- </title>
-
-<para>
-Consider if methods are least set or not.
-<link linkend="module.io.adapter">
-IO::Adapter
-</link>
-is enough minimum ?
-</para>
-
-</sect1>
-
-
</chapter>
diff --git a/fml/doc/en/tutorial/internals/directory.sgml b/fml/doc/en/tutorial/internals/directory.sgml
new file mode 100644
index 00000000..bee4dfd7
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/directory.sgml
@@ -0,0 +1,49 @@
+<!--
+ $FML: directory.sgml,v 1.6 2005/06/25 15:11:34 fukachan Exp $
+-->
+
+
+<chapter id="directory">
+ <title>
+ Directory
+ </title>
+
+
+<sect1 id="directory.subdir.hier.level">
+ <title>
+ Q: how recursively sub directory can be created ?
+ </title>
+
+<para>
+The structore holding the html-ized article is as follows:
+<screen>
+200201/msg\d+.html
+</screen>
+</para>
+
+<para>
+one sub-directory by default.
+</para>
+
+<para>
+Consider directory listing.
+"ls" returns 1000 files soon, but 10000 files a little slowly.
+</para>
+
+<para>
+To accelerate listing, we should use sub-directory structure.
+For example, each sub-directory holds 1000 files.
+HTML 化されたファイルをおくサブディレクトリを 1000 ごとに用意すると、
+The structure such as "spool/sub/file" holds 10^6 ( million ) files
+and
+listing of it is fast.
+</para>
+
+<para>
+It must be enough to assume that 1 million articles for one ML.
+</para>
+
+</sect1>
+
+
+</chapter>
diff --git a/fml/doc/en/tutorial/internals/language.sgml b/fml/doc/en/tutorial/internals/language.sgml
new file mode 100644
index 00000000..dc4aa124
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/language.sgml
@@ -0,0 +1,224 @@
+<!--
+ $FML: language.sgml,v 1.3 2004/10/06 09:07:39 fukachan Exp $
+-->
+
+
+<chapter id="language.preference">
+ <title>
+ Language preference in processing
+ </title>
+
+
+<sect1 id="language.preference.overview">
+ <title>
+ Problems of language preference
+ </title>
+
+<para>
+The simplest model is that we suppose we should return the japanese
+message when the ML is configures as for Japanese.
+This model needs the language of a ML is fixed.
+This ML always returns the error message in Japanese.
+</para>
+
+<para>
+However, it is not proper to ignore Accept-Language: header field
+since some Japanese people cannot read Japanese on the screen.
+There may be invalid Accept-Language: field.
+There are several problems.
+</para>
+
+<para>
+For example, if "Accept-Language: ja" is given, we can recognize the
+language is "ja". However, how about the case Japanese send a mail
+with the body content "help" (English) ? In that case we cannot
+determine we should return the reply in us-ascii or iso-2022-jp.
+For example, how about the following example ?
+<screen>
+Example:
+
+From: rudo@example.co.jp
+Subject: help
+mime-version: 1.0
+content-type: text/plain; charset=us-ascii
+
+help
+</screen>
+</para>
+
+<para>
+We should return the English reply message based on charset
+information since this message contains English only, so charset is
+us-ascii. But this case we should return Japanese message since the
+sender is a Japanese. So we should return the help message in both
+English and Japanese if the ML is configures as Japanese
+preferrable. If English is preferrable, the reply is English only.
+</para>
+
+<para>
+If Accept-Lanaguage: is specified, we prefer it. Even if the ML is
+English preferrable (config: language_preference_order = en) and the
+message with "Accept-Lanaguage: ja" is given, the ML returns the
+Japanese help message.
+&fml8; behaves like it.
+</para>
+
+</sect1>
+
+
+<sect1 id="language.preference.ml.ja">
+ <title>
+ Japanese preferred ML
+ </title>
+
+<para>
+language_preference_order variable controls the behaviour.
+By default, an ML for Japanese is configures as
+<screen>
+language_preference_order = ja en
+</screen>
+&fml8; uses this hint.
+</para>
+
+
+<sect2>
+ <title>
+ Accept-Language: ja, en
+ </title>
+
+<para>
+&fml8; returns the message only in Japanese.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ Accept-Language: en
+ </title>
+
+<para>
+&fml8; returns the message only in English.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ no Accept-Language:, Content-Type: charset=iso-2022-jp
+ </title>
+
+<para>
+&fml8; returns the message only in Japanese.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ no Accept-Language:, Content-Type: charset=us-ascii
+ </title>
+
+<para>
+We cannot determine the language.
+We should return the message in both English and Japanese.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ no Accept-Language:, no Content-Type:
+ </title>
+
+<para>
+We cannot determine the language.
+We should return the message in both English and Japanese.
+</para>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="language.preference.ml.en">
+ <title>
+ English preferred ML
+ </title>
+
+<para>
+By default, a ML for English people is configured as
+<screen>
+language_preference_order = en
+</screen>
+&fml8; uses this hints.
+</para>
+
+
+<sect2>
+ <title>
+ Accept-Language: ja, en
+ </title>
+
+<para>
+&fml8; returns the message only in Japanese.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ Accept-Language: en
+ </title>
+
+<para>
+&fml8; returns the message only in English.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ no Accept-Language:, Content-Type: charset=iso-2022-jp
+ </title>
+
+<para>
+&fml8; returns the message only in Japanese.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ no Accept-Language:, Content-Type: charset=us-ascii
+ </title>
+
+<para>
+&fml8; returns the message only in English.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ no Accept-Language:, no Content-Type:
+ </title>
+
+<para>
+&fml8; returns the message only in English.
+</para>
+
+</sect2>
+
+</sect1>
+
+
+</chapter>
diff --git a/fml/doc/en/tutorial/internals/lock.sgml b/fml/doc/en/tutorial/internals/lock.sgml
new file mode 100644
index 00000000..54b05194
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/lock.sgml
@@ -0,0 +1,83 @@
+<!--
+ $FML: lock.sgml,v 1.5 2005/06/25 15:11:34 fukachan Exp $
+-->
+
+
+<chapter id="lock">
+ <title>
+ Lock
+ </title>
+
+<para>
+Synchronization among processes uses lock.
+&fml8; provides flock(2) or lockf(2) based lock mechanism.
+</para>
+
+
+<sect1 id="lock.overview">
+ <title>
+ Overview: lock
+ </title>
+
+<para>
+After 2003/03, &fml8; provides more granular not giant lock.
+</para>
+
+<para>
+Each resource defines each lock channel name.
+</para>
+
+<para>
+For example,
+Mail::Delivery related class accesses the member list.
+It needs several locks.
+</para>
+
+<para>
+Mail::Delivery::SMTP needs lock of member list.
+FML::Send and FML::Process::Delivery locks member list access
+in callling Mail::Delivery::SMTP.
+</para>
+
+<para>
+Instead
+Mail::Delivery::Queue just sees the mail queue.
+The function can access the queue concurrently, also.
+So this module does not need lock.
+</para>
+
+<para>
+Generally speaking, modules using maps require lock.
+For example,
+FML/Command/UserControl.pm and
+FML/Command/Auth.pm
+needs write lock, but
+FML/Credential.pm
+needs only read lock.
+</para>
+
+<para>
+It is useful if &fml8; provides reader writer lock. But it is not implemented.
+Currently we attension we use short critical region.
+</para>
+
+</sect1>
+
+
+<sect1 id="lock.todo">
+ <title>
+ TODO
+ </title>
+
+<para>
+mutex lock in calling *_maps.
+</para>
+
+<para>
+READER WRITER LOCK in calling IO::Adapter.
+</para>
+
+</sect1>
+
+
+</chapter>
diff --git a/fml/doc/en/tutorial/internals/main.cf.sgml b/fml/doc/en/tutorial/internals/main.cf.sgml
new file mode 100644
index 00000000..43eaf7ef
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/main.cf.sgml
@@ -0,0 +1,119 @@
+<!--
+ $FML: main.cf.sgml,v 1.10 2004/10/06 09:07:39 fukachan Exp $
+-->
+
+
+<sect2 id="main.cf">
+ <title>
+ Example: /usr/local/etc/fml/main.cf
+ </title>
+
+<para>
+/usr/local/etc/fml/main.cf is not specific.
+This is meta file to define fundamental variables
+e.g. fml version, directory path et.al.
+&fml8; loader reads them.
+</para>
+
+<para>
+The format of main.cf is same as other .cf files:
+<footnote>
+<para>
+file extension corresponds to the format.
+</para>
+</footnote>
+<screen>
+variable = value
+</screen>
+style.
+
+<screen>
+#
+# $FML: main.cf.sgml,v 1.10 2004/10/06 09:07:39 fukachan Exp $
+#
+
+# fml version
+# This is important
+# Example: fml 8.0
+# fml-current YYYYMMDD
+# fml-devel YYYYMMDD
+fml_version = current-20020701
+
+fml_owner = fml
+
+fml_group = fml
+
+
+###
+### DIRECTORIES
+###
+
+# Example: /usr/local
+prefix = /usr/local
+exec_prefix = ${prefix}
+
+# $config_dir holds the global main configuration and
+# several version-dependent default configurations
+# Example: /usr/local/etc/fml
+config_dir = /usr/local/etc/fml
+
+# Example: /usr/local/etc/fml/defaults/$fml_version
+default_config_dir = $config_dir/defaults/$fml_version
+
+# defined for convenience, for example, we need this variable
+# at include, include-ctl, which needs expansion of ../libexec/fml/fml.pl
+# Example: /usr/local/libexec/fml
+executable_prefix = ${exec_prefix}/libexec/fml
+
+# Example: /usr/local/libexec/fml/$fml_version
+libexec_dir = ${exec_prefix}/libexec/fml/$fml_version
+
+# Example: /usr/local/lib/fml/$fml_version
+lib_dir = ${exec_prefix}/lib/fml/$fml_version
+
+# Example: /usr/local/share/fml/$fml_version
+share_dir = ${prefix}/share/fml/$fml_version
+
+# site local library location
+# which is prepared but not used by fml itself
+local_lib_dir = ${exec_prefix}/lib/fml/site_local
+
+
+# ml's home directories
+# $ml_home_dir (e.g. /var/spool/ml/elena ) is taken from loader's @ARGV.
+# This is compatible with fml 4.0.
+# Example: /var/spool/ml
+default_ml_home_prefix = /var/spool/ml
+
+
+
+###
+### CONFIGURATION FILES AND DEFAULT PARAMETERS
+###
+
+
+# default domain
+default_domain = fml.org
+
+
+# version dependent default_config.cf location
+# whic holds
+# Example: /usr/local/etc/fml/defaults/8.0/default_config.cf
+default_config_cf = $default_config_dir/default_config.cf
+
+
+# domain specific configurations
+# Example: /usr/local/etc/fml/domains/fml.org/default_config.cf
+domain_default_config = $config_dir/domains/$default_domain/config.cf
+
+
+# virtual format: domain directory
+# for example,
+# fml.org /var/spool/ml/fml.org
+# nuinui.net /var/spool/ml/nuinui.net
+virtual_maps = $config_dir/virtual
+
+</screen>
+</para>
+
+</sect2>
diff --git a/fml/doc/en/tutorial/internals/merge.sgml b/fml/doc/en/tutorial/internals/merge.sgml
new file mode 100644
index 00000000..100172f5
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/merge.sgml
@@ -0,0 +1,122 @@
+<!--
+ $FML: merge.sgml,v 1.3 2005/06/25 15:11:34 fukachan Exp $
+-->
+
+
+<chapter id="merge.internal.to.fml8">
+ <title>
+ Convert another ML system to &fml8;
+ </title>
+
+
+<sect1 id="merge.internal.fml4to8">
+ <title>
+ Implementation: &fml4; to &fml8;
+ </title>
+
+<sect2>
+ <title>
+ Case 1: /var/spool/ml/elena/ from &fml4; to &fml8;
+ </title>
+
+<para>
+This conversion does the following steps in fact.
+</para>
+
+<para>
+1) install &fml8; firstly. In this case, add
+/var/spool/ml/etc/mail/aliases into $alias_maps of postfix main.cf.
+/var/spool/ml/etc/mail/aliases may be empty.
+</para>
+
+<para>
+2) run "makefml --force newml elena" to create several files &fml8;
+needs.
+</para>
+
+<para>
+3) convert address lists in /var/spool/ml/elena to &fml8; style.
+</para>
+
+<para>
+3-1)
+IO::Adapter ignores a line beginning with '^#' as a comment.
+We should handle carefully it since
+"actives" file contains ^# lines as "off" address.
+</para>
+
+<para>
+3-2)
+s=skip (off) options is ignored.
+It handles as "on".
+</para>
+
+<para>
+3-3)
+m=... (digest) options is ignored.
+
+Also, "# address" is "off" in the case of &fml4; but ignored in the
+case of &fml8;. We should warn it ?
+</para>
+
+<para>
+4) remove the corresponding entry of alias file
+(/var/spool/ml/etc/fml/aliases) of &fml4; and rebuild .db.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ Case 2: convert the whole /var/spool/ml/ from &fml4; to &fml8;
+ </title>
+
+<para>
+Apply case 1 for all ML's.
+</para>
+
+<para>
+If we can stop all ML's, it is easy to remove
+/var/spool/ml/etc/fml/aliases of &fml4; firstly and apply case 1 steps.
+stop MTA in migration.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ Discussion: use half and half of &fml4; and &fml8; softwares.
+ </title>
+
+<para>
+(X-Sequence: fml-devel 389)
+</para>
+
+<para>
+How in half and half case.
+</para>
+
+<para>
+For example, site_init.ph or config.ph of &fml4; follows
+<screen>
+[fml4]
+
+push(@ACTIVE_LIST,"$DIR/recipients") if( -f "$DIR/recipients" ) ;
+</screen>
+instead in the case of &fml8;
+site_default_config.cf or config.cf follows:
+<screen>
+[fml8]
+
+html_archive_dir = $ml_home_dir/htdocs
+</screen>
+</para>
+
+</sect2>
+
+</sect1>
+
+
+</chapter>
diff --git a/fml/doc/en/tutorial/internals/restriction.sgml b/fml/doc/en/tutorial/internals/restriction.sgml
new file mode 100644
index 00000000..60731434
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/restriction.sgml
@@ -0,0 +1,202 @@
+<!--
+ $FML: restriction.sgml,v 1.9 2005/06/25 15:11:35 fukachan Exp $
+-->
+
+
+<chapter id="restriction">
+ <title>
+ Restrict input data
+ </title>
+
+<para>
+&fml8; checks the input by regular expression FML::Restriction class
+provides.
+</para>
+
+
+<sect1 id="restriction.overview">
+ <title>
+ Overview: checks of input data
+ </title>
+
+<sect2>
+ <title>
+ Restriction for article posting
+ </title>
+
+<para>
+Restrictions for article are ambiguous or too restrictive. In fact
+FML::Restriction class does not provide restriction rules for article
+posting.
+</para>
+
+<para>
+Instead FML::Filter filter system checks each line of content.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ Restrictions for command mail
+ </title>
+
+<para>
+FML::Process::Command class parses each line of the command mail and
+checks the input by regular expressions FML::Restriction::Command
+provides. If the check is passed, &fml8; calls
+FML::Command::{User,Admin}::COMMAND at the next step.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ CGI
+ </title>
+
+<para>
+CGI programs can receive the input from HTTP via only safe_param_XXX()
+method.
+</para>
+
+<para>
+It is expected that
+safe_param_*()
+and
+try_cgi_*()
+returns the safe value.
+</para>
+
+<para>
+These safe_param_XXX() functions checks the input by regular
+expressions FML::Restriction::CGI provides (FML::Restriction::CGI
+inherits FML::Restriction::Base).
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ makefml / fml
+ </title>
+
+<para>
+CUI runs on the shell.
+It means he/she who runs CUI has priviledge to log in the mailing list
+server.
+So it does not check the input.
+</para>
+
+<para>
+Each module checks the input independetly in that case
+though no checks by FML::Restriction at the entrance.
+For example, "adduser" module checks whether the input address
+is valid or not even in the case of CUI.
+These restrictions are dependent command specific modules.
+</para>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="restriction.class">
+ <title>
+ FML::Restriction class
+ </title>
+
+<para>
+ACLs for the input data and commands are found at FML::Restriction
+class.
+</para>
+
+<para>
+For example, CGI modules use FML::Restriction::CGI class to check
+if the input data matches the proper regular expression.
+</para>
+
+<para>
+Though FML::Restriction inherits FML::Restriction::Base class,
+fundamentally each module should use FML::Restriction as object
+composition. For example, use in the following way:
+<screen>
+use FML::Restriction::CGI;
+$safe = new FML::Restriction::CGI;
+my $allowed_regexp = $safe->param_regexp();
+
+if ($value =~ /^$allowed_regexp{$key}$) { ... ok, do something ... ;}
+</screen>
+</para>
+
+</sect1>
+
+
+<sect1 id="restrictioncgi.input.data">
+ <title>
+ How CGI restricts the input
+ </title>
+
+<para>
+CGI checks the input data by using FML::Restriction::CGI class.
+</para>
+
+<para>
+The input should be restricted by FML::Restriction class.
+We should not use param() method provided by perl's CGI class.
+Instead use safe_param_xxx() method always to get value.
+</para>
+
+<para>
+The following use may be allowed
+<screen>
+for my $dirty_buf (param()) {
+ ... check ...
+}
+</screen>
+but we should not use raw param() call.
+<screen>
+param($dirtty_buf)
+</screen>
+Instead, use safe_param_key().
+<screen>
+for my $key (param()) {
+ ... check ...
+
+ if (key eq $key) {
+ value = safe_param_key()
+ }
+}
+</screen>
+</para>
+
+</sect1>
+
+
+<sect1>
+ <title>
+ Discussion: FML::Restriction is too restrictive ?
+ </title>
+
+<para>
+FML::Restriction class allows a subset of RFC defined expression.
+</para>
+
+<para>
+RRC definition is too large.
+It is too difficult to implement it ;-)
+We restrict the expression a little.
+</para>
+
+<para>
+FML::Restriction::Command may be more granular but more granular
+version is not implemented.
+</para>
+
+</sect1>
+
+
+</chapter>
diff --git a/fml/doc/en/tutorial/internals/struct.sgml b/fml/doc/en/tutorial/internals/struct.sgml
index ab4e7002..2d42b866 100644
--- a/fml/doc/en/tutorial/internals/struct.sgml
+++ b/fml/doc/en/tutorial/internals/struct.sgml
@@ -1,5 +1,5 @@
<!--
- $FML: struct.sgml,v 1.1 2003/07/28 10:41:30 fukachan Exp $
+ $FML: struct.sgml,v 1.2 2003/08/03 05:28:49 fukachan Exp $
$jaFML: struct.sgml,v 1.2 2003/04/15 14:51:41 fukachan Exp $
-->
@@ -9,7 +9,32 @@
</title>
-&struct.curproc;
+<sect1 id="structure.curproc">
+ <title>
+ curproc object
+ </title>
+
+<para>
+Example of FML::Process::Distribute object.
+</para>
+
+ &struct.curproc;
+
+</sect1>
+
+
+<sect1 id="structure.pcb">
+ <title>
+ PCB category list
+ </title>
+
+<para>
+PCB category list, which contains module and function relation.
+</para>
+
+&list.pcb;
+
+</sect1>
</appendix>
diff --git a/fml/doc/en/tutorial/internals/userctl.sgml b/fml/doc/en/tutorial/internals/userctl.sgml
new file mode 100644
index 00000000..29bb95d5
--- /dev/null
+++ b/fml/doc/en/tutorial/internals/userctl.sgml
@@ -0,0 +1,57 @@
+<!--
+ $FML: userctl.sgml,v 1.3 2004/10/06 09:07:40 fukachan Exp $
+-->
+
+
+<chapter id="userctl">
+ <title>
+ subscribe / unsubscribe
+ </title>
+
+
+<sect1 id="userctl.deladd">
+ <title>
+ which map subscribe/unsubscribe is operated to ?
+ </title>
+
+<para>
+Subscribe/unsubscribe is operated to $primary_*map.
+</para>
+
+<para>
+For example,
+subscription of remote administrators is operated into
+both $primary_admin_member_map and $primary_admin_recipient_map.
+unsubscription of remote administrators is operated into
+both $primary_admin_member_map and $primary_admin_recipient_map.
+</para>
+
+<para>
+Why use primary_*_map ?
+If we use admin_member_maps and admin_recipient_maps, it causes a problem.
+</para>
+
+<para>
+Subscription should be operated into one map. So we should operate it
+into primary_*_map.
+</para>
+
+<para>
+Unsubscription must be same since xxx_maps is composed of different
+privileged maps.
+</para>
+
+<para>
+For example, $member_maps is as follows.
+It contais a list of member and a list of remote administrators.
+<screen>
+member_maps = $primary_member_map
+ $admin_member_maps
+</screen>
+So unsubscription operated for $member_maps may cause
+unsubscription of remote administrators. It is wrong logic.
+</para>
+
+</sect1>
+
+</chapter>