summaryrefslogtreecommitdiff
path: root/fml/doc/en/tutorial/module
diff options
context:
space:
mode:
authorfukachan <fukachan>2003-07-28 10:41:29 +0000
committerfukachan <fukachan>2003-07-28 10:41:29 +0000
commit8768dbb6785b070e61a076c75fd45c03299352ad (patch)
treebcaa2fdbe1bd6429af707ab39c272001f95baf41 /fml/doc/en/tutorial/module
parentafcf3d6497a5fb98329451f25bb497434532487a (diff)
downloadfml8-8768dbb6785b070e61a076c75fd45c03299352ad.tar.gz
fml8-8768dbb6785b070e61a076c75fd45c03299352ad.tar.bz2
fml8-8768dbb6785b070e61a076c75fd45c03299352ad.zip
translated
Diffstat (limited to 'fml/doc/en/tutorial/module')
-rw-r--r--fml/doc/en/tutorial/module/IO.sgml389
-rw-r--r--fml/doc/en/tutorial/module/Message.sgml310
-rw-r--r--fml/doc/en/tutorial/module/encode.sgml131
3 files changed, 830 insertions, 0 deletions
diff --git a/fml/doc/en/tutorial/module/IO.sgml b/fml/doc/en/tutorial/module/IO.sgml
new file mode 100644
index 00000000..f96e3097
--- /dev/null
+++ b/fml/doc/en/tutorial/module/IO.sgml
@@ -0,0 +1,389 @@
+<!--
+ $FML$
+ $jaFML: IO.sgml,v 1.4 2003/04/15 14:51:42 fukachan Exp $
+-->
+
+<chapter id="module.io.adapter">
+ <title>
+ IO abstraction layer (IO::Adapter class)
+ </title>
+
+
+<sect1 id="module.io.adapter.overview">
+ <title>
+ IO::Adapter overview
+ </title>
+
+<para>
+All IO of &fmldevel; should use IO::Adapter class like vfs/vnode
+interface. For example, read/write member list, add/remove a user.
+The usage is like this:
+<screen>
+use IO::Adapter;
+$obj = new IO::Adapter $map, $map_params;
+$obj->open || croak("cannot open $map");
+while ($x = $obj->get_next_key()) { ... }
+$obj->close;
+</screen>
+</para>
+
+<para>
+$map is map:identifier. file: can be omitted.
+Currently available maps follows:
+<screen>
+file:/var/spool/ml/elena/recipients
+unix.group:root
+nis.group:root
+mysql:id
+postgresql:id (not yet implemented)
+ldap:id (not yet implemented)
+</screen>
+</para>
+
+<para>
+"file:" map is a normal file (text file).
+"unix.group:root" map is to read root entry in /etc/group file.
+"nis.group:root" map is to read root entry in NIS (YP).
+"mysql:id" map implies the use of MySQL.
+Parameters for MySQL access is defined in "mysql:id" entry.
+These paraemeters should be specified before calling "new
+IO::Adapter".
+</para>
+
+</sect1>
+
+
+<sect1 id="module.io.adapter.methods">
+ <title>
+ IO::Adapter methods
+ </title>
+
+<para>
+Official method IO::Adapter privides currently follows:
+<screen>
+new()
+open()
+close()
+
+get_next_key()
+
+add(KEY)
+delete(KEY)
+
+getpos()
+setpos(NUM)
+eof()
+
+touch()
+
+find(REGEXP, $args)
+</screen>
+</para>
+
+<para>
+KEY is a primary key for database access. In almost cases, the primary
+key is a mail address. REGEXP is a regular expression (regexp), this
+is usually also a mail address.
+</para>
+
+<para>
+Unification of all types of IO needs that we should implement leastest
+methods.
+</para>
+
+<para>
+The currently implemented methods are selected by test and our
+operations. If could, we select SQL IO more than file IO for
+abstraction model. It introduces difference between &fml4; and &fml8;
+but it is mandatory for further abstraction.
+</para>
+
+</sect1>
+
+
+<sect1>
+ <title>
+ argument type of methods
+ </title>
+
+<para>
+get_next_key() is typical. It needs no argument or STR as the
+argument and the return value is STR. since this method is used to
+list up the content of files or retrieve the specific address in the
+file.
+</para>
+
+<para>
+In other case, the argument may be a pair of strings.
+<screen>
+KEY_STR => [
+ VALUE_STR_1
+ VALUE_STR_2
+ VALUE_STR_3
+]
+</screen>
+This is used as the return value to represent ARRAY. For example,
+"actives" file of &fml4; consists of lines which have plural space
+separeted entries. So it is a type of array.
+<screen>
+rudo@nuinui.net s=skip m=xxx.yyy.z # commnet
+
+rudo@nuinui.net => [
+ s=skip
+ m=xxx.yyy.z
+ # comment
+]
+</screen>
+</para>
+
+<para>
+It is summarized as follows.
+The argument is one of "nothing" or "STR".
+The return value is either of STR of ARRAY_REF (array reference).
+<screen>
+argument return value
+---------------------------------------
+none => STR
+
+STR => STR
+
+none => [STR, STR, ... ]
+
+STR => [STR, STR, ... ]
+</screen>
+</para>
+
+</sect1>
+
+
+<sect1 id="module.io.adapter.map.file">
+ <title>
+ file map
+ </title>
+
+<para>
+"file:/some/where/file/name" or file name "/some/where/file/name" map
+is abstraction of IO to/from a text file.
+</para>
+
+</sect1>
+
+
+<sect1 id="module.io.adapter.map.unixgroup">
+ <title>
+ unixgroup map
+ </title>
+
+<para>
+Abstraction of /etc/group. IO is read only.
+</para>
+
+<para>
+For example, the access to
+<screen>
+wheel:*:0:root,rudo,kenken
+</screen>
+in /etc/group is "unixgroup:wheel" map in IO::Adapter.
+<screen>
+$obj = new IO::Adapter "unixgroup:wheel";
+</screen>
+If you call get_next_key() method for this object,
+you will get the member of wheel group sequentially.
+In other words the wheel group is regarded as the follogin file
+by IO::Adapter.
+<screen>
+root
+rudo
+kenken
+</screen>
+</para>
+
+</sect1>
+
+
+<sect1 id="module.io.adapter.map.nis">
+ <title>
+ NIS map
+ </title>
+
+<para>
+It is same as one of /etc/group but the data is retrieved from NIS/YP.
+</para>
+
+</sect1>
+
+
+<sect1 id="module.io.adapter.map.mysql">
+ <title>
+ MySQL map
+ </title>
+
+<para>
+For more eacy maintenance, we should write all mysql configurations in
+one file. For example, it is better that we have only to write SQL
+configuratinos in config.cf.
+</para>
+
+<para>
+But we identify plural mysql consitions. So, we use the tag
+[mysql:members] to declare the region between the tag to the next tag
+or =cut. It is similar to .ini file (M$). We use the tags like this:
+<screen>
+config.cf example
+
+member_maps = mysql:members
+
+recipient_maps = mysql:recipients
+
+[mysql:members]
+
+sql_server = localhost
+sql_user = fml
+sql_password = uja
+sql_database = fml
+sql_table = ml
+
+sql_find = select * from ...
+
+ ...
+</screen>
+</para>
+
+<para>
+In calling IO::Adapter, use
+<screen>
+new IO::Adapter "mysql:members", $config;
+</screen>
+where $config is a hash reference holding some paremeters like this:
+<screen>
+$config => {
+ [mysql:members] => {
+ sql_sever => localhost
+ ...
+ }
+}
+</screen>
+FML::Config prepares this $config by readinc .cf files. Hence, we
+usually use FML::Config object as an argument of IO::Adapter::new()
+method.
+</para>
+
+
+<sect2>
+ <title>
+ Discussion:
+ How to write sql statements in config.cf ?
+ (fml-devel 204)
+ </title>
+
+<para>
+How about lexical scope ? The .cf files cannot define all variables
+since lexical scope variables exist.
+We use &amp;varname syntax for such lexical scope variables.
+</para>
+
+<para>
+For example, use different member and recipient maps. In sql
+statements, the difference is a flag (fml_recipient) in a table. So
+in calling MySQL , the where statement has different value but it is
+determined lexically.
+<screen>
+member_maps = mysql:members
+
+recipient_maps = mysql:recipients
+
+
+[mysql:members]
+
+sql_server = localhost
+sql_user = fml
+sql_password = uja
+sql_database = fml
+sql_table = ml
+
+sql_get_next_key = select fml_address from $sql_table
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+
+sql_getline = select * from $sql_table
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+
+sql_add = insert into $sql_table
+ values ('$ml_name', '$ml_domain', '&amp;address', 1, 1)
+
+sql_delete = delete from $sql_table
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+ and
+ fml_address = '&amp;address'
+
+sql_find = select * from $sql_table
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+ and
+ fml_address like '&amp;regexp'
+
+
+
+[mysql:recipients]
+
+sql_server = localhost
+sql_user = fml
+sql_password = uja
+sql_database = fml
+sql_table = ml
+
+sql_get_next_key = select fml_address from $sql_table
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+ and
+ fml_recipient = '1'
+
+sql_getline = select * from $sql_table
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+ and
+ fml_recipient = '1'
+
+sql_add = update ml
+ set recipient = 1
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+ and
+ fml_address = '&amp;address'
+
+sql_delete = update ml
+ set recipient = 0
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+ and
+ fml_address = '&amp;address'
+
+
+sql_find = select * from $sql_table
+ where fml_ml = '$ml_name'
+ and
+ fml_domain = '$ml_domain'
+ and
+ fml_recipient = '1'
+ and
+ fml_address like '&amp;regexp'
+</screen>
+</para>
+
+</sect2>
+
+
+</sect1>
+
+
+</chapter>
diff --git a/fml/doc/en/tutorial/module/Message.sgml b/fml/doc/en/tutorial/module/Message.sgml
new file mode 100644
index 00000000..a0c017e1
--- /dev/null
+++ b/fml/doc/en/tutorial/module/Message.sgml
@@ -0,0 +1,310 @@
+<!--
+ $FML$
+ $jaFML: Message.sgml,v 1.2 2003/04/15 14:51:42 fukachan Exp $
+-->
+
+<chapter id="module.mail.message">
+ <title>
+ Mail::Message module
+ </title>
+
+<sect1 id="module.mail.message.overview">
+ <title>
+ Mail::Message overview
+ </title>
+
+<para>
+Mail::Message object provides several methods to analyze a message and
+manipulate messages or parts of a message.
+</para>
+
+<para>
+Precisely speaking, this module analyzes the specified mail message
+and build a chain of Mail::Message objects.
+<screen>
+If not multipart
+
+ header -> body
+
+else if multipart
+
+ header -> preamble -> part1 -> part2 -> trailor
+</screen>
+The link between objects is double link list. Mail::Message class
+provides several methods to manipulate these structures.
+</para>
+
+<para>
+Each part of this chain is a Mail::Message object. In other words, one
+mail message consits of a chain of plural Mail::Message objects.
+</para>
+
+<para>
+For example, "header" is a Mail::Message, which type is
+text/rfc822-headers and the data is Mail::Header object. Instead
+"part1" is a Mail::Message object, which type is text/plain and the
+data is reference to the data string.
+</para>
+
+<para>
+References:
+<ulink url="../../en/modules/Mail/Message.txt">
+Mail::Message module manual.
+</ulink>
+</para>
+
+</sect1>
+
+
+<sect1 id="module.mail.message.parse">
+ <title>
+ Mail::Message module: analyze
+ </title>
+
+<para>
+parse() analyzes the file which file name or the file handle for the
+file should be specified at the argument.
+</para>
+
+<para>
+data_type_list() returns information of the chain.
+The return value is array reference.
+For example, MIME/multipart consists of the following objects.
+<screen>
+ type[ 1]: text/rfc822-headers | multipart/mixed
+ type[ 2]: multipart/mixed | multipart/mixed
+ type[ 3]: multipart.preamble | multipart/mixed
+ type[ 4]: multipart.delimiter | multipart/mixed
+ type[ 5]: text/plain | multipart/mixed
+ type[ 6]: multipart.delimiter | multipart/mixed
+ type[ 7]: image/gif | multipart/mixed
+ type[ 8]: multipart.close-delimiter | multipart/mixed
+ type[ 9]: text/plain | multipart/mixed
+</screen>
+The center is the object type, the right one is the mime type of the
+whole message (content-type in the mail header).
+</para>
+
+</sect1>
+
+
+<sect1 id="module.mail.message.create">
+ <title>
+ Mail::Message module: create a new object
+ </title>
+
+<para>
+new() method is used to create a new object chain.
+</para>
+
+<para>
+The following MIME/multipart specific methdos exist.
+<screen>
+build_mime_multipart_chain($args)
+parse_and_build_mime_multipart_chain($args)
+build_mime_header($args)
+</screen>
+These method is used internally now.
+So these will become private methods in the furure.
+Please do not use these methods.
+</para>
+
+<para>
+To create a new MIME/mulitpart message, use Mail::Message::Compose. It
+is MIME::Lite class in fact :-)
+</para>
+
+</sect1>
+
+
+<sect1 id="module.mail.message.headerop">
+ <title>
+ Mail::Message module: header manipulations
+ </title>
+
+<para>
+dup_header() method duplicates only header part of a chain and left
+the body part. The new chain has different head (header object) but
+the second part is the same as the original chain.
+<screen>
+ |<--------------- mail body ------------->
+header0 ----> part1 -> part2 -> ...
+ A
+ |
+dup_header0 ---
+</screen>
+</para>
+
+
+<para>
+whole_message_header() returns the header object the chain. The return
+value is a Mail::Message object not string.
+</para>
+
+<para>
+header_data_type() return the type of the whole message as string.
+It tells whether this message is text or multipart.
+</para>
+
+</sect1>
+
+
+<sect1 id="module.mail.message.bodyop">
+ <title>
+ Mail::Message module: manipulate messabe body
+ </title>
+
+<para>
+Consider the following object chain.
+<screen>
+If multipart
+
+header -> body
+
+else if not multipart
+
+header -> preamble -> part1 -> part2 -> trailor
+</screen>
+</para>
+
+
+<para>
+header_data_type() return the type of the whole type.
+It is the information from Content-Type: in the whole message header.
+</para>
+
+<para>
+whole_message_body() returns body or part1 if multipart.
+whole_message_body_head() is same.
+</para>
+
+<para>
+find_first_plaintext_message($args) return the first text/plain type
+object in the chain. This is useful in filter codes since filter
+system checks the first text field in a lot of cases.
+</para>
+
+</sect1>
+
+
+<sect1 id="module.mail.message.search">
+ <title>
+ Mail::Message module: search
+ </title>
+
+<para>
+find() searches the specified type of Mail::Message in the object
+chain and returns the first matched object.
+</para>
+
+</sect1>
+
+
+<sect1 id="module.mail.message.print">
+ <title>
+ Mail::Message module: print
+ </title>
+
+<para>
+print() method is useual print() functions.
+Usually specify the file descriptor as the argument.
+</para>
+
+<para>
+print() has the concept "mode" to specify CRLF or LF. use
+set_print_mode(mode) and reset_print_mode() to set the mode. By
+default, mode is raw. Specify smtp mode in SMTP codes.
+</para>
+
+</sect1>
+
+
+<sect1 id="module.mail.message.utils">
+ <title>
+ Mail::Message module: utility functions
+ </title>
+
+<sect2>
+ <title>
+ size
+ </title>
+
+<para>
+size() returns the size of the object not the whole size.
+header_size() tells the size of the header.
+body_size() tells the size of the body part.
+</para>
+
+<para>
+is_empty() tells the object data is empty or not.
+</para>
+</sect2>
+
+
+<sect2>
+ <title>
+ general information
+ </title>
+
+<para>
+envelope_sender() returns the envelope sender as string.
+</para>
+
+<para>
+data_type() returns the type of the object (a part of an object chain)
+not the whole message type (Content-Type: in the whole message
+header).
+</para>
+
+<para>
+encoding_mechanism() returns the encoding mechanism of the object (a
+part of an object chain) as string. This is not of the whole message
+encoding mechanism.
+</para>
+
+</sect2>
+
+
+<sect2>
+ <title>
+ Mail::Message internals
+ </title>
+
+<para>
+num_paragraph() returns the number of paragraph in the data of the
+object.
+</para>
+
+
+<para>
+nth_paragraph(N) returns N-th paragrah as the string.
+Caution that N starts from 1 not 0.
+</para>
+
+
+<para>
+header() return the header part of a multipart block.
+data() returns the data part.
+Respectively, alias of message_fields($size) and message_text($size).
+</para>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="module.mail.message.ref">
+ <title>
+ Rerefences
+ </title>
+
+<para>
+
+<ulink url="../../en/modules/Mail/Message.txt">
+Mail::Message manual
+</ulink>
+</para>
+</sect1>
+
+
+</chapter>
diff --git a/fml/doc/en/tutorial/module/encode.sgml b/fml/doc/en/tutorial/module/encode.sgml
new file mode 100644
index 00000000..a609c8fe
--- /dev/null
+++ b/fml/doc/en/tutorial/module/encode.sgml
@@ -0,0 +1,131 @@
+<!--
+ $FML$
+ $jaFML: encode.sgml,v 1.2 2003/04/15 14:51:42 fukachan Exp $
+-->
+
+<chapter id="module.mail.message.encode">
+ <title>
+ Mail::Message::Encode class
+ </title>
+
+<para>
+[reference] fml-help ML's Count: 02012, 02013, 02016.
+</para>
+
+<screen>
+[Usage]
+
+ use Mail::Message::Encode;
+ my $encode = new Mail::Message::Encode;
+ my $str_euc = $encode->convert( $s, 'euc-jp' );
+ my $str_euc = $encode->convert( $s, 'euc-jp', 'iso-2022-jp' );
+
+ my $encode = new Mail::Message::Encode;
+ my $status = $encode->convert_str_ref( \$s, 'euc-jp' );
+ my $status = $encode->convert_str_ref( \$s, 'euc-jp', 'jis' );
+
+ my $fp = sub { ... };
+ $encode->run_in_chcode( $fp, $oout, $in );
+
+ * 4.0 compatible functions are available.
+ ues Mail::Message::Encode qw(STR2EUC);
+ my $euc_s = STR2EUC( $s );
+</screen>
+
+
+<sect1>
+ <title>
+ Mail::Message::Encode specification
+ </title>
+
+<para>
+The main code is within _convert_str_ref() method.
+
+<screen>
+ sub convert # if the argument is STR.
+ {
+ my ($self, $str, $out_code, $in_code) = @_;
+ _convert_str_ref(\$str, $out, $in);
+
+ return $str;
+ }
+
+
+ sub convert_str_ref # if the argument is STR_REF.
+ {
+ my ($self, $str, $out, $in) = @_;
+ _convert_str_ref($str, $out, $in);
+ }
+
+
+ sub _convert_str_ref # if the argument is STR_REF.
+ {
+ my ($str, $out, $in) = @_;
+
+ # 1. speculate charset
+ if $in unspecified -> speculat -> fail -> return 0
+
+ # 2. try conversion
+ if ($in resolved or or $in specified in @_) {
+ converted to $out charset
+ (use jcode, Jcode, use Encode if perl version > 5.8).
+ conversion
+ return 1 ; # success
+ }
+ else { # principle of least surprise ?
+ nothing todo ;
+ return $str;
+ }
+
+ return 0 ; # failed
+ }
+</screen>
+
+<screen>
+sub base64 {}
+sub quoted_printable {}
+</screen>
+is useful for convenience.
+<screen>
+$x = $encode->base64($s);
+</screen>
+For backward compatibility, STR2XXX() functoins are prepared.
+<screen>
+ STR2EUC( $str, [$icode] )
+ STR2JIS( $str, [$icode] )
+ STR2SJIS( $str, [$icode] )
+</screen>
+These wraps convert_str_ref().
+</para>
+
+</sect1>
+
+
+<sect1>
+ <title>
+ run_in_chcode()
+ </title>
+
+<para>
+In language dependent processes, convert the charset to machine
+friendly one, process something and back it to the original chaset
+each time. This step is widely used. So it is convenient to prepare a
+function to unify these steps in one function.
+<screen>
+run_in_chcode example:
+
+sub run_in_chcode
+{
+ my ($self, $proc, $s, $out_code, $in_code) = @_;
+
+ my $conv_status = convert_str_ref($s, $EUC_JP, $in_code);
+ my $proc_status = &$proc($s, @_);
+ convert_str_ref($s, $out_code, $EUC_JP) if $conv_status && $out_code;
+ return wantarray ? ($conv_status, $proc_status): $conv_status;
+}
+</screen>
+</para>
+
+</sect1>
+
+</chapter>