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.hayabusa.taglib;
017
018import java.io.IOException;
019
020import jakarta.mail.internet.MimeUtility;
021import jakarta.servlet.ServletException;
022import jakarta.servlet.http.HttpServletRequest;
023import jakarta.servlet.http.HttpServletResponse;
024
025import org.opengion.fukurou.security.HybsCryptography;                  // 5.10.11.0 (2019/05/03)
026import org.opengion.fukurou.system.LogWriter;
027import org.opengion.fukurou.util.StringUtil;
028import org.opengion.fukurou.util.XHTMLTag;
029import org.opengion.fukurou.util.ToString;                                              // 6.1.1.0 (2015/01/17)
030import org.opengion.hayabusa.common.HybsSystem;
031import org.opengion.hayabusa.common.HybsSystemException;
032import org.opengion.hayabusa.db.DBTableModel;
033import org.opengion.hayabusa.resource.GUIInfo;
034
035import static org.opengion.fukurou.util.StringUtil.nval;
036
037/**
038 * 制御を別の画面にフォワードする場合に使用するタグです(通常は、entry.jsp で使用します)。
039 *
040 * フォワード時に、指定の引数をセットできます。
041 *
042 * @og.formSample
043 * ●形式:<og:forward page="…" gamenId="[…]" />
044 * ●body:なし
045 *
046 * ●Tag定義:
047 *   <og:forward
048 *       gamenId            【TAG】gamenId 属性を登録します
049 *       page             ○【TAG】転送先URLを指定します(必須)。
050 *       keys               【TAG】キーを CSV形式でセットします
051 *       vals               【TAG】キーに対応する値を CSV形式でセットします
052 *       dbkeys             【TAG】DBキーをCSV形式でセットします
053 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します(初期値:session)
054 *       useRedirect        【TAG】response.sendRedirect するかどうか[true/false]を指定します(初期値:false)
055 *       contentType        【TAG】response.sendRedirect する場合、ContentType を設定します(初期値:未指定) 7.1.0.0 (2020/01/20)
056 *       target             【TAG】サブミット先の文書を表示させるフレーム、またはウィンドウの名前を指定します
057 *       filename           【TAG】ファイル転送時にファイル名の別名を指定します(初期値:null)
058 *       disposition        【TAG】ファイル転送時のヘッダー情報として、Content-Dispositionに設定する値を指定します(初期値:CONTENT_DISPOSITION[={@og.value SystemData#CONTENT_DISPOSITION}])。
059 *       noTransition       【TAG】(通常は使いません )画面遷移を行わない形式の登録方法を使用するかを指定します
060 *       useAjaxSubmit      【TAG】(通常は使いません) ajaxを利用したsubmitを利用するかどうかを指定します
061 *       redirectEncode     【TAG】(通常は使いません) useRedirect=true時に 日本語を含む転送先(page)をバイナリ変換するときのコード名[UTF-8/Windows-31J]など(初期値:null)
062 *       forceEnc           【TAG】(通常は使いません) valsの値が[で開始している場合でもURLEncodeを通すかを設定します(初期値:false) 5.10.15.3 (2019/09/27)
063 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
064 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
065 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
066 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
067 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
068 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
069 *   />
070 *
071 * ※ 6.4.3.0 (2016/02/05) disposition 追加
072 *    以前は、inline 固定でしたが、引数で指定できるようにします。
073 *
074 * ●使用例
075 *       <og:forward
076 *          page          = "転送先URLを指定します(必須)。"
077 *          dbkeys        = "DBキーをCSV形式でセットします。"
078 *          keys          = "キーを CSV形式でセットします。"
079 *          vals          = "キーに対応する値を CSV形式でセットします。"
080 *          scope         = "キャッシュする場合のスコープ(request,page,session,application)を指定します(初期値:session)。"
081 *          gamenId       = "gamenId 属性を登録します。"
082 *          useRedirect   = "useRedirect 属性を登録します。"
083 *          filename      = "ファイル転送時にファイル名を指定する場合に設定します。"
084 *          target        = "taregt 属性を登録します。"
085 *          noTransition  = "実際にforwardせずに、id="forwardUrl"属性のbody部分に遷移先のURLを出力します。(画面遷移なしモード時に使用します)"
086 *       />
087 *
088 * @og.group 画面制御
089 *
090 * @version  4.0
091 * @author       Kazuhiko Hasegawa
092 * @since    JDK5.0,
093 */
094public class ForwardTag extends CommonTagSupport {
095        /** このプログラムのVERSION文字列を設定します。   {@value} */
096        private static final String VERSION = "7.1.0.0 (2020/01/20)" ;
097        private static final long serialVersionUID = 710020200120L ;
098
099        // 7.2.9.4 (2020/11/20) PMD:Private field 'XXXX' could be made final; it is only initialized in the declaration or constructor.
100//      private static final long urlCheckTime          = 1000*60*60*24;                                                // 5.10.11.0 (2019/05/03)
101        private static final long URL_CHECK_TIME        = 1000*60*60*24;                                                // 7.3.0.0 (2021/01/06)
102        private final String urlCheckCrypt                      = HybsSystem.sys( "URL_CHECK_CRYPT" );
103
104        private transient DBTableModel  table   ;
105        private String          tableId         = HybsSystem.TBL_MDL_KEY;
106        private String          page            ;
107        private String          keys            ;
108        private String          dbkeys          ;
109        private String[]        vals            ;
110        private String          gamenId         ;                                               // 3.5.4.9 (2004/02/25) 追加
111        private boolean         useRedirect ;                                           // 3.5.6.6 (2004/08/23) 追加
112        private String          contentType     ;                                               // 7.1.0.0 (2020/01/20) 追加
113        private String          target          ;                                               // 3.8.0.4 (2005/08/08) 追加
114        private String          filename        ;                                               // 4.0.0   (2005/11/30) 追加
115        private String          disposition     = HybsSystem.sys( "CONTENT_DISPOSITION" );              // 6.4.3.0 (2016/02/05) 追加
116        private boolean         noTransition;                                           // 4.3.3.0 (2008/10/01) 追加
117        private boolean         useAjaxSubmit   ;                                       // 4.3.8.0 (2009/08/01) 追加
118        private String          redirectEncode  ;                                       // 5.6.5.0 (2013/06/07) 追加
119        // urlCheck関係 5.10.11.0 (2019/05/03) 追加
120        private boolean         useURLCheck             = HybsSystem.sysBool( "LINK_URL_CHECK" );
121//      private long            urlCheckTime    = 1000*60*60*24;                                                        // 5.10.11.0 (2019/05/03)
122//      private String          urlCheckCrypt   = HybsSystem.sys( "URL_CHECK_CRYPT" );
123        private boolean         useForceEnc     ;                                               // 5.10.15.3 (2019/09/27) 強制URLエンコード用
124
125        /**
126         * デフォルトコンストラクター
127         *
128         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
129         */
130        public ForwardTag() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
131
132        /**
133         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
134         *
135         * @og.rev 2.1.0.0 (2002/10/11) 戻り値の先頭の "?" を追加しないように変更。
136         * @og.rev 3.0.1.3 (2003/03/11) 直接転送した場合の整合性を取る為の対応。
137         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
138         * @og.rev 3.1.2.0 (2003/04/07) ソースコード中の固定値を、定義ファイルを使用するように変更する。
139         * @og.rev 3.5.4.9 (2004/02/25) gamenId を指定して、フォワードできるようにします。
140         * @og.rev 3.5.6.6 (2004/08/23) useRedirect 属性を追加します。
141         * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性を追加します。
142         * @og.rev 4.3.7.1 (2009/06/08) target属性に絶対パス及び"_"で始まる予約語を指定できるようにします。
143         * @og.rev 4.3.8.0 (2009/08/01) useAjaxSubmit対応、noTransition値取得メソッド名変更
144         * @og.rev 5.0.0.4 (2009/10/01) 画面遷移なし登録で戻った際に最終行が選択されるバグを修正
145         * @og.rev 5.1.3.0 (2010/02/01) noTransition、ajaxSubmitのコントロールは、requestで行う。
146         * @og.rev 5.1.6.0 (2010/05/01) IE以外は、MIMEエンコードする。(RFC2231に従う)
147         * @og.rev 5.1.7.0 (2010/06/01) 画面IDをパラメーターに付加する。
148         * @og.rev 5.1.7.0 (2010/06/01) 遷移先がJSP以外の場合は、フォワードページのキャッシュをしない。
149         * @og.rev 5.1.8.0 (2010/07/01) httpが指定されていた場合に、自身の画面IDが付加されるバグを修正
150         * @og.rev 5.3.8.0 (2011/08/01) ファイル名指定でIEの場合、URLエンコードすると途中で切れるため(IE7のバグ)、Shift_JIS(WIndows-31J)で直接指定する。
151         * @og.rev 5.6.5.0 (2013/06/07) redirectEncode 属性を追加します。
152         * @og.rev 5.7.4.1 (2014/03/14) 日本語ファイル名が正しく処理できない件を修正(IE11のMSIE関連)
153         * @og.rev 6.0.2.5 (2014/10/31) debug="true" を設定したときは、forward も sendRedirect も行わない。
154         * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応
155         * @og.rev 6.4.0.2 (2015/12/11) 飛び先の画面が見つからない(アクセス権がない)場合、転送先URL を null にする。
156         * @og.rev 6.9.0.0 (2018/01/31) Windows10 の Edge で、ファイルの文字化け対応(FileDownload servletと同じ対応を入れます)。
157         * @og.rev 6.9.8.0 (2018/05/28) debug="true" 時は、画面遷移は行わない。
158         * @og.rev 5.10.11.0 (2019/05/03) URLチェック対応を追加
159         * @og.rev 7.1.0.0 (2020/01/20) contentType 追加。
160         *
161         * @return      後続処理の指示
162         */
163        @Override
164        public int doEndTag() {
165                debugPrint();                                                                   // 4.0.0 (2005/02/28)
166                if( !useTag() ) { return EVAL_PAGE ; }                  // 6.3.4.0 (2015/08/01)
167
168                // noTransition = isNoTransitionRequest() || noTransition; // 4.3.3.0 (2008/10/01) 追加
169                noTransition  = isNoTransitionRequest();                // 5.1.3.0 (2010/02/01)
170                useAjaxSubmit = isAjaxSubmitRequest();                  // 5.1.3.0 (2010/02/01)
171
172                final String fwdUrl = makeGamenLink();                  // 3.5.4.9 (2004/02/25)
173                if( fwdUrl == null ) { return EVAL_PAGE ; }             // 6.4.0.2 (2015/12/11)
174
175                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid declaring a variable if it is unreferenced before a possible exit point.
176                final String urlEnc = getUrlEncode();
177                final HttpServletResponse response = (HttpServletResponse)pageContext.getResponse();
178                try {
179                        String url = response.encodeRedirectURL( fwdUrl );      // 3.5.4.9 (2004/02/25)
180                        // 5.1.7.0 (2010/06/01) 画面IDをパラメーターに付加する。
181                        // 5.1.8.0 (2010/07/01) httpが指定されていた場合に、自身の画面IDが付加されるバグを修正
182                        // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
183                        if( filename == null ) {
184                                if( !page.startsWith( "http" ) && page.endsWith( ".jsp" ) ) {
185                                        if( keys == null || keys.isEmpty() || ( "," + keys + "," ).indexOf( ",GAMENID," ) < 0 ) {
186                                                if( gamenId != null && gamenId.length() > 0 ) {
187                                                        url = XHTMLTag.addUrlEncode( url, "GAMENID=" + gamenId );
188                                                }
189                                                // useRedirect=trueでGAMENIDを指定せず、../GF9100/index.jsp等と書かれている場合の対応
190                                                else if( !useRedirect ) {
191                                                        url = XHTMLTag.addUrlEncode( url, "GAMENID=" + getGUIInfoAttri( "KEY" ) );
192                                                }
193                                        }
194                                }
195                        }
196                        else {
197                                final String newFilename        = filename;
198                                final String newFilenameEnc     = StringUtil.urlEncode( newFilename );          // 5.9.29.0 (2018/02/02)
199
200                                // 5.1.6.0 (2010/05/01) IE以外は、MIMEエンコードする。(RFC2231に従う)
201                                // 5.7.4.1 (2014/03/14) 日本語ファイル名が正しく処理できない件を修正(IE11のMSIE関連)
202                                // 条件を反転させた上でIE11対応を行う
203                                final String reqHeader = ((HttpServletRequest)pageContext.getRequest()).getHeader( "User-Agent" );
204//                              if( reqHeader.indexOf( "MSIE" ) >= 0 || reqHeader.indexOf( "Trident" ) >= 0 ) {
205                                if( reqHeader.indexOf( "MSIE" ) >= 0 || reqHeader.indexOf( "Trident" ) >= 0 || reqHeader.indexOf( "Edge" ) >= 0 ) {             // 6.9.0.0 (2018/01/31)
206                                        filename = new String( filename.getBytes("Windows-31J"), "ISO-8859-1" );
207                                }
208                                else {
209                                        filename = MimeUtility.encodeWord( filename, "UTF-8", "B" );
210                                }
211
212//                              response.setHeader( "Content-Disposition",disposition + "; filename=\"" + filename + "\"" );            // 6.4.3.0 (2016/02/05)
213                                response.setHeader( "Content-disposition",disposition + "; filename=\"" + newFilename
214                                                + "\"; filename*=UTF-8''" + newFilenameEnc );                                                                                                   // 5.9.29.0 (2018/02/02) RFC6266方式を併記
215                        }
216
217                        // 3.5.6.6 (2004/08/23) useRedirect 属性を追加
218                        String url2 = XHTMLTag.addUrlEncode( url , urlEnc );
219                        // 4.3.3.0 (2008/10/01) 追加
220                        // if( noTransition ) {
221                        if( noTransition || useAjaxSubmit ) { // 4.3.8.0 (2009/08/01) useAjaxSubmitと共用
222                                // 5.0.0.4 (2009/10/01)
223                                if( noTransition ) {
224                                        final int selRow = nval( getRequestValue( "SEL_ROW" ),-1 );
225                                        if( selRow > 0 ) {
226                                                url2 = XHTMLTag.addUrlEncode( url2, "SEL_ROW=" + selRow );
227                                        }
228                                }
229                                if( useURLCheck ) { // 5.10.11.0 (2019/05/03) useURLCheck追加
230                                        url2 = addURLCheck(url2);
231                                }
232                                // 6.9.8.0 (2018/05/28) debug="true" 時は、画面遷移は行わない。
233                                final String script = "<div id=\"noTransitionUrl\">" + url2 + "</div>" +
234                                                                          "<div id=\"noTransitionTarget\">" + target + "</div>" ;
235
236//                              jspPrint( "<div id=\"noTransitionUrl\">" + url2 + "</div>" );
237//                              jspPrint( "<div id=\"noTransitionTarget\">" + target + "</div>" );
238                                if( isDebug() ) {
239                                        final String debugMsg = "<pre>debug=\"true\" 時には、画面遷移を行いません。" + CR
240                                                                                        + " noTransition=" + noTransition + " , useAjaxSubmit=" + useAjaxSubmit + CR
241                                                                                        + " URL=" + url2 + CR
242                                                                                        + "</pre>" + CR;
243                                        jspPrint( debugMsg );
244                                }
245                                else {
246                                        jspPrint( script );
247                                }
248                        }
249                        // 3.8.0.4 (2005/08/08) target 属性を追加します。
250                        else if( target != null && target.length() > 0 ) {
251                                // 4.3.7.1 (2009/06/08)
252                                String src = null;
253                                if( useURLCheck ) { // 5.10.11.0 (2019/05/03) useURLCheck追加
254                                        url2 = addURLCheck(url2);
255                                }
256
257                                if( target.startsWith( "_b" ) ) { // "_blank"
258                                        src = "window.open(\"" + url2 + "\", \"_blank\") ";
259                                }
260                                else {
261                                        String frameTop = "";
262                                        if( target.indexOf('.') < 0 ) { frameTop = "top."; }
263                                        src = frameTop + target + ".location.href=\"" + url2 + "\"" + CR;
264                                }
265                                // 8.1.0.0 (2021/12/28) HTML5 準拠に見直し(<script> type属性削除)
266//                              final String script = "<script type=\"text/javascript\" ><!-- " + CR
267                                final String script = "<script><!-- " + CR
268                                                                + src + CR
269                                                                + "// --></script>" ;
270                                // 6.9.8.0 (2018/05/28) debug="true" 時は、画面遷移は行わない。
271                                if( isDebug() ) {
272                                        final String debugMsg = "<pre>debug=\"true\" 時には、画面遷移を行いません。" + CR
273                                                                                        + " target=" + target + CR
274                                                                                        + " src=" + src + CR
275                                                                                        + "</pre>" + CR;
276                                        jspPrint( debugMsg );
277                                }
278                                else {
279                                        jspPrint( script );
280                                }
281                        }
282                        else if( useRedirect ) {
283                                if( useURLCheck ) { // 5.10.11.0 (2019/05/03) useURLCheck追加
284                                        url2 = addURLCheck(url2);
285                                }
286
287                                // 5.6.5.0 (2013/06/07) redirectEncode 属性追加
288                                if( redirectEncode != null ) {
289                                        url2 = new String( url2.getBytes( redirectEncode ), "ISO-8859-1" );
290                                }
291
292                                // 6.0.2.5 (2014/10/31) debug="true" を設定したときは、forward も sendRedirect も行わない。
293                                if( isDebug() ) {
294                                        final String debugMsg = "<pre>debug=\"true\" 時には、forward も sendRedirect も行いません。"
295                                                                                        + CR
296                                                                                        + "Redirect URL=" + url2 + CR
297                                                                                        + "</pre>" + CR;
298                                        jspPrint( debugMsg );
299                                }
300                                else {
301                                        // 7.1.0.0 (2020/01/20) contentType 追加。例)"text/plain; charset=UTF-8"
302                                        if( contentType != null ) {
303                                                response.setContentType( contentType );
304                                        }
305                                        response.sendRedirect( url2 );
306                                }
307                        }
308                        else {
309                                // 6.0.2.5 (2014/10/31) debug="true" を設定したときは、forward も sendRedirect も行わない。
310                                if( isDebug() ) {
311                                        final String debugMsg = "<pre>debug=\"true\" 時には、forward も sendRedirect も行いません。"
312                                                                                        + CR
313                                                                                        + "Forward URL=" + url2  + CR
314                                                                                        + "</pre>" + CR;
315                                        jspPrint( debugMsg );
316                                }
317                                else {
318                                        pageContext.forward( url2 );
319                                }
320                        }
321                } catch( final IOException ex ) {
322                        final String errMsg = "フォワード/リダイレクトでIOエラーが発生しました。"
323                                                                + CR
324                                                                + fwdUrl + "?" + urlEnc ;
325                        throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
326                } catch( final ServletException ex) {
327                        final String errMsg = "フォワード/リダイレクトでServletエラーが発生しました。"
328                                                                + CR
329                                                                + fwdUrl + "?" + urlEnc ;
330                        throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
331                }
332
333                // 3.0.1.3 (2003/03/11) forward で直接転送した場合の整合性を取る為の対応。
334                // 5.1.7.0 (2010/06/01) 遷移先がJSP以外の場合は、フォワードページのキャッシュをしない。
335                // 6.9.8.0 (2018/05/28) FindBugs:null でないことがわかっている値の冗長な null チェック
336//              if( fwdUrl != null && fwdUrl.endsWith( ".jsp" ) ) {
337                if( fwdUrl.endsWith( ".jsp" ) ) {                                                               // fwdUrl は、nullチェック済み
338                        setSessionAttribute( HybsSystem.FORWARD_PAGE_KEY, fwdUrl );     // 3.5.4.9 (2004/02/25)
339                }
340
341                return SKIP_PAGE ;              // ページの残りの処理を行わない。
342        }
343
344        /**
345         * タグリブオブジェクトをリリースします。
346         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
347         *
348         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
349         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
350         * @og.rev 3.5.4.9 (2004/02/25) 画面ID属性(gamenId)を追加
351         * @og.rev 3.8.5.0 (2006/03/06) filename 属性を追加します。
352         * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性を追加します。
353         * @og.rev 5.6.5.0 (2013/06/07) redirectEncode 属性を追加します。
354         * @og.rev 6.4.3.0 (2016/02/05) disposition属性、新規追加。
355         * @og.rev 5.10.11.0 (2019/05/03) urlCheck対応
356         * @og.rev 5.10.15.3 (2019/09/27) forceEnc追加
357         * @og.rev 7.1.0.0 (2020/01/20) contentType 追加。
358         */
359        @Override
360        protected void release2() {
361                super.release2();
362                tableId                 = HybsSystem.TBL_MDL_KEY;
363                page                    = null;
364                keys                    = null;
365                dbkeys                  = null;
366                vals                    = null;
367                table                   = null;
368                gamenId                 = null;
369                useRedirect             = false;                                // 3.5.6.6 (2004/08/23) 追加
370                contentType     = null;                                 // 7.1.0.0 (2020/01/20) 追加
371                target                  = null;                                 // 3.8.0.4 (2005/08/08) 追加
372                filename                = null;
373                disposition             = HybsSystem.sys( "CONTENT_DISPOSITION" );              // 6.4.3.0 (2016/02/05) 追加
374                noTransition    = false;                                // 4.3.3.0 (2008/10/01) 追加
375                useAjaxSubmit   = false;                                // 4.3.8.0 (2009/08/01) 追加
376                redirectEncode  = null;                                 // 5.6.5.0 (2013/06/07) 追加
377                useURLCheck             = HybsSystem.sysBool( "LINK_URL_CHECK" ); // 5.10.11.0 (2019/05/03)
378                useForceEnc             = false;                                // 5.10.15.3 (2019/09/27)
379        }
380
381        /**
382         * keys 属性 を元に、request情報より values の値を取り込む。
383         *
384         * keys属性は キー情報がCSV形式になっている為,ばらして
385         * values属性の配列に一つづつ設定していきます。
386         *
387         * @og.rev 3.1.7.0 (2003/05/02) 戻るボタン用のBACK_GAMENID を、引数に追加します。
388         * @og.rev 3.1.8.0 (2003/05/16) 戻るボタン用のBACK_GAMENID の自動登録を廃止します。
389         * @og.rev 4.0.0.0 (2005/01/31) getParameterRows() を使用するように変更
390         * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
391         * @og.rev 5.10.15.3 (2019/09/27) forceEnc追加
392         *
393         * @return      URLエンコードされた文字列
394         */
395        private String getUrlEncode() {
396                final String[] dbkey = StringUtil.csv2Array( dbkeys );
397                final String[] key   = StringUtil.csv2Array( keys );
398
399                final int dbCount = dbkey.length;
400                final int count   = key.length  ;
401
402                String[] allKey = new String[ dbCount + count ];
403                String[] allval = new String[ dbCount + count ];
404
405                final int[] rowNo = getParameterRows();         // 4.0.0 (2005/01/31)
406                if( dbCount > 0 && dbkey[0] != null && dbkey[0].length() > 0 && rowNo.length > 0 ) {
407                        table = (DBTableModel)getObject( tableId );
408                        if( table != null ) {
409                                for( int i=0; i<dbCount; i++ ) {
410                                        allKey[i] = dbkey[i];
411                                        allval[i] = table.getValue(rowNo[0],table.getColumnNo( dbkey[i] ));
412                                }
413                        }
414                }
415
416                // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
417                if( count > 0 && vals != null && vals.length == count ) {
418                        for( int i=0; i<count; i++ ) {
419                                allKey[i+dbCount] = key[i];
420                                allval[i+dbCount] = vals[i];
421                        }
422                }
423
424//              return XHTMLTag.urlEncode( allKey,allval );
425                return XHTMLTag.urlEncode( allKey,allval,"&",useForceEnc );             // 5.10.15.3 (2019/09/27)
426        }
427
428        /**
429         * 【TAG】転送先URLを指定します。
430         *
431         * @og.tag 転送先URLを指定します。
432         *
433         * @param       url 転送先URL
434         */
435        public void setPage( final String url ) {
436                page = getRequestParameter( url );
437        }
438
439        /**
440         * 【TAG】DBキーをCSV形式でセットします。
441         *
442         * @og.tag
443         * URI の引数にセットするキーを CSV形式でセットします。
444         * ここの指定は,DBTableModel 上のデータを取り込みます。
445         *
446         * @param       key DBキー(CSV形式)
447         */
448        public void setDbkeys( final String key ) {
449                dbkeys = getRequestParameter( key ) ;
450        }
451
452        /**
453         * 【TAG】キーを CSV形式でセットします。
454         *
455         * @og.tag
456         * URI の引数にセットするキーを CSV形式でセットします。
457         *
458         * @param       key キー(CSV形式)
459         */
460        public void setKeys( final String key ) {
461                keys = getRequestParameter( key ) ;
462        }
463
464        /**
465         * 【TAG】キーに対応する値を CSV形式でセットします。
466         *
467         * @og.tag
468         * URI の引数にセットする値を CSV形式でセットします。
469         * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。
470         * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。
471         *
472         * @og.rev 3.5.6.2 (2004/07/05) CommonTagSupport#getCSVParameter を使用
473         *
474         * @param       val 値(CSV形式)
475         */
476        public void setVals( final String val ) {
477                vals = getCSVParameter( val );
478
479                // 先に分解しないとデータ自身にカンマを持っている場合に分解をミスる。
480        }
481
482        /**
483         * 画面IDとpage から、フォワードするURLを作成します。
484         * page が null の場合は、index.jsp に転送されます。
485         *
486         * @og.rev 3.5.4.9 (2004/02/25) 新規追加
487         * @og.rev 3.5.5.0 (2004/03/12) URLを求めるのに、GUIInfo#getRealAddress() を使用する。
488         * @og.rev 4.0.0.0 (2005/01/31) GUIInfoの実アドレスのパラメータを考慮する。
489         * @og.rev 6.4.0.2 (2015/12/11) 飛び先の画面が見つからない(アクセス権がない)場合、転送先URL を null にする。
490         *
491         * @return      フォワードするURL(転送先URL)
492         */
493        private String makeGamenLink() {
494                if( page == null ) { page = "index.jsp"; }
495
496                if( gamenId == null || gamenId.isEmpty() ) { return page; }
497
498                final GUIInfo guiInfo = getGUIInfo( gamenId );
499                if( guiInfo == null ) {                                 // 見つからない場合は、転送しない
500                        LogWriter.log( "Forward[" + gamenId + "]先にはアクセス不可です。" );
501                        return null;                                            // 6.4.0.2 (2015/12/11)
502                }
503
504                final String address = guiInfo.getRealAddress( page );
505                final String link    = getRequestParameter( address );
506
507                // Ver 4.0.0 (2007/06/12) gamenId を使用する場合は、useRedirect = true をセット
508                useRedirect = true;
509                return link;
510        }
511
512        /**
513         * 【TAG】画面ID を指定します。
514         *
515         * @og.tag
516         * gamenId 属性は、画面IDをキーに、実アドレスを求めるのに使用します。
517         * 画面IDが指定された場合は、実アドレスに変換する。指定されない場合は、
518         * page 属性をそのままリダイレクトアドレスとします。
519         * gamenId を指定した場合は、このuseRedirect属性に関係なく、Redirect されます。
520         *
521         * @og.rev 3.5.4.9 (2004/02/25) 新規追加
522         *
523         * @param   id 画面ID
524         * @see         #setUseRedirect( String )
525         */
526        public void setGamenId( final String id ) {
527                gamenId = nval( getRequestParameter( id ),gamenId );
528        }
529
530        /**
531         * 【TAG】response.sendRedirect するかどうか[true/false]を指定します(初期値:false)。
532         *
533         * @og.tag
534         * useRedirect 属性は、URLの転送方式を指定できます。
535         * 通常は、pageContext.forward しますが、この属性に true を
536         * 設定すると、response.sendRedirect します。
537         * gamenId を指定した場合は、この属性に関係なく、Redirect されます。
538         * 初期値は、false (forward) です。
539         *
540         * @og.rev 3.5.6.6 (2004/08/23) 新規追加
541         *
542         * @param   flag リダイレクト転送か [true:redirect/false:forwrd]
543         * @see         #setGamenId( String )
544         */
545        public void setUseRedirect( final String flag ) {
546                useRedirect = nval( getRequestParameter( flag ),useRedirect );
547        }
548
549        /**
550         * 【TAG】response.sendRedirect する場合、ContentType を設定します(初期値:未指定)。
551         *
552         * @og.tag
553         * useRedirect="true" の場合のみ、この属性は有効になります。
554         * 例)contentType="text/plain; charset=UTF-8"
555         * 初期値は、未指定です。
556         *
557         * @og.rev 7.1.0.0 (2020/01/20) contentType 追加。
558         *
559         * @param   type ContentType属性
560         * @see         #setUseRedirect( String )
561         */
562        public void setContentType( final String type ) {
563                contentType = nval( getRequestParameter( type ),contentType );
564        }
565
566        /**
567         * 【TAG】サブミット先の文書を表示させるフレーム、またはウィンドウの名前を指定します。
568         *
569         * @og.tag サブミット先のフレーム名(ターゲット属性)を設定します。
570         *
571         * @og.rev 3.8.0.4 (2005/08/08) 新規追加
572         *
573         * @param       name フレーム名(ターゲット属性)
574         */
575        public void setTarget( final String name ) {
576                target = nval( getRequestParameter( name ),target );
577        }
578
579        /**
580         * 【TAG】ファイル転送時にファイル名の別名を指定します(初期値:null)。
581         *
582         * @og.tag
583         * ファイルを転送する場合に、オープンさせるファイル名を指定します。
584         * 指定しない場合は、フォラード前に呼び出されたアドレスがそのまま使用されます。
585         *
586         * ※ useRedirect="true"時(つまり、リダイレクトする場合)は、ファイル名の指定が
587         * できません。(少なくとも私の知識では出来ませんでした。)
588         *
589         * @param   name ファイル名
590         */
591        public void setFilename( final String name ) {
592                filename = nval( getRequestParameter( name ),filename );
593        }
594
595        /**
596         * 【TAG】ファイルダウンロードさせる場合に、Content-Disposition に設定する値
597         *              (初期値:CONTENT_DISPOSITION[={@og.value SystemData#CONTENT_DISPOSITION}])。
598         *
599         * @og.tag
600         * inline(そのまま開く) を指定すると、PDF などは直接ダウンロードが始まります。
601         * attachment(ダウンロードダイアログを表示する) を指定すると、保存のダイアログを表示しますが
602         * EXCEL などの場合、inline にしても、ダイアログが表示され、開くをクリックしても
603         * ダウンロードが始まらなかったり、EXCELが開いたあと、ブラウザの操作が出来なくなったり、
604         * よくわからないため、選択できるようにします。
605         * (初期値:システム定数のCONTENT_DISPOSITION[={@og.value SystemData#CONTENT_DISPOSITION}])。
606         *
607         * @og.rev 6.4.3.0 (2016/02/05) disposition属性、新規追加。
608         *
609         * @param   dispos Content-Dispositionに設定する値(inline/attachment)
610         */
611        public void setDisposition( final String dispos ) {
612                final String temp = nval( getRequestParameter( dispos ),disposition );
613
614                if( "inline".equals( temp ) || "attachment".equals( temp ) ) {
615                        disposition = temp;
616                }
617                else {
618                        final String errMsg = "disposition 属性は、[inline/attachment] から、指定してください。"
619                                                                + " disposition=[" + dispos + "]" + CR ;
620                        throw new HybsSystemException( errMsg );
621                }
622        }
623
624        /**
625         * 【TAG】(通常は使いません)画面遷移を行わない形式の登録方法を使用するかを指定します。
626         *
627         * @og.tag
628         * 画面遷移なしの登録を行うかどうかを指定します。
629         * trueが指定された場合、forwardタグでは、実際の画面遷移は行わずに、forward先の
630         * URLを<div id="noTransitionUrl">[URL]</div>の形でHTMLとして出力し、JavaScript側で
631         * 実際の画面遷移を発生させます。target属性は<div id="noTransitionTarget">[TARGET]</div>で
632         * 出力されます。
633         *
634         * この値は、og:headタグで設定値、または前画面からの値を継承するため、通常、この属性ではセットしません。
635         *
636         * @og.rev 4.3.3.0 (2008/10/01) 新規追加
637         * @og.rev 5.1.3.0 (2010/02/01) noTransition、ajaxSubmitのコントロールは、requestで行う。
638         *
639         * @param   noTrnstn 画面遷移を行わない登録か [true:画面遷移を伴わない/false:伴う]
640         */
641        public void setNoTransition( final String noTrnstn ) {
642                setNoTransitionRequest( nval( getRequestParameter( noTrnstn ), isNoTransitionRequest() ) );
643        }
644
645        /**
646         * 【TAG】(通常は使いません)ajaxを利用したsubmitを利用するかどうか[true:利用する/false:利用しない]を指定します。
647         *
648         * @og.tag
649         * ajaxを利用したSubmit処理を行うかどうかを指定します。
650         * setNoTransitionをtrueにした場合と同様の処理を行います。
651         * (forwardせずにURLをDIVタグで出力する)
652         *
653         * この値は、og:headタグで設定値、または前画面からの値を継承するため、通常、この属性ではセットしません。
654         *
655         * @og.rev 4.3.8.0 (2009/08/01) 新規追加
656         * @og.rev 5.1.3.0 (2010/02/01) noTransition、ajaxSubmitのコントロールは、requestで行う。
657         *
658         * @param   ajaxSubmit ajaxを利用したsubmitを利用するか [true:利用する/false:利用しない]
659         */
660        public void setUseAjaxSubmit( final String ajaxSubmit ) {
661                setAjaxSubmitRequest( nval( getRequestParameter( ajaxSubmit ), isAjaxSubmitRequest() ) );
662        }
663
664        /**
665         * 【TAG】(通常は使いません)useRedirect=true時に 日本語を含む転送先(page)をバイナリ変換するときのコード名[UTF-8/Windows-31J]など(初期値:null)。
666         *
667         * @og.tag
668         * 日本語ファイル名を持つ URL を useRedirect で転送する場合に、転送先(page)をバイナリ変換しないと、転送できないケースがあります。
669         * このあたりは、ブラウザにも依存するので、既存の処理に影響しない様に、このパラメータを使用する場合のみ
670         * 処理を実行します。
671         * IEでの日本語ファイル転送で、うまくいかない場合の、暫定処置です。
672         * IEの場合は、redirectEncode="UTF-8" で、日本語ファイルを転送できます。
673         * ただし、useRedirect=true時に filename 属性によるファイル名の書き換え処理はできませんので、ご注意ください。
674         * 初期値は、null で、バイナリエンコードしません。(互換性ありの状態です。)
675         *
676         * @og.rev 5.6.5.0 (2013/06/07) 新規追加
677         *
678         * @param   redEnc 転送先(page)の変換文字コード名 (UTF-8/Windows-31Jなど)
679         */
680        public void setRedirectEncode( final String redEnc ) {
681                redirectEncode = nval( getRequestParameter( redEnc ), redirectEncode );
682        }
683
684        /**
685         * 【TAG】リンクアドレスにURLチェック用の確認キーを付加するかどうか[true/false]を指定します。
686         *
687         * @og.tag
688         * この属性は、URLCheckFilter(org.opengion.hayabusa.filter.URLCheckFilter)と合わせて使用します。
689         * trueが指定された場合、リンクURLのパラメーターに、URL確認用のパラメーターが出力されます。
690         * このパラメーターを、URLCheckFilterが復号化し、正式なアクセスであるかどうかの判定を行います。
691         *
692         * 初期値は、 システムリソースのLINK_URL_CHECK です。
693         *
694         * @og.rev 5.10.11.0 (2019/05/03) 新規追加
695         *
696         * @param       flag 暗号化するかかどうか [true:暗号化する/false:しない]
697         * @see org.opengion.hayabusa.filter.URLCheckFilter
698         */
699        public void setUseURLCheck( final String flag ) {
700                useURLCheck = nval( getRequestParameter( flag ),useURLCheck );
701        }
702
703        /**
704         * 【TAG】valsの値が[で開始している場合でもURLEncodeを通すかを設定します(初期値:false)。
705         *
706         * @og.tag
707         * テーブルモデルの値の変換のため、通常は先頭が[の場合はエンコードがかかりません。
708         * 強制的にかける場合にtrueにします。
709         *
710         * @og.rev 5.10.15.3 (2019/09/27) forceEnc追加
711         *
712         * @param flg URLEncodeを通す場合は、trueをセット
713         */
714        public void setForceEnc( final String flg ) {
715                useForceEnc = nval( getRequestParameter( flg ), useForceEnc );
716        }
717
718        /**
719         * urlCheckのパラメータを付加します。
720         *
721         * @og.rev 5.10.11.0 (2019/05/03) 新規追加
722         *
723         * @param url 元のアドレス
724         * @return urlCheckを付加したアドレス
725         */
726        private String addURLCheck( final String url ) {
727                HybsCryptography criptCls = null;
728                if( urlCheckCrypt != null && urlCheckCrypt.length() > 0 ){
729                        criptCls = new HybsCryptography( urlCheckCrypt );
730                }
731//              return XHTMLTag.addURLCheckKey( url, HybsSystem.URL_CHECK_KEY, getUser().getUserID(), System.currentTimeMillis() + urlCheckTime, criptCls );
732                return XHTMLTag.addURLCheckKey( url, HybsSystem.URL_CHECK_KEY, getUser().getUserID(), System.currentTimeMillis() + URL_CHECK_TIME, criptCls );  // 7.3.0.0 (2021/01/06)
733        }
734
735        /**
736         * このオブジェクトの文字列表現を返します。
737         * 基本的にデバッグ目的に使用します。
738         *
739         * @return このクラスの文字列表現
740         * @og.rtnNotNull
741         */
742        @Override
743        public String toString() {
744                return ToString.title( this.getClass().getName() )
745                                .println( "VERSION"                     ,VERSION                )
746                                .println( "tableId"                     ,tableId                )
747                                .println( "page"                        ,page                   )
748                                .println( "keys"                        ,keys                   )
749                                .println( "dbkeys"                      ,dbkeys                 )
750                                .println( "vals"                        ,vals                   )
751                                .println( "gamenId"                     ,gamenId                )
752                                .println( "useRedirect"         ,useRedirect    )
753                                .println( "target"                      ,target                 )
754                                .println( "filename"            ,filename               )
755                                .println( "disposition"         ,disposition    )
756                                .println( "noTransition"        ,noTransition   )
757                                .println( "useAjaxSubmit"       ,useAjaxSubmit  )
758                                .println( "redirectEncode"      ,redirectEncode )
759                                .println( "useURLCheck"         ,useURLCheck    )               // 5.10.11.0 (2019/05/03)
760                                .println( "Other..."            ,getAttributes().getAttribute() )
761                                .fixForm().toString() ;
762        }
763}