    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.fukurou.util;
    017
    018import org.opengion.fukurou.security.HybsCryptography;
    019
    020/**
    021 * XHTMLTag.java は、共通的に使用されるHTMLタグの生成メソッドを集約したクラスです。
    022 *
    023 * 全変数／メソッドは、public static final 宣言されています。
    024 *
    025 * @version  4.0
    026 * @author   Kazuhiko Hasegawa
    027 * @since    JDK5.0,
    028 */
    029public final class XHTMLTag {
    030
    031        /** システム依存の改行記号をセットします。 */
    032        public static final String CR = System.getProperty("line.separator");
    033
    034        /** バッファの初期容量を通常より若干多い目に設定します。(50)  */
    035        public static final int BUFFER_SMALL = 50;
    036
    037        /** バッファの初期容量を通常より多い目に設定します。(200)  */
    038        public static final int BUFFER_MIDDLE = 200;
    039
    040        /** バッファの初期容量を通常より大幅に多い目に設定します。(500)  */
    041        public static final int BUFFER_LARGE  = 500;
    042
    043        /** URLチェックキー発行用 4.3.7.1 (2009/06/08) */
    044        private static final HybsCryptography HYBS_CRYPTOGRAPHY = new HybsCryptography(); // 4.3.7.0 (2009/06/01)
    045
    046        /**
    047         * BUTTON タグの属性リストです。
    048         *
    049         * @og.rev 5.7.1.0 (2013/12/06) HTML5関連の属性を追加
    050         */
    051        private static final String[]
    052                BUTTON_KEY =  { "type","name","value","onClick"
    053                                                ,"id","class","lang","dir","title","style","xml:lang"
    054                                                ,"disabled","tabindex","accesskey"
    055                                                ,"onBlur","onFocus","ondblClick","onMouseDown","onMouseUp"
    056                                                ,"onMouseMove","onMouseOut","onMouseOver"
    057                                                // 5.7.1.0 (2013/12/06) HTML5関連の属性
    058                                                ,"autofocus"
    059                                        };
    060
    061        /**
    062         * INPUT タグの属性リストです。
    063         *
    064         * @og.rev 5.7.1.0 (2013/12/06) HTML5関連の属性を追加
    065         */
    066        private static final String[]
    067                INPUT_KEY = { "type","size","maxlength","checked","src"
    068                                                ,"alt","accept","usemap","ismap"
    069                                                ,"id","class","lang","dir","title","style","xml:lang"
    070                                                ,"readonly","disabled","tabindex","accesskey","onClick","onChange"
    071                                                ,"onBlur","onFocus","ondblClick","onMouseDown","onMouseUp"
    072                                                ,"onMouseMove","onMouseOut","onMouseOver"
    073                                                ,"onSelect","onKeydown","onKeypress","onKeyup"
    074                                                // 5.7.1.0 (2013/12/06) HTML5関連の属性
    075                                                ,"autocomplete","autofocus","pattern","placeholder","list","min","max","step","required"
    076                                        };
    077
    078        /**
    079         * TEXTAREA タグの属性リストです。
    080         *
    081         * @og.rev 5.7.1.0 (2013/12/06) HTML5関連の属性を追加
    082         */
    083        private static final String[]
    084                TEXTAREA_KEY = { "name","rows","cols"
    085                                                ,"id","class","lang","dir","title","style","xml:lang"
    086                                                ,"readonly","disabled","tabindex","accesskey","onClick"
    087                                                ,"onBlur","onFocus","ondblClick","onMouseDown","onMouseUp"
    088                                                ,"onMouseMove","onMouseOut","onMouseOver"
    089                                                ,"onSelect","onKeydown","onKeypress","onKeyup"
    090                                                // 5.7.1.0 (2013/12/06) HTML5関連の属性
    091                                                ,"autofocus","placeholder"
    092                                        };
    093
    094        /**
    095         * LINK タグの属性リストです。
    096         *
    097         */
    098        private static final String[]
    099                LINK_KEY = { "type","name","hreflang","rel","rev","charset"
    100                                                ,"target","shape","coords","onClick"
    101                                                ,"id","class","lang","dir","title","style","xml:lang"
    102                                                ,"tabindex","accesskey"
    103                                                ,"onBlur","onFocus","ondblClick","onMouseDown","onMouseUp"
    104                                                ,"onMouseMove","onMouseOut","onMouseOver"
    105                                        };
    106
    107        /**
    108         * SELECT タグの属性リストです。
    109         *
    110         * @og.rev 5.7.1.0 (2013/12/06) HTML5関連の属性を追加
    111         */
    112        private static final String[]
    113                SELECT_KEY = { "size","multiple",
    114                                                "id","class","lang","dir","title","style","xml:lang"
    115                                                ,"disabled","tabindex","onClick","onChange"
    116                                                ,"onBlur","onFocus","ondblClick","onMouseDown","onMouseUp"
    117                                                ,"onMouseMove","onMouseOut","onMouseOver"
    118                                                ,"onSelect","onKeydown","onKeypress","onKeyup"
    119                                                // 5.7.1.0 (2013/12/06) HTML5関連の属性
    120                                                ,"autofocus"
    121                                        };
    122
    123        /**
    124         * OPTION タグの属性リストです。
    125         *
    126         */
    127        private static final String[]
    128                OPTION_KEY = { "value","label","selected"
    129                                                ,"id","class","lang","dir","title","style","xml:lang"
    130                                                ,"disabled"
    131                                        };
    132
    133        /**
    134         * FRAME タグの属性リストです。
    135         *
    136         */
    137        private static final String[]
    138                FRAME_KEY = { "name","longdesc","marginwidth","marginheight","noresize"
    139                                                ,"scrolling","frameborder"
    140                                                ,"id","class","title","style"
    141                                        };
    142
    143        /**
    144         * IFRAME タグの属性リストです。
    145         *
    146         * @og.rev 5.9.1.2 (2015/10/23) 新規追加
    147         */
    148        private static final String[]
    149                IFRAME_KEY = { "name","srcdoc","seamless","sandbox","width","height"
    150                                                ,"marginwidth","marginheight","noresize","scrolling","frameborder"
    151                                                ,"id","class","title","style"
    152                                        };
    153
    154
    155        /**
    156         * IMAGE タグの属性リストです。
    157         *
    158         */
    159        private static final String[]
    160                IMAGE_KEY = { "src","alt","longdesc","width","height","usemap","ismap","name","onClick"
    161                                                ,"align","border","hspace","vspace"              // この行は非推奨属性です。
    162                                                ,"id","class","title","style","lang","dir","xml:lang"
    163                                                ,"onBlur","onFocus","ondblClick","onMouseDown","onMouseUp"
    164                                                ,"onMouseMove","onMouseOut","onMouseOver"
    165                                        };
    166
    167        /**
    168         * FORM タグの属性リストです。
    169         *
    170         */
    171        private static final String[]
    172                FORM_KEY = { "action","method","enctype","accept-charset","accept","name","target"
    173                                                ,"id","class","title","style","lang","dir","xml:lang"
    174                                        };
    175
    176        /**
    177         * SPAN タグの属性リストです。
    178         *
    179         */
    180        private static final String[]
    181                SPAN_KEY = { "id","class","title","style","lang","dir","xml:lang" };
    182
    183        /**
    184         * PRE タグの属性リストです。
    185         *
    186         */
    187        private static final String[]
    188                PRE_KEY = { "id","class","title","style","lang","dir","xml:lang" };
    189
    190        /**
    191         *  デフォルトコンストラクターをprivateにして、
    192         *  オブジェクトの生成をさせないようにする。
    193         *
    194         */
    195        private XHTMLTag() { }
    196
    197        /**
    198         * ボタンを作成します。
    199         *
    200         * &lt;button type="形式" name="名前" value="送信文字" オプション･･･ &gt;ラベル&lt;/button&gt;
    201         *
    202         * <table border="1" frame="box" rules="all" >
    203         *   <caption>Attributes に設定できる属性</caption>
    204         *   <tr><td>name="名前"</td><td>オプション</td><td>LabelResource.properties のキー</td></tr>
    205         *   <tr><td>type="形式"</td><td>必須</td><td>submit/reset/button</td></tr>
    206         *   <tr><td>value="値"</td><td>オプション</td><td>name属性と共に送信される値</td></tr>
    207         *   <tr><td>disabled="disabled"</td><td>オプション</td><td>ボタンを利用できない状態にする場合に指定</td></tr>
    208         *   <tr><td>tabindex="Tab移動順"</td><td>オプション</td><td>0～32767の範囲で数字で指定(小さい順に移動)</td></tr>
    209         *   <tr><td>accesskey="ショートカットキー"</td><td>オプション</td><td>文字セット中の１文字：WindowsであればAltキーと同時使用</td></tr>
    210         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    211         *   <tr><td>body="表示するタグ文字列"</td><td>オリジナル</td><td>画像や文字などボタン上に表示させたいタグの文字列</td></tr>
    212         * </table>
    213         *
    214         * 設定できる属性
    215         * 形式は，
    216         *  submit  送信(サブミット)
    217         *  reset   リセット
    218         *  button  汎用ボタン
    219         * を指定します。
    220         *
    221         * ラベルに，HTMLテキスト(強調文字など)をはめ込むことが出来ます。
    222         * また，イメージ &lt;img ････&gt; を指定することも,可能です。
    223         * disabled="disabled" のとき，このボタンのデータはサーバーに送信されません。
    224         * 属性群は,タグの中に,CSS等で使用できる class="XXX" などの
    225         * 汎用属性を自由に登録する事が出来ます。
    226         *
    227         * @param   attri 属性群
    228         *
    229         * @return  ボタンタグ文字列
    230         */
    231        public static String button( final Attributes attri ) {
    232                String   checkedType = "|submit|reset|button|";
    233
    234                String type  = attri.get( "type" );
    235                if( checkedType.indexOf( "|" + type + "|" ) < 0 ) {
    236                        String errMsg = "button タイプ設定エラー [" + type + "]";
    237                        throw new RuntimeException( errMsg );
    238                }
    239
    240                String values = attri.getAttribute( BUTTON_KEY );
    241                String body   = attri.get( "body" );
    242                if( body == null ) { body = "" ; }
    243
    244                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    245                rtn.append("<button ");
    246                rtn.append( values );
    247                rtn.append( ">" );
    248                rtn.append( body );
    249                rtn.append("</button>");
    250
    251                return rtn.toString();
    252        }
    253
    254        /**
    255         * 入力フォームを作成します。
    256         *
    257         * @param   attri 属性群
    258         *
    259         * @return  入力フォームタグ文字列
    260         * @see     #input( Attributes attri,String name,String value,String optAtt )
    261         */
    262        public static String input( final Attributes attri ) {
    263                String name     = attri.get( "name" );
    264                String value    = attri.get( "value" );
    265                String optAttri = attri.get( "optionAttributes" );
    266
    267                return input( attri,name,value,optAttri );
    268        }
    269
    270        /**
    271         * 入力フォームを作成します。
    272         *
    273         * &lt;input type="text" name="名前" value="送信文字" ....&gt;
    274         *
    275         * <table border="1" frame="box" rules="all" >
    276         *   <caption>Attributes に設定できる属性</caption>
    277         *   <tr><td>name="名前"</td><td>オプション</td><td>LabelResource.properties のキー</td></tr>
    278         *   <tr><td>type="形式"</td><td>必須</td><td>text/password/checkbox/radio/submit/reset/button/image/file/hidden</td></tr>
    279         *   <tr><td>value="値"</td><td>オプション</td><td>name属性と共に送信される値</td></tr>
    280         *   <tr><td>size="30"</td><td>オプション</td><td>inputタグの大きさ</td></tr>
    281         *   <tr><td>maxlength="50"</td><td>オプション</td><td>type属性が｢text｣,｢password｣ のときの最大文字数</td></tr>
    282         *   <tr><td>checked="checked"</td><td>オプション</td><td>type属性が｢checkbox｣,｢radio｣ の場合に選択されている状態にする。</td></tr>
    283         *   <tr><td>disabled="disabled"</td><td>オプション</td><td>選択や変更の操作をできない状態にする場合に指定</td></tr>
    284         *   <tr><td>accept="MIMEタイプ"</td><td>オプション</td><td>type属性が｢file｣の場合に処理可能なMIMEタイプを指定</td></tr>
    285         *   <tr><td>tabindex="Tab移動順"</td><td>オプション</td><td>0～32767の範囲で数字で指定(小さい順に移動)</td></tr>
    286         *   <tr><td>accesskey="ショートカットキー"</td><td>オプション</td><td>文字セット中の１文字：WindowsであればAltキーと同時使用</td></tr>
    287         *   <tr><td>src="URL"</td><td>オプション</td><td>type属性が｢image｣の場合送信ボタンの画像URLを指定</td></tr>
    288         *   <tr><td>alt="代替文字列"</td><td>オプション</td><td>type属性が｢image｣の場合、画像が表示できないときの代替文字列を指定</td></tr>
    289         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    290         *   <tr><td>body="表示するタグ文字列"</td><td>オリジナル</td><td>画像や文字などボタン上に表示させたいタグの文字列</td></tr>
    291         *   <tr><td>サポート外</td><td>未実装</td><td>readonly属性、usemap属性、ismap属性、align属性</td></tr>
    292         * </table>
    293         *
    294         * 設定できる属性
    295         * 形式は，
    296         *  text       １行のテキストフィールド
    297         *  password   パスワード用テキストフィールド
    298         *  checkbox   チェックボックス(複数選択可)
    299         *  radio      ラジオボタン(複数選択不可)
    300         *  submit     送信(サブミット)
    301         *  reset      リセット
    302         *  button     汎用ボタン
    303         *  image      イメージによる画像ボタン
    304         *  file       送信ファイルの選択
    305         *  hidden     表示せずにサーバーに送信する。
    306         * を指定します。
    307         *
    308         * ラジオボタン／チェックボックスであらかじめ,チェックをして
    309         * おきたい場合は,checked 属性に "checked" を登録します。
    310         * ファイルダイアログの場合は,attributesの accept 属性に "MIMEタイプ"
    311         * を登録します。
    312         * 属性群は,タグの中に,CSS等で使用できる class="XXX" などの
    313         * 文字を自由に登録する事が出来ます。
    314         * CSSでクラスを対応 class="XXXX"
    315         * タブで移動順を指定する tabindex="タブ順"
    316         * ショートカットキーを割り当てる accesskey="ショートカットキー"
    317         *
    318         * @param   attri  属性群
    319         * @param   name   名前
    320         * @param   value  値
    321         * @param   optAttri オプション文字列(タグ属性定義されていない属性の登録用文字列)
    322         *
    323         * @return  入力フォームタグ文字列
    324         */
    325        public static String input( final Attributes attri,final String name,final String value,final String optAttri ) {
    326                String values = attri.getAttribute( INPUT_KEY );
    327
    328                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    329                rtn.append("<input ");
    330                if( name  != null ) { rtn.append("name=\"").append( name ).append( "\" " ); }
    331                if( value != null ) { rtn.append("value=\"").append( value ).append( "\" " ); }
    332                rtn.append( values );
    333                if( optAttri != null ) {
    334                        rtn.append( " " );
    335                        rtn.append( optAttri );
    336                }
    337                rtn.append( " />" );
    338
    339                return rtn.toString();
    340        }
    341
    342        /**
    343         * 入力フォームの属性情報のみの文字列を作成します。
    344         * これは、name 属性や value 属性など、一般に都度変更されるフィールド
    345         * 以外の固定的な属性情報を、先に作成しておく場合に、使用します。
    346         *
    347         * @param   attri       属性リスト
    348         *
    349         * @return  入力フォームタグの属性情報文字列
    350         */
    351        public static String inputAttri( final Attributes attri ) {
    352                return attri.getAttribute( INPUT_KEY );
    353        }
    354
    355        /**
    356         * テキストエリアの属性情報のみの文字列を作成します。
    357         * これは、name 属性や value 属性など、一般に都度変更されるフィールド
    358         * 以外の固定的な属性情報を、先に作成しておく場合に、使用します。
    359         *
    360         * @param   attri       属性リスト
    361         *
    362         * @return  テキストエリアの属性情報文字列
    363         */
    364        public static String textareaAttri( final Attributes attri ) {
    365                return attri.getAttribute( TEXTAREA_KEY );
    366        }
    367
    368        /**
    369         * プルダウン等のメニューの属性情報のみの文字列を作成します。
    370         * これは、name 属性や value 属性など、一般に都度変更されるフィールド
    371         * 以外の固定的な属性情報を、先に作成しておく場合に、使用します。
    372         *
    373         * @param   attri       属性リスト
    374         *
    375         * @return  プルダウン等のメニューの属性情報文字列
    376         */
    377        public static String selectAttri( final Attributes attri ) {
    378                return attri.getAttribute( SELECT_KEY );
    379        }
    380
    381        /**
    382         * HIDDEN フォームを作成します。
    383         *
    384         * id属性に、name と同じ値が設定されます。
    385         *
    386         * @og.rev 5.5.4.0 (2012/07/02) ID属性追加
    387         *
    388         * @param   name  フォームの名前
    389         * @param   value 値
    390         *
    391         * @return  HIDDENフォームタグ文字列
    392         */
    393        public static String hidden( final String name,final String value ) {
    394//              StringBuilder rtn = new StringBuilder( BUFFER_SMALL );
    395
    396//              rtn.append("<input type=\"hidden\" ");
    397//              rtn.append("name=\"" ).append( name );
    398//              rtn.append("\" value=\"").append( value );
    399//              rtn.append( "\" />" );
    400
    401//              return rtn.toString();
    402                return hidden(name,value,name);
    403        }
    404
    405        /**
    406         * HIDDEN フォームを作成します。
    407         *
    408         * @og.rev 5.5.4.0 (2012/07/02) ID属性追加
    409         *
    410         * @param   name  フォームの名前
    411         * @param   value 値
    412         * @param   id    フォームのID
    413         *
    414         * @return  HIDDENフォームタグ文字列
    415         */
    416        public static String hidden( final String name, final String value, final String id ) {
    417                StringBuilder rtn = new StringBuilder( BUFFER_SMALL );
    418
    419                rtn.append( "<input type=\"hidden\" " );
    420                rtn.append( "name=\"" ).append( name );
    421                rtn.append( "\" value=\"" ).append( value );
    422                rtn.append( "\" id=\"" ).append( id );
    423                rtn.append( "\" />" );
    424
    425                return rtn.toString();
    426        }
    427
    428        /**
    429         * テキストエリアを作成します。
    430         *
    431         * &lt;textarea name="名前" rows="4" cols="40"  ....&gt;送信文字列 &lt;/textarea&gt;
    432         *
    433         * <table border="1" frame="box" rules="all" >
    434         *   <caption>Attributes に設定できる属性</caption>
    435         *   <tr><td>name="名前"</td><td>オプション</td><td>LabelResource.properties のキー</td></tr>
    436         *   <tr><td>rows="行数"</td><td>オプション</td><td>入力フィールドの表示行数</td></tr>
    437         *   <tr><td>cols="幅"</td><td>オプション</td><td>入力フィールドの表示幅(文字数)</td></tr>
    438         *   <tr><td>disabled="disabled"</td><td>オプション</td><td>選択や変更の操作をできない状態にする場合に指定</td></tr>
    439         *   <tr><td>tabindex="Tab移動順"</td><td>オプション</td><td>0～32767の範囲で数字で指定(小さい順に移動)</td></tr>
    440         *   <tr><td>accesskey="ショートカットキー"</td><td>オプション</td><td>文字セット中の１文字：WindowsであればAltキーと同時使用</td></tr>
    441         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    442         *   <tr><td>value="値"</td><td>オリジナル</td><td>name属性と共に送信される値</td></tr>
    443         *   <tr><td>body="表示するタグ文字列"</td><td>オリジナル</td><td>画像や文字などボタン上に表示させたいタグの文字列</td></tr>
    444         *   <tr><td>サポート外</td><td>未実装</td><td>readonly属性</td></tr>
    445         * </table>
    446         *
    447         * 設定できる属性
    448         *
    449         * 属性群は,タグの中に,CSS等で使用できる class="XXX" などの
    450         * 文字を自由に登録する事が出来ます。
    451         * CSSでクラスを対応 class="XXXX"
    452         * タブで移動順を指定する tabindex="タブ順"
    453         * ショートカットキーを割り当てる accesskey="ショートカットキー"
    454         *
    455         * @param   attri 属性群
    456         *
    457         * @return  入力フォームタグ文字列
    458         */
    459        public static String textarea( final Attributes attri ) {
    460                String values = attri.getAttribute( TEXTAREA_KEY );
    461                String body   = attri.get( "body" );
    462                if( body == null ) { body = "" ; }
    463
    464                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    465                rtn.append("<textarea ");
    466                rtn.append( values );
    467                rtn.append( ">" );
    468                rtn.append( body );
    469                rtn.append( "</textarea>" );
    470
    471                return rtn.toString();
    472        }
    473
    474        /**
    475         * ページリンクを作成します。
    476         *
    477         * &lt;A href="ＵＲＬ" target="ターゲット名"&gt;ラベル&lt;/A&gt;
    478         *
    479         * <table border="1" frame="box" rules="all" >
    480         *   <caption>Attributes に設定できる属性</caption>
    481         *   <tr><td>href="URL"</td><td>必須</td><td>リンク先のURLを指定します。</td></tr>
    482         *   <tr><td>charset="文字セット"</td><td>オプション</td><td>リンク先の文字コードセットを指定します。</td></tr>
    483         *   <tr><td>hreflang="言語セット"</td><td>オプション</td><td>リンク先の基本となる言語コードを指定します。</td></tr>
    484         *   <tr><td>type="MIMEタイプ"</td><td>オプション</td><td>リンク先のMIMEタイプを指定します。</td></tr>
    485         *   <tr><td>name="名前"</td><td>オプション</td><td>この要素をリンクの到達点とするための名前を指定します。</td></tr>
    486         *   <tr><td>rel="リンクタイプ"</td><td>オプション</td><td>この文書からみた href 属性で指定されるリンク先との関係</td></tr>
    487         *   <tr><td>rev="リンクタイプ"</td><td>オプション</td><td>href 属性で指定されるリンク先からみた、この文書との関係</td></tr>
    488         *   <tr><td>tabindex="Tab移動順"</td><td>オプション</td><td>0～32767の範囲で数字で指定(小さい順に移動)</td></tr>
    489         *   <tr><td>accesskey="ショートカットキー"</td><td>オプション</td><td>文字セット中の１文字：WindowsであればAltキーと同時使用</td></tr>
    490         *   <tr><td>target="フレーム名"</td><td>オプション</td><td>リンク先のフレーム名</td></tr>
    491         *   <tr><td>body="表示するタグ文字列"</td><td>オリジナル</td><td>画像や文字などをリンクにできます。</td></tr>
    492         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    493         *   <tr><td>サポート外</td><td>未実装</td><td>shape属性、coords属性</td></tr>
    494         * </table>
    495         *
    496         * 設定できる属性
    497         *
    498         * ラベルなしの場合, href属性の "URL" そのものを付けます。
    499         *
    500         * target属性のフレーム名は
    501         *
    502         *  _top        フレームを解除して,リンク先をフレーム全体に表示する。
    503         *  _parent リンク先を親フレームに表示する。
    504         *  _self   リンク先を自分自身に表示する。
    505         *  _blank  新しいウインドウを開いて，表示する。
    506         *  その他  フレーム作成時の名前で指定可能。
    507         *
    508         * を指定します。
    509         * なしの場合 _self (自分自身)を指定します。
    510         *
    511         * リンクメール機能
    512         * URLを，mailto:メールアドレス で設定すれば,メール送信ダイアログを
    513         * 開く事が出来ます。
    514         * 画像リンク機能
    515         * 画像をクリックするリンクは，ラベルの個所に &lt;img&gt;タグを設定します。
    516         *
    517         * &lt;a href="books.html"&gt;&lt;img src="banner.gif" width="468px" height="60px" alt="関連書籍紹介" border="0"&gt;&lt;/a&gt;
    518         *
    519         * 属性群は,タグの中に,CSS等で使用できる class="XXX" などの
    520         * 文字を自由に登録する事が出来ます。
    521         * CSSでクラスを対応 class="XXXX"
    522         * タブで移動順を指定する tabindex="タブ順"
    523         * ショートカットキーを割り当てる accesskey="ショートカットキー"
    524         *
    525         * @param   attri 属性群
    526         *
    527         * @return  ページリンクタグ文字列
    528         */
    529        public static String link( final Attributes attri ) {
    530                return link( attri,"" );
    531        }
    532
    533        /**
    534         * ページリンクを作成します。
    535         *
    536         * @param   attri 属性群
    537         * @param   urlEncode 文字列   ( ?key1=val1&amp;････ という文字列 無いときは "" )
    538         *
    539         * @return  ページリンクタグ文字列
    540         */
    541        public static String link( final Attributes attri, final String urlEncode ) {
    542
    543                String href = addUrlEncode( attri.get( "href" ),urlEncode );
    544
    545                String values = attri.getAttribute( LINK_KEY );
    546                String body   = attri.get( "body" );
    547                if( body == null ) { body = attri.get( "href" ) ; }
    548
    549                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    550                rtn.append("<a href=\"");
    551                rtn.append( href );
    552                rtn.append( "\" " );
    553                rtn.append( values );
    554                rtn.append( ">" );
    555                rtn.append( body );
    556                rtn.append( "</a>" );
    557
    558                return rtn.toString();
    559        }
    560
    561        /**
    562         * xlink 形式のページリンクを作成します。
    563         *
    564         * 基本的には、link と同じです。アドレスの指定も、href で指定してください。
    565         * 内部的に、xlink:href に変換します。
    566         * また、URL引数を、"&amp;" で結合するのではなく、"&amp;amp;" で結合させます。
    567         * これは、xlink そのものが、XML上に記述された場合に、XMLのルールで再度パース
    568         * される為です。
    569         *
    570         * @param   attri 属性群
    571         * @param   urlEncode 文字列   ( ?key1=val1&amp;････ という文字列 無いときは "" )
    572         *
    573         * @return  ページリンクタグ文字列
    574         */
    575        public static String xlink( final Attributes attri, final String urlEncode ) {
    576
    577                String href = addUrlEncode( attri.get( "href" ),urlEncode,"&amp;" );
    578
    579                String values = attri.getAttribute( LINK_KEY );
    580                String body   = attri.get( "body" );
    581                if( body == null ) { body = attri.get( "href" ) ; }
    582
    583                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    584                rtn.append("<a xlink:href=\"");
    585                rtn.append( href );
    586                rtn.append( "\" " );
    587                rtn.append( values );
    588                rtn.append( ">" );
    589                rtn.append( body );
    590                rtn.append( "</a>" );
    591
    592                return rtn.toString();
    593        }
    594
    595        /**
    596         * メニューを作成します。
    597         *
    598         * @param   attri 属性群
    599         * @param   opt 選択肢(オプション)
    600         *
    601         * @return  メニュータグ文字列
    602         */
    603        public static String select( final Attributes attri,final Options opt ) {
    604                String name     = attri.get( "name" );
    605                String optAttri = attri.get( "optionAttributes" );
    606
    607                return select( attri,opt,name,optAttri );
    608        }
    609
    610        /**
    611         * メニューを作成します。
    612         *
    613         * &lt;select size="行数" name="名前" multiple&gt;
    614         *   &lt;option value="送信文字１"&gt;コメント&lt;/option&gt;
    615         *   &lt;option value="送信文字２"&gt;コメント&lt;/option&gt;
    616         *   &lt;option value="送信文字３" selected="selected"&gt;コメント&lt;/option&gt;
    617         * &lt;/select&gt;
    618         *
    619         * <table border="1" frame="box" rules="all" >
    620         *   <caption>Attributes に設定できる属性</caption>
    621         *   <tr><td>name="名前"</td><td>オプション</td><td>LabelResource.properties のキー</td></tr>
    622         *   <tr><td>size="行数"</td><td>オプション</td><td>select要素をリストボックスとして表示する場合の行数</td></tr>
    623         *   <tr><td>multiple="multiple"</td><td>オプション</td><td>選択肢の中から複数選択出来るようにする。</td></tr>
    624         *   <tr><td>disabled="disabled"</td><td>オプション</td><td>選択や変更の操作をできない状態にする場合に指定</td></tr>
    625         *   <tr><td>tabindex="Tab移動順"</td><td>オプション</td><td>0～32767の範囲で数字で指定(小さい順に移動)</td></tr>
    626         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    627         * </table>
    628         *
    629         * 属性群は,タグの中に,CSS等で使用できる class="XXX" などの
    630         * 文字を自由に登録する事が出来ます。
    631         * CSSでクラスを対応 class="XXXX"
    632         *
    633         * @param   attri       属性群
    634         * @param   opt         選択肢(オプション)
    635         * @param   name        名前
    636         * @param   optAttri オプション属性
    637         *
    638         * @return  メニュータグ文字列
    639         */
    640        public static String select( final Attributes attri,final Options opt,final String name,final String optAttri ) {
    641                String values  = attri.getAttribute( SELECT_KEY );
    642                String options = opt.getOption();
    643
    644                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    645                rtn.append("<select ");
    646                if( name  != null ) { rtn.append("name=\"").append( name ).append( "\" " ); }
    647                rtn.append( values );
    648                if( optAttri != null ) {
    649                        rtn.append( " " );
    650                        rtn.append( optAttri );
    651                }
    652                rtn.append( ">" );
    653                rtn.append( options );
    654                rtn.append( "</select>" );
    655
    656                return rtn.toString();
    657        }
    658
    659        /**
    660         * オプションを作成します。
    661         *
    662         * &lt;select size="行数" name="名前" multiple&gt;
    663         *   &lt;option value="送信文字１"&gt;コメント&lt;/option&gt;
    664         *   &lt;option value="送信文字２"&gt;コメント&lt;/option&gt;
    665         *   &lt;option value="送信文字３" selected="selected"&gt;コメント&lt;/option&gt;
    666         * &lt;/select&gt;
    667         *
    668         * <table border="1" frame="box" rules="all" >
    669         *   <caption>Attributes に設定できる属性</caption>
    670         *   <tr><td>value="値"</td><td>オプション</td><td>送信する値</td></tr>
    671         *   <tr><td>selected="selected"</td><td>オプション</td><td>選択肢をあらかじめ選択された状態にしておく</td></tr>
    672         *   <tr><td>disabled="disabled"</td><td>オプション</td><td>選択や変更の操作をできない状態にする場合に指定</td></tr>
    673         *   <tr><td>body="表示するタグ文字列"</td><td>オリジナル</td><td>選択肢に表示させたいタグの文字列</td></tr>
    674         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    675         * </table>
    676         *
    677         * セレクタとは，リストボックスやメニューなどの option引数にセットする
    678         * 複数のデータをoptionタグでくるんだものです。
    679         *
    680         * @param   attri 属性群
    681         *
    682         * @return  オプションタグ文字列
    683         */
    684        public static String option( final Attributes attri ) {
    685                String values  = attri.getAttribute( OPTION_KEY );
    686                String body     = attri.get( "body" );
    687                if( body == null ) { body = "No Label" ; }
    688
    689                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    690                rtn.append("<option ");
    691                rtn.append( values );
    692                rtn.append( " >" );
    693                rtn.append( body );
    694                rtn.append( "</option>" );
    695
    696                return rtn.toString();
    697        }
    698
    699        /**
    700         * フレームタグを作成します。
    701         *
    702         * &lt;frame marginheight="2px" marginwidth="2px" src="query.jsp" name="QUERY" /&gt;
    703         *
    704         * <table border="1" frame="box" rules="all" >
    705         *   <caption>Attributes に設定できる属性</caption>
    706         *   <tr><td>src="URL"</td><td>オプション</td><td>フレームの表示先URLを指定します。</td></tr>
    707         *   <tr><td>name="フレーム名"</td><td>オプション</td><td>フレームに付ける名前を指定します。</td></tr>
    708         *   <tr><td>longdesc="URI"</td><td>オプション</td><td>フレームの詳しい説明のURI</td></tr>
    709         *   <tr><td>marginwidth="左右のマージン"</td><td>オプション</td><td>フレーム内の左右のマージンを指定します。</td></tr>
    710         *   <tr><td>marginheight="上下のマージン"</td><td>オプション</td><td>フレーム内の上下のマージンを指定します。</td></tr>
    711         *   <tr><td>noresize="noresize"</td><td>オプション</td><td>フレームサイズを変更できないようにします。</td></tr>
    712         *   <tr><td>scrolling="スクロールの制御"</td><td>オプション</td><td>yes:スクロールバーを表示 no:表示しない auto:必要に応じて表示(デフォルト)</td></tr>
    713         *   <tr><td>frameborder="枠の表示"</td><td>オプション</td><td>0:枠を表示しない  1:枠を表示する。(デフォルト)</td></tr>
    714         *   <tr><td>keys="引数にセットするキー"</td><td>オプション</td><td>URI の引数にセットするキーを CSV 形式でセットします。</td></tr>
    715         *   <tr><td>value="引数にセットする値"</td><td>オプション</td><td>URI の引数にセットする値を CSV 形式でセットします。</td></tr>
    716         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style</td></tr>
    717         * </table>
    718         *
    719         * 設定できる属性
    720         *
    721         * scrolling属性
    722         *
    723         *  yes:常にスクロールバーを表示
    724         *  no:常にスクロールバーを表示しない
    725         *  auto:必要に応じてスクロールバーを表示(デフォルト)
    726         *
    727         * を指定します。
    728         *
    729         * frameborder属性
    730         *
    731         *  0:枠を表示しない
    732         *  1:枠を表示する。(デフォルト)
    733         *
    734         * を指定します。
    735         *
    736         * 属性群は,タグの中に,CSS等で使用できる class="XXX" などの
    737         * 文字を自由に登録する事が出来ます。
    738         * CSSでクラスを対応 class="XXXX"
    739         *
    740         * @param   attri 属性群
    741         *
    742         * @return  フレームタグ文字列
    743         */
    744        public static String frame( final Attributes attri ) {
    745                return frame( attri,"" );
    746        }
    747
    748        /**
    749         * フレームタグを作成します。
    750         *
    751         * @param   attri 属性群
    752         * @param   urlEncode 文字列   ( ?key1=val1&amp;････ という文字列 無いときは "" )
    753         *
    754         * @return  フレームタグ文字列
    755         */
    756        public static String frame( final Attributes attri,final String urlEncode ) {
    757
    758                String src  = addUrlEncode( attri.get( "src" ),urlEncode );
    759                String values = attri.getAttribute( FRAME_KEY );
    760
    761                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    762                rtn.append("<frame src=\"");
    763                rtn.append( src );
    764                rtn.append( "\" " );
    765                rtn.append( values );
    766                rtn.append( " />" );
    767
    768                return rtn.toString();
    769        }
    770
    771        /**
    772         * インラインフレームタグを作成します。
    773         *
    774         * @param   attri 属性群
    775         * @param   urlEncode 文字列   ( ?key1=val1&amp;････ という文字列 無いときは "" )
    776         *
    777         * @og.rev 5.9.1.2 (2015/10/23) 新規追加
    778         *
    779         * @return  インラインフレームタグ文字列
    780         */
    781        public static String iframe( final Attributes attri,final String urlEncode ) {
    782
    783                String src  = addUrlEncode( attri.get( "src" ),urlEncode );
    784                String values = attri.getAttribute( IFRAME_KEY );
    785
    786                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    787                rtn.append("<iframe src=\"");
    788                rtn.append( src );
    789                rtn.append( "\" " );
    790                rtn.append( values );
    791                rtn.append( "><!-- --></iframe>" ); // iframeは自己終了できない
    792
    793                return rtn.toString();
    794        }
    795
    796        /**
    797         * URLエンコード文字列を作成します。
    798         * エンコードすべき文字列が無い場合は, ０ストリング("") を返します。
    799         * エンコード文字列がある場合は, "?KEY1=VAL1&amp;KEY2=VAL2&amp;･･･" という文字列を
    800         * 返します。
    801         * つまり、どちらのケースでも、URI に 連結させればよいことになります。
    802         *
    803         * @param   keys   URLの引数となるキー群
    804         * @param   values URLの引数となる値群
    805         *
    806         * @return  URLエンコード文字列
    807         */
    808        public static String urlEncode( final String keys,final String values ) {
    809                return urlEncode( keys,values,"&" );
    810        }
    811
    812        /**
    813         * URLエンコード文字列を作成します。
    814         * エンコードすべき文字列が無い場合は, ０ストリング("") を返します。
    815         * エンコード文字列がある場合は, "?KEY1=VAL1&amp;KEY2=VAL2&amp;･･･" という文字列を
    816         * 返します。
    817         * つまり、どちらのケースでも、URI に 連結させればよいことになります。
    818         *
    819         * @param   keys   URLの引数となるキー群
    820         * @param   values URLの引数となる値群
    821         * @param   join   URLの引数群を連結させる文字列
    822         *
    823         * @return  URLエンコード文字列
    824         */
    825        public static String urlEncode( final String keys,final String values,final String join ) {
    826                if( keys == null || values == null ) { return ""; }
    827
    828                String[] key = StringUtil.csv2Array( keys );
    829                String[] val = StringUtil.csv2Array( values );
    830
    831                return ( urlEncode( key,val,join ) );
    832        }
    833
    834        /**
    835         * URLエンコード文字列を作成します。
    836         * エンコードすべき文字列が無い場合は, ０ストリング("") を返します。
    837         * エンコード文字列がある場合は, "?KEY1=VAL1&amp;KEY2=VAL2&amp;･･･" という文字列を
    838         * 返します。
    839         * つまり、どちらのケースでも、URI に 連結させればよいことになります。
    840         *
    841         * @param   key   URLの引数となるキーの配列
    842         * @param   val   URLの引数となる値の配列
    843         *
    844         * @return  URLエンコード文字列
    845         */
    846        public static String urlEncode( final String[] key,final String[] val ) {
    847                return urlEncode( key,val,"&" );
    848        }
    849
    850        /**
    851         * URLエンコード文字列を作成します。
    852         * エンコードすべき文字列が無い場合は, ０ストリング("") を返します。
    853         * エンコード文字列がある場合は, "?KEY1=VAL1&amp;KEY2=VAL2&amp;･･･" という文字列を
    854         * 返します。
    855         * つまり、どちらのケースでも、URI に 連結させればよいことになります。
    856         *
    857         * @og.rev 5.10.15.3 (2019/09/27) fenc追加対応で作成
    858         *
    859         * @param   key   URLの引数となるキーの配列
    860         * @param   val   URLの引数となる値の配列
    861         * @param   join   URLの引数群を連結させる文字列
    862         *
    863         * @return  URLエンコード文字列
    864         */
    865        public static String urlEncode( final String[] key,final String[] val,final String join ) {
    866                return urlEncode( key, val, join, false);
    867        }
    868
    869        /**
    870         * URLエンコード文字列を作成します。
    871         * エンコードすべき文字列が無い場合は, ０ストリング("") を返します。
    872         * エンコード文字列がある場合は, "?KEY1=VAL1&amp;KEY2=VAL2&amp;･･･" という文字列を
    873         * 返します。
    874         * つまり、どちらのケースでも、URI に 連結させればよいことになります。
    875         *
    876         * @og.rev 4.3.3.3 (2008/10/22) valに対して副作用を及ぼさないように修正
    877         * @og.rev 5.10.12.4 (2019/06/21) keyのURIエンコードを追加
    878         * @og.rev 5.10.15.3 (2019/09/27) fencフラグ追加
    879         *
    880         * @param   key   URLの引数となるキーの配列
    881         * @param   val   URLの引数となる値の配列
    882         * @param   join   URLの引数群を連結させる文字列
    883         * @param   fenc  先頭が[の場合でも強制エンコードするためのフラグ(初期値false)
    884         *
    885         * @return  URLエンコード文字列
    886         */
    887        public static String urlEncode( final String[] key,final String[] val,final String join, final boolean fenc ) {
    888                if( key == null || key.length == 0 || val == null || val.length == 0 ) {
    889                        return "";
    890                }
    891                else if( key.length != val.length ) {
    892                        String errMsg = "urlEncode のキーとバリューの個数が異なります。" + CR
    893                                                + "key.length=[" + key.length + "]  val.length=[" + val.length + "]";
    894                        throw new RuntimeException( errMsg );
    895                }
    896
    897                // 4.3.3.3 (2008/10/22)
    898                String[] tval = new String[val.length];
    899
    900                for( int i=0; i<val.length; i++ ) {
    901                        if( key[i] == null || key[i].length() == 0 ) { return ""; }
    902                        if( val[i] == null || val[i].length() == 0 ) { tval[i] = ""; }
    903//                      else if( val[i].charAt(0) == '[' ) {            // 暫定対応
    904                        else if( val[i].charAt(0) == '[' && !fenc ) {           // 5.10.15.3 (2019/09/27) fenc追加
    905                                tval[i] = val[i];
    906                        }
    907                        else {
    908                                tval[i] = StringUtil.urlEncode( val[i] );
    909                        }
    910//                      else if( val[i].charAt(0) != '[' ) {            // 暫定対応
    911//                              tval[i] = StringUtil.urlEncode( val[i] );
    912//                      }
    913//                      else {
    914//                              tval[i] = val[i];
    915//                      }
    916                }
    917
    918                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    919
    920//              rtn.append( key[0] ).append( "=" ).append( tval[0] );
    921                rtn.append( StringUtil.urlEncode(key[0]) ).append( "=" ).append( tval[0] ); // 5.10.12.4 (2019/06/21)
    922                for( int i=1; i<key.length; i++) {
    923                        rtn.append( join );
    924//                      rtn.append( key[i] ).append( "=" ).append( tval[i] );
    925                        rtn.append( StringUtil.urlEncode(key[i]) ).append( "=" ).append( tval[i] ); // 5.10.12.4 (2019/06/21)
    926                }
    927                return rtn.toString();
    928        }
    929
    930        /**
    931         * URL文字列に、URLエンコード文字列を連結します。
    932         *
    933         * URL文字列中にすでに "?" 文字が存在する場合は、URLエンコード側の
    934         * 文字列とは、 "&amp;" で連結します。
    935         * 逆に、"?" が存在しなければ、"?" で連結します。
    936         * URLエンコード文字列が null の場合は、連結しません。
    937         *
    938         * @param   url URL文字列
    939         * @param   encode URLエンコード文字列
    940         *
    941         * @return  連結文字列
    942         */
    943        public static String addUrlEncode( final String url,final String encode ) {
    944                return addUrlEncode( url,encode,"&" );
    945        }
    946
    947        /**
    948         * URL文字列に、URLエンコード文字列を連結します。
    949         *
    950         * URL文字列中にすでに "?" 文字が存在する場合は、URLエンコード側の
    951         * 文字列とは、 join (例 "&amp;" ) で連結します。
    952         * 逆に、"?" が存在しなければ、"?" で連結します。
    953         * URLエンコード文字列が null の場合は、連結しません。
    954         * 連結する、encode 文字列の先頭が、join 文字列の場合、そのまま連結します。
    955         * 先頭が、そうでない場合は、join 文字列で連結します。
    956         * "?" が存在せず、encode 文字列の先頭が、join 文字列の場合は、、
    957         * encode 文字列の先頭を取り除いて、"?" で連結します。
    958         *
    959         * 例：
    960         *    ①. abc.html    key1=val1&amp;key2=val2      ⇒ abc.html?key1=val1&amp;key2=val2
    961         *    ②．abc.html   &amp;key1=val1&amp;key2=val2  ⇒ abc.html?key1=val1&amp;key2=val2
    962         *    ③．abc.html?key1=val1    key2=val2          ⇒ abc.html?key1=val1&amp;key2=val2
    963         *    ④．abc.html?key1=val1   &amp;key2=val2      ⇒ abc.html?key1=val1&amp;key2=val2
    964         *
    965         * @og.rev 5.2.1.0 (2010/10/01) urlがnullの場合に、NullPointerExceptionが発生するバグを修正
    966         *
    967         * @param   url URL文字列
    968         * @param   encode URLエンコード文字列
    969         * @param   join   URLの引数群を連結させる文字列
    970         *
    971         * @return  連結文字列
    972         */
    973        public static String addUrlEncode( final String url,final String encode,final String join ) {
    974                // 5.2.1.0 (2010/10/01) urlがnullの場合に、NullPointerExceptionが発生するバグを修正
    975                String tmpUrl = ( url == null ? "" : url );
    976
    977                if( encode == null || encode.length() == 0 ) { return tmpUrl; }
    978
    979                final String rtn ;
    980                if( tmpUrl.indexOf( '?' ) < 0 ) {
    981                        if( encode.startsWith( join ) ) {
    982                                rtn = tmpUrl + "?" + encode.substring(join.length());           // ②
    983                        }
    984                        else {
    985                                rtn = tmpUrl + "?" + encode;                                                            // ①
    986                        }
    987                }
    988                else {
    989                        if( encode.startsWith( join ) ) {
    990                                rtn = tmpUrl + encode;                                          // ④
    991                        }
    992                        else {
    993                                rtn = tmpUrl + join + encode;                           // ③
    994                        }
    995                }
    996                return rtn ;
    997        }
    998
    999        /**
    1000         * 指定位置に画像を配置します。
    1001         *
    1002         * @param   attri 属性群
    1003         *
    1004         * @return  イメージタグ文字列
    1005         */
    1006        public static String img( final Attributes attri ) {
    1007                String values = attri.getAttribute( IMAGE_KEY );
    1008                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    1009                rtn.append( "<img " );
    1010                rtn.append( values );
    1011                rtn.append( " />" );
    1012
    1013                return rtn.toString();
    1014        }
    1015
    1016        /**
    1017         * フォームを作成します。
    1018         *
    1019         * &lt;form action="URI" method="HTTPメソッド" enctype="MIMEタイプ" target="フレーム名" ･･･ &gt;フォーム等&lt;/form&gt;
    1020         *
    1021         * <table border="1" frame="box" rules="all" >
    1022         *   <caption>Attributes に設定できる属性</caption>
    1023         *   <tr><td>action="URI"</td><td>必須</td><td>送信されたフォームデータを処理するプログラムＵＲＩ</td></tr>
    1024         *   <tr><td>method="HTTPメソッド"</td><td>オプション</td><td>get/post</td></tr>
    1025         *   <tr><td>enctype="MIMEタイプ"</td><td>オプション</td><td>フォームデータ送信時のMIMEタイプ</td></tr>
    1026         *   <tr><td>accept-charset="文字セット"</td><td>オプション</td><td>データとして受付可能な文字セットの指定</td></tr>
    1027         *   <tr><td>accept="MIMEタイプ"</td><td>オプション</td><td>データとして処理可能なMIMEタイプを指定</td></tr>
    1028         *   <tr><td>name="名前"</td><td>オプション</td><td>スクリプト等から参照する場合の名前</td></tr>
    1029         *   <tr><td>target="フレーム名"</td><td>オプション</td><td>フォームを送信した結果を表示させるフレーム</td></tr>
    1030         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    1031         *   <tr><td>body="フォーム等の文字列"</td><td>必須</td><td>input 等のフォーム要素</td></tr>
    1032         * </table>
    1033         *
    1034         * @param   attri 属性群
    1035         *
    1036         * @return  フォームタグ文字列
    1037         */
    1038        public static String form( final Attributes attri ) {
    1039                String values = attri.getAttribute( FORM_KEY );
    1040                String body   = attri.get( "body" );
    1041                if( body == null ) { body = "" ; }
    1042
    1043                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    1044                rtn.append("<form ");
    1045                rtn.append( values );
    1046                rtn.append( ">" );
    1047                rtn.append( CR );
    1048                rtn.append( body );
    1049                rtn.append( CR );
    1050                rtn.append("</form>");
    1051
    1052                return rtn.toString();
    1053        }
    1054
    1055        /**
    1056         * 汎用インライン要素(SPAN)を作成します。
    1057         *
    1058         * &lt;span class="XXXX" ･･･ &gt;テキスト等&lt;/span&gt;
    1059         *
    1060         * <table border="1" frame="box" rules="all" >
    1061         *   <caption>Attributes に設定できる属性</caption>
    1062         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    1063         *   <tr><td>body="テキスト等の文字列"</td><td>オプション</td><td>このテキストを修飾します。</td></tr>
    1064         * </table>
    1065         *
    1066         * @param   attri 属性群
    1067         *
    1068         * @return  SPANタグ文字列
    1069         */
    1070        public static String span( final Attributes attri ) {
    1071                String values = attri.getAttribute( SPAN_KEY );
    1072
    1073                String optAttri = attri.get( "optionAttributes" );
    1074                String body   = attri.get( "body" );
    1075                if( body == null ) { body = "" ; }
    1076
    1077                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    1078                rtn.append("<span ");
    1079                rtn.append( values );
    1080                if( optAttri != null ) {
    1081                        rtn.append( " " );
    1082                        rtn.append( optAttri );
    1083                }
    1084                rtn.append( ">" );
    1085                rtn.append( body );
    1086                rtn.append( "</span>" );
    1087
    1088                return rtn.toString();
    1089        }
    1090
    1091        /**
    1092         * 整形済みテキスト(PRE)を作成します。
    1093         *
    1094         * &lt;pre class="XXXX" ･･･ &gt;テキスト等&lt;/pre&gt;
    1095         *
    1096         * <table border="1" frame="box" rules="all" >
    1097         *   <caption>Attributes に設定できる属性</caption>
    1098         *   <tr><td>汎用属性</td><td>オプション</td><td>class,id,title,style,lang,dir,xml:lang</td></tr>
    1099         *   <tr><td>body="テキスト等の文字列"</td><td>オプション</td><td>このテキストを修飾します。</td></tr>
    1100         * </table>
    1101         *
    1102         * @param   attri 属性群
    1103         *
    1104         * @return  PREタグ文字列
    1105         */
    1106        public static String pre( final Attributes attri ) {
    1107                String values = attri.getAttribute( PRE_KEY );
    1108
    1109                String optAttri = attri.get( "optionAttributes" );
    1110                String body   = attri.get( "body" );
    1111                if( body == null ) { body = "" ; }
    1112
    1113                StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
    1114                rtn.append("<pre ");
    1115                rtn.append( values );
    1116                if( optAttri != null ) {
    1117                        rtn.append( " " );
    1118                        rtn.append( optAttri );
    1119                }
    1120                rtn.append( ">" );
    1121                rtn.append( body );
    1122                rtn.append( "</pre>" );
    1123
    1124                return rtn.toString();
    1125        }
    1126
    1127        /**
    1128         * URLチェック用のキーを返します。
    1129         *
    1130         * 引数に指定されたhrefに対して、時間とユーザーIDを付加した暗号化文字列を
    1131         * 引数に追加します。
    1132         *
    1133         * 暗号化は、org.opengion.fukurou.util.HybsCryptographyを使用します。
    1134         * 暗号化を行う文字列のフォーマットは、[href],time=[checkTime],userid=[loginUser]です。
    1135         *
    1136         * @og.rev 4.3.7.1 (2009/06/08) 新規追加
    1137         * @og.rev 4.3.7.4 (2009/07/01) 循環参照を解消
    1138         * @og.rev 5.8.8.0 (2015/06/05) キー指定対応で別メソッドに処理を委譲
    1139         *
    1140         * @param   href チェック対象のURL
    1141         * @param   key チェックキーのパラメーターキー
    1142         * @param   userid ユーザーID
    1143         * @param   time 有効時間
    1144         *
    1145         * @return  チェックキー
    1146         * @see org.opengion.fukurou.security.HybsCryptography
    1147         */
    1148        public static String addURLCheckKey( final String href, final String key, final String userid, final long time ) {
    1149//              String checkKey = href;
    1150//              checkKey = checkKey.replace( "../", "" );
    1151
    1152//              checkKey = checkKey + ",time=" + time + ",userid=" + userid;
    1153//              checkKey = HYBS_CRYPTOGRAPHY.encrypt( checkKey );
    1154//              return addUrlEncode( href, key + "=" + checkKey );
    1155
    1156                return addURLCheckKey( href, key, userid, time, null );
    1157        }
    1158
    1159        /**
    1160         * URLチェック用のキーを返します。
    1161         *
    1162         * 引数に指定されたhrefに対して、時間とユーザーIDを付加した暗号化文字列を
    1163         * 引数に追加します。
    1164         *
    1165         * 暗号化は、org.opengion.fukurou.util.HybsCryptographyを使用します。
    1166         * cryptを渡した場合はそのキーを利用して変換をかけますが、NULLの場合は標準キーで暗号化されます。
    1167         * 暗号化を行う文字列のフォーマットは、[href],time=[checkTime],userid=[loginUser]です。
    1168         *
    1169         * @og.rev 5.8.8.0 (2015/06/05) 新規作成
    1170         *
    1171         * @param   href チェック対象のURL
    1172         * @param   key チェックキーのパラメーターキー
    1173         * @param   userid ユーザーID
    1174         * @param   time 有効時間
    1175         * @param       crypt 暗号化クラス
    1176         *
    1177         * @return  チェックキー
    1178         * @see org.opengion.fukurou.security.HybsCryptography
    1179         */
    1180        public static String addURLCheckKey( final String href, final String key, final String userid, final long time, final HybsCryptography crypt ) {
    1181                String checkKey = href;
    1182
    1183                checkKey = checkKey + ",time=" + time + ",userid=" + userid;
    1184
    1185                if( crypt == null ){
    1186                        checkKey = HYBS_CRYPTOGRAPHY.encrypt( checkKey );
    1187                }
    1188                else{
    1189                        checkKey = crypt.encrypt( checkKey );
    1190                }
    1191
    1192                return addUrlEncode( href, key + "=" + checkKey );
    1193        }
    1194
    1195        /**
    1196         * Aタグの文字列を解析して、href属性にURLチェック用の暗号化文字列を付加した形で、
    1197         * Aタグを再構築し、返します。
    1198         *
    1199         * @og.rev 4.3.7.1 (2009/06/08) 新規追加
    1200         * @og.rev 4.3.7.4 (2009/07/01) 循環参照を解消
    1201         * @og.rev 5.8.8.0 (2015/06/05) キー指定対応で別メソッドに処理を委譲
    1202         *
    1203         * @param   tag Aタグ文字列
    1204         * @param   key チェックキーのパラメーターキー
    1205         * @param   userid ユーザーID
    1206         * @param   time 有効時間
    1207         *
    1208         * @return  URLチェックキーが付加されたAタグ文字列
    1209         */
    1210        public static String embedURLCheckKey( final String tag, final String key, final String userid, final long time ) {
    1211//              String rtn = tag;
    1212//              int hrefStr = rtn.indexOf( "href=\"" );
    1213//              if( hrefStr >= 0 ) {
    1214//                      int hrefEnd = rtn.indexOf( "\"",hrefStr + 6 );
    1215//                      if( hrefEnd >= 0 ) {
    1216//                              String href = rtn.substring( hrefStr + 6, hrefEnd );
    1217//                              href = XHTMLTag.addURLCheckKey( href, key, userid, time );
    1218//                              rtn = rtn.substring( 0,  hrefStr ) + "href=\"" + href + rtn.substring( hrefEnd );
    1219//                      }
    1220//              }
    1221//              return rtn;
    1222                return embedURLCheckKey( tag, key, userid, time, null  );
    1223        }
    1224
    1225        /**
    1226         * Aタグの文字列を解析して、href属性にURLチェック用の暗号化文字列を付加した形で、
    1227         * Aタグを再構築し、返します。
    1228         *
    1229         * @og.rev 5.8.8.0 (2015/06/05) 新規作成
    1230         *
    1231         * @param   tag Aタグ文字列
    1232         * @param   key チェックキーのパラメーターキー
    1233         * @param   userid ユーザーID
    1234         * @param   time 有効時間
    1235         * @param       crypt 暗号化クラス
    1236         *
    1237         * @return  URLチェックキーが付加されたAタグ文字列
    1238         */
    1239        public static String embedURLCheckKey( final String tag, final String key, final String userid, final long time, final HybsCryptography crypt ) {
    1240                String rtn = tag;
    1241                int hrefStr = rtn.indexOf( "href=\"" );
    1242                if( hrefStr >= 0 ) {
    1243                        int hrefEnd = rtn.indexOf( "\"",hrefStr + 6 );
    1244                        if( hrefEnd >= 0 ) {
    1245                                String href = rtn.substring( hrefStr + 6, hrefEnd );
    1246                                href = XHTMLTag.addURLCheckKey( href, key, userid, time, crypt );
    1247                                rtn = rtn.substring( 0,  hrefStr ) + "href=\"" + href + rtn.substring( hrefEnd );
    1248                        }
    1249                }
    1250                return rtn;
    1251        }
    1252}