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 org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.fukurou.system.LogWriter; 021import org.opengion.fukurou.system.HybsConst; // 6.4.5.2 (2016/05/06) 022import org.opengion.fukurou.util.FileUtil; // 6.4.5.2 (2016/05/06) 023import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 024import org.opengion.fukurou.util.StringUtil ; // 6.2.0.0 (2015/02/27) 025 026import static org.opengion.fukurou.util.StringUtil.nval; // 5.9.10.5 (2016/07/22) 027 028import jakarta.servlet.ServletRequest ; 029import jakarta.servlet.http.HttpServletRequest ; 030 031/** 032 * BODY部に記述されたエンジン固有の文字列({@XXXX}など)を、 033 * ユーザー情報のエンコーディングに変換するタグです。 034 * 035 * XML形式で 日本語コードのパースが、JSPエンジン(Tomcat)でサポート 036 * されるまでの、暫定的なタグです。 037 * なお、このタグの内部に存在するカスタムタグは、先に実行されるため 038 * 漢字コードは、変換されません。 039 * 040 * ※ 6.3.1.0 (2015/06/28) caseKey、caseVal、caseNN、caseNull、caseIf 属性追加 041 * 042 * @og.formSample 043 * ●形式:<og:text >・・・</og:text> 044 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します) 045 * 046 * ●Tag定義: 047 * <og:text 048 * value 【TAG】value 値に直接書かれたコードを出力します 049 * include 【TAG】動的にファイルを include します(初期値:null) 050 * usePrintOut 【TAG】デバッグ用に、value 値を System.out.println に 出力するかどうか(初期値:false) 6.9.3.0 (2018/03/26) 051 * useStop 【TAG】6.9.9.1 (2018/08/27) BODYを処理後に停止するかどうか[true/false]を指定します(初期値:false) 052 * xssCheck 【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true]) 053 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 054 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 055 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 056 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 057 * caseIf 【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 058 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 059 * > ... Body ... 060 * </og:text> 061 * 062 * ●使用例 063 * ・<og:text > 064 * <p>あいおえお:<input name="PN" value="{@PN}" /> </p> 065 * </og:text> 066 * ・<og:text value="あいうえお" /> 067 * 068 * 動的にファイルを include することが出来ます。 069 * ・<og:text include="{@query}.txt" /> 070 * 071 * @og.group 画面部品 072 * 073 * @version 4.0 074 * @author Kazuhiko Hasegawa 075 * @since JDK5.0, 076 */ 077public class TextTag extends CommonTagSupport { 078 /** このプログラムのVERSION文字列を設定します。 {@value} */ 079 private static final String VERSION = "7.0.1.3 (2018/11/12)" ; 080 private static final long serialVersionUID = 701320181112L ; 081 082 private String value ; 083 private boolean useInclude ; 084 private boolean usePrintOut ; // 6.9.3.0 (2018/03/26) 085 086 private boolean xssCheck = HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.9.10.5 (2016/07/22) XSS対策 087 088 // 6.9.9.1 (2018/08/27) BODYを処理後に停止するかどうかを指定します。 089 private boolean useStop ; // BODYを処理後に停止(true)するかどうか 090 091 /** 092 * デフォルトコンストラクター 093 * 094 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 095 */ 096 public TextTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 097 098 /** 099 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 100 * 101 * @og.rev 6.3.1.0 (2015/06/28) caseKey、caseVal、caseNN、caseNull、caseIf 属性追加 102 * 103 * @return 後続処理の指示( EVAL_BODY_BUFFERED ) 104 */ 105 @Override 106 public int doStartTag() { 107 // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 108 return useTag() && !useInclude && value == null 109 ? EVAL_BODY_BUFFERED // Body を評価する。( extends BodyTagSupport 時) 110 : SKIP_BODY ; // Body を評価しない 111 } 112 113 /** 114 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 115 * 116 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更 117 * @og.rev 3.0.0.0 (2002/12/25) StringUtil#changeString 廃止 118 * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。 119 * @og.rev 4.0.0.0 (2007/10/12) 処理中にエラーを発生させないようにしする。 120 * @og.rev 6.3.1.0 (2015/06/28) caseKey、caseVal、caseNN、caseNull、caseIf 属性追加 121 * @og.rev 5.9.10.5 (2016/07/22) XSS対策 122 * 123 * @return 後続処理の指示(SKIP_BODY) 124 */ 125 @Override 126 public int doAfterBody() { 127 // 6.3.1.0 (2015/06/28) caseKey、caseVal、caseNN、caseNull、caseIf 属性追加 128 // 4.0.0.0 (2007/10/12) 処理中にエラーを発生させない 129 try { 130 useXssCheck( xssCheck ); // 5.9.10.5 (2016/07/22) 131 value = getBodyString(); 132 } 133 catch( final HybsSystemException ex ) { // 主に、UserInfo が見つからない場合 134 value = getBodyContent().getString() ; 135 } 136 137 return SKIP_BODY ; 138 } 139 140 /** 141 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 142 * 143 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 144 * @og.rev 6.3.1.0 (2015/06/28) caseKey、caseVal、caseNN、caseNull、caseIf 属性追加 145 * @og.rev 6.9.0.2 (2018/02/13) debug="true" で、System.out.println( value ) を出します。 146 * @og.rev 6.9.3.0 (2018/03/26) debug="true" ではなく、専用属性の usePrintOut で出力を制御します。 147 * @og.rev 6.9.9.1 (2018/08/27) useStop 属性を追加します。 148 * @og.rev 7.0.1.3 (2018/11/12) useStop 属性は、useTagが有効の場合のみ判定する。 149 * 150 * @return 後続処理の指示 151 */ 152 @Override 153 public int doEndTag() { 154 if( usePrintOut ) { 155 System.out.println( "TextTag=" + value ); // 6.9.3.0 (2018/03/26) 156 } 157 else { 158 debugPrint(); // 4.0.0 (2005/02/28) 159 if( useTag() ) { // 6.3.1.0 (2015/06/28) 160 jspPrint( value ); 161 } 162 else { 163 return EVAL_PAGE ; // 7.0.1.3 (2018/11/12) タグが使用されない場合は、useStop の判定は行わない。 164 } 165 } 166// return EVAL_PAGE ; 167 return useStop ? SKIP_PAGE : EVAL_PAGE ; 168 } 169 170 /** 171 * タグリブオブジェクトをリリースします。 172 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 173 * 174 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加 175 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 176 * @og.rev 5.9.10.5 (2016/07/22) xssCheck追加 177 * @og.rev 6.9.3.0 (2018/03/26) usePrintOut 新規追加 178 * @og.rev 6.9.9.1 (2018/08/27) useStop 属性を追加します。 179 * 180 */ 181 @Override 182 protected void release2() { 183 super.release2(); 184 value = null; 185 useInclude = false; 186 usePrintOut = false; // 6.9.3.0 (2018/03/26) 187 xssCheck = HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.9.10.5 (2016/07/22) 188 useStop = false; // 6.9.9.1 (2018/08/27) 189 } 190 191 /** 192 * 【TAG】value 値に設定します。 193 * 194 * @og.tag 195 * ここで、value に設定した場合は、BODY 部は無視されます。 196 * なお、このタグでは、エラー発生時でも継続して処理を続けられるようにします。 197 * error.jsp などのエラー処理画面で、このタグを使用するケースがある為です。 198 * 199 * <og:text value="あいうえお" /> 200 * 201 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更 202 * @og.rev 3.0.0.0 (2002/12/25) StringUtil#changeString 廃止 203 * @og.rev 4.0.0.0 (2005/12/31) エラー発生時でも異常終了させずに処理を続けます。 204 * 205 * @param val 設定値 206 */ 207 public void setValue( final String val ) { 208 if( !useInclude ) { 209 try { 210 value = getRequestParameter( val ); 211 } 212 catch( final HybsSystemException ex ) { 213 value = val ; 214 LogWriter.log( "val=" + val + " [" + ex.getMessage() + "]" ); 215 } 216 } 217 } 218 219 /** 220 * 【TAG】動的にファイルを include します。 221 * 222 * @og.tag 223 * 指定のファイル名は、自身のディレクトリからの相対パスで表されます。 224 * 225 * @og.rev 4.0.0.0 (2007/05/25) 新規追加 226 * @og.rev 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更 227 * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。 228 * 229 * @param file ファイル名 230 */ 231 public void setInclude( final String file ) { 232 useInclude = true; 233 234 final String relativePath = getRequestParameter( file ); 235 final String resourcePath = getContextRelativePath(getRequest(), relativePath); 236 final String realPath = HybsSystem.url2dir( resourcePath.substring(1) ); 237 238 // 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更 239 value = FileUtil.getValue( realPath , HybsConst.UTF_8 ); // 6.4.5.2 (2016/05/06) 240 } 241 242 /** 243 * 【TAG】デバッグ用に、value 値を System.out.println に 出力するかどうか[true/false]を設定します。 244 * 245 * @og.tag 246 * DOS窓に出力するので、サービス化していない場合のデバッグ用の機能です。 247 * Tomcat内のJSPで、繰返し処理を行っているような場合、処理時間が長い場合、HTMLとしての 248 * レスポンスは、すべての処理が完了するまで戻ってこないため、進捗状況がわかりません。 249 * そこで、DOS窓上に、System.out.printlnとして、value値を出力します。 250 * このフラグを true にセットした場合には、debugも、useTag(タグの使用)も効果は無く、 251 * value値も JSPには表示しません。 252 * 初期値は、(false:出力しない) です。 253 * 254 * @og.rev 6.9.3.0 (2018/03/26) usePrintOut 新規追加 255 * 256 * @param flag System.out.println に 出力するかどうか [true:する/false:しない] 257 */ 258 public void setUsePrintOut( final String flag ) { 259 usePrintOut = nval( getRequestParameter( flag ),usePrintOut ); 260 } 261 262 /** 263 * 【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します 264 * (初期値:USE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。 265 * 266 * @og.tag 267 * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。 268 * (><) が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。 269 * (初期値:システム定数のUSE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。 270 * 271 * @og.rev 5.9.10.5 (2016/07/22) xssCheck 272 * 273 * @param flag XSSチェック [true:する/false:しない] 274 * @see org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK 275 */ 276 public void setXssCheck( final String flag ) { 277 xssCheck = nval( getRequestParameter( flag ),xssCheck ); 278 } 279 280 /** 281 * 【TAG】BODYを処理後に停止するかどうか[true/false]を指定します(初期値:false)。 282 * 283 * @og.tag 284 * true を指定すると、以下の処理は、行われません。 285 * 初期値は、停止しない ("false") 286 * 287 * @og.rev 6.9.9.1 (2018/08/27) useStop 属性を追加します。 288 * 289 * @param flag 処理後停止 [true:する/それ以外:しない] 290 */ 291 public void setUseStop( final String flag ) { 292 useStop = nval( getRequestParameter( flag ),useStop ); 293 } 294 295 /** 296 * このオブジェクトの文字列表現を返します。 297 * 基本的にデバッグ目的に使用します。 298 * 299 * @og.rev 6.9.0.2 (2018/02/13) useTag 属性の値も表示に加えます。 300 * 301 * @return このクラスの文字列表現 302 * @og.rtnNotNull 303 */ 304 @Override 305 public String toString() { 306 return ToString.title( this.getClass().getName() ) 307 .println( "VERSION" ,VERSION ) 308 .println( "useTag" ,useTag() ) // 6.9.0.2 (2018/02/13) 309 .println( "value" ,value ) 310 .println( "Other..." ,getAttributes().getAttribute() ) 311 .fixForm().toString() ; 312 } 313 314 /** 315 * 動的にファイルを include する為の、コンテキストパスを求めます。 316 * 317 * 指定のファイル名は、自身のディレクトリからの相対パスで表されます。 318 * 319 * @og.rev 4.0.0.0 (2007/05/25) 新規追加 320 * @og.rev 4.0.0.0 (2007/11/30) if の評価方法を変更します。 321 * 322 * @param request ServletRequestオブジェクト 323 * @param relativePath ファイル名 324 * 325 * @return コンテキストパス 326 */ 327 private String getContextRelativePath( final ServletRequest request,final String relativePath ) { 328 // 6.1.0.0 (2014/12/26) refactoring 329 if( StringUtil.startsChar( relativePath , '/' ) // 6.2.0.0 (2015/02/27) 1文字 String.startsWith 330 || !(request instanceof HttpServletRequest) ) { 331 return relativePath ; 332 } 333 334 final HttpServletRequest hrequest = (HttpServletRequest) request; 335 String uri = (String)request.getAttribute("jakarta.servlet.include.servlet_path"); 336 if( uri != null && uri.lastIndexOf('/') >= 0 ) { 337 final String pathInfo = (String)request.getAttribute("jakarta.servlet.include.path_info"); 338 if( pathInfo == null ) { 339 uri = uri.substring(0, uri.lastIndexOf('/')); 340 } 341 } 342 else { 343 uri = hrequest.getServletPath(); 344 if( uri.lastIndexOf('/') >= 0 ) { 345 uri = uri.substring(0, uri.lastIndexOf('/')); 346 } 347 } 348 return uri + '/' + relativePath; 349 } 350}