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         * <button type="形式" name="名前" value="送信文字" オプション・・・ >ラベル</button>
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>文字セット中の1文字: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>文字セット中の1文字: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       1行のテキストフィールド
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>文字セット中の1文字: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="URL" 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>文字セット中の1文字: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="送信文字1"&gt;コメント&lt;/option&gt;
615         *   &lt;option value="送信文字2"&gt;コメント&lt;/option&gt;
616         *   &lt;option value="送信文字3" 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="送信文字1"&gt;コメント&lt;/option&gt;
664         *   &lt;option value="送信文字2"&gt;コメント&lt;/option&gt;
665         *   &lt;option value="送信文字3" 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         * エンコードすべき文字列が無い場合は, 0ストリング("") を返します。
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         * エンコードすべき文字列が無い場合は, 0ストリング("") を返します。
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         * エンコードすべき文字列が無い場合は, 0ストリング("") を返します。
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         * エンコードすべき文字列が無い場合は, 0ストリング("") を返します。
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         * エンコードすべき文字列が無い場合は, 0ストリング("") を返します。
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         *    A.abc.html   &amp;key1=val1&amp;key2=val2  ⇒ abc.html?key1=val1&amp;key2=val2
962         *    B.abc.html?key1=val1    key2=val2          ⇒ abc.html?key1=val1&amp;key2=val2
963         *    C.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());           // A
983                        }
984                        else {
985                                rtn = tmpUrl + "?" + encode;                                                            // @
986                        }
987                }
988                else {
989                        if( encode.startsWith( join ) ) {
990                                rtn = tmpUrl + encode;                                          // C
991                        }
992                        else {
993                                rtn = tmpUrl + join + encode;                           // B
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>送信されたフォームデータを処理するプログラムURI</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}