diff options
| author | fukachan <fukachan> | 2003-07-28 10:41:29 +0000 |
|---|---|---|
| committer | fukachan <fukachan> | 2003-07-28 10:41:29 +0000 |
| commit | 8768dbb6785b070e61a076c75fd45c03299352ad (patch) | |
| tree | bcaa2fdbe1bd6429af707ab39c272001f95baf41 /fml/doc/en/tutorial/module | |
| parent | afcf3d6497a5fb98329451f25bb497434532487a (diff) | |
| download | fml8-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.sgml | 389 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/module/Message.sgml | 310 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/module/encode.sgml | 131 |
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 &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', '&address', 1, 1) + +sql_delete = delete from $sql_table + where fml_ml = '$ml_name' + and + fml_domain = '$ml_domain' + and + fml_address = '&address' + +sql_find = select * from $sql_table + where fml_ml = '$ml_name' + and + fml_domain = '$ml_domain' + and + fml_address like '&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 = '&address' + +sql_delete = update ml + set recipient = 0 + where fml_ml = '$ml_name' + and + fml_domain = '$ml_domain' + and + fml_address = '&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 '&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> |
