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 javax.servlet.ServletRequest ; 029import javax.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 = "6.9.9.1 (2018/08/27)" ; 080 private static final long serialVersionUID = 699120180827L ; 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 * 149 * @return 後続処理の指示 150 */ 151 @Override 152 public int doEndTag() { 153 if( usePrintOut ) { 154 System.out.println( "TextTag=" + value ); // 6.9.3.0 (2018/03/26) 155 } 156 else { 157 debugPrint(); // 4.0.0 (2005/02/28) 158 if( useTag() ) { // 6.3.1.0 (2015/06/28) 159 jspPrint( value ); 160 } 161 } 162// return EVAL_PAGE ; 163 return useStop ? SKIP_PAGE : EVAL_PAGE ; 164 } 165 166 /** 167 * タグリブオブジェクトをリリースします。 168 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 169 * 170 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加 171 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 172 * @og.rev 5.9.10.5 (2016/07/22) xssCheck追加 173 * @og.rev 6.9.3.0 (2018/03/26) usePrintOut 新規追加 174 * @og.rev 6.9.9.1 (2018/08/27) useStop 属性を追加します。 175 * 176 */ 177 @Override 178 protected void release2() { 179 super.release2(); 180 value = null; 181 useInclude = false; 182 usePrintOut = false; // 6.9.3.0 (2018/03/26) 183 xssCheck = HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.9.10.5 (2016/07/22) 184 useStop = false; // 6.9.9.1 (2018/08/27) 185 } 186 187 /** 188 * 【TAG】value 値に設定します。 189 * 190 * @og.tag 191 * ここで、value に設定した場合は、BODY 部は無視されます。 192 * なお、このタグでは、エラー発生時でも継続して処理を続けられるようにします。 193 * error.jsp などのエラー処理画面で、このタグを使用するケースがある為です。 194 * 195 * <og:text value="あいうえお" /> 196 * 197 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更 198 * @og.rev 3.0.0.0 (2002/12/25) StringUtil#changeString 廃止 199 * @og.rev 4.0.0.0 (2005/12/31) エラー発生時でも異常終了させずに処理を続けます。 200 * 201 * @param val 設定値 202 */ 203 public void setValue( final String val ) { 204 if( !useInclude ) { 205 try { 206 value = getRequestParameter( val ); 207 } 208 catch( final HybsSystemException ex ) { 209 value = val ; 210 LogWriter.log( "val=" + val + " [" + ex.getMessage() + "]" ); 211 } 212 } 213 } 214 215 /** 216 * 【TAG】動的にファイルを include します。 217 * 218 * @og.tag 219 * 指定のファイル名は、自身のディレクトリからの相対パスで表されます。 220 * 221 * @og.rev 4.0.0.0 (2007/05/25) 新規追加 222 * @og.rev 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更 223 * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。 224 * 225 * @param file ファイル名 226 */ 227 public void setInclude( final String file ) { 228 useInclude = true; 229 230 final String relativePath = getRequestParameter( file ); 231 final String resourcePath = getContextRelativePath(getRequest(), relativePath); 232 final String realPath = HybsSystem.url2dir( resourcePath.substring(1) ); 233 234 // 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更 235 value = FileUtil.getValue( realPath , HybsConst.UTF_8 ); // 6.4.5.2 (2016/05/06) 236 } 237 238 /** 239 * 【TAG】デバッグ用に、value 値を System.out.println に 出力するかどうか[true/false]を設定します。 240 * 241 * @og.tag 242 * DOS窓に出力するので、サービス化していない場合のデバッグ用の機能です。 243 * Tomcat内のJSPで、繰返し処理を行っているような場合、処理時間が長い場合、HTMLとしての 244 * レスポンスは、すべての処理が完了するまで戻ってこないため、進捗状況がわかりません。 245 * そこで、DOS窓上に、System.out.printlnとして、value値を出力します。 246 * このフラグを true にセットした場合には、debugも、useTag(タグの使用)も効果は無く、 247 * value値も JSPには表示しません。 248 * 初期値は、(false:出力しない) です。 249 * 250 * @og.rev 6.9.3.0 (2018/03/26) usePrintOut 新規追加 251 * 252 * @param flag System.out.println に 出力するかどうか [true:する/false:しない] 253 */ 254 public void setUsePrintOut( final String flag ) { 255 usePrintOut = nval( getRequestParameter( flag ),usePrintOut ); 256 } 257 258 /** 259 * 【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します 260 * (初期値:USE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。 261 * 262 * @og.tag 263 * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。 264 * (><) が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。 265 * (初期値:システム定数のUSE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。 266 * 267 * @og.rev 5.9.10.5 (2016/07/22) xssCheck 268 * 269 * @param flag XSSチェック [true:する/false:しない] 270 * @see org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK 271 */ 272 public void setXssCheck( final String flag ) { 273 xssCheck = nval( getRequestParameter( flag ),xssCheck ); 274 } 275 276 /** 277 * 【TAG】BODYを処理後に停止するかどうか[true/false]を指定します(初期値:false)。 278 * 279 * @og.tag 280 * true を指定すると、以下の処理は、行われません。 281 * 初期値は、停止しない ("false") 282 * 283 * @og.rev 6.9.9.1 (2018/08/27) useStop 属性を追加します。 284 * 285 * @param flag 処理後停止 [true:する/それ以外:しない] 286 */ 287 public void setUseStop( final String flag ) { 288 useStop = nval( getRequestParameter( flag ),useStop ); 289 } 290 291 /** 292 * このオブジェクトの文字列表現を返します。 293 * 基本的にデバッグ目的に使用します。 294 * 295 * @og.rev 6.9.0.2 (2018/02/13) useTag 属性の値も表示に加えます。 296 * 297 * @return このクラスの文字列表現 298 * @og.rtnNotNull 299 */ 300 @Override 301 public String toString() { 302 return ToString.title( this.getClass().getName() ) 303 .println( "VERSION" ,VERSION ) 304 .println( "useTag" ,useTag() ) // 6.9.0.2 (2018/02/13) 305 .println( "value" ,value ) 306 .println( "Other..." ,getAttributes().getAttribute() ) 307 .fixForm().toString() ; 308 } 309 310 /** 311 * 動的にファイルを include する為の、コンテキストパスを求めます。 312 * 313 * 指定のファイル名は、自身のディレクトリからの相対パスで表されます。 314 * 315 * @og.rev 4.0.0.0 (2007/05/25) 新規追加 316 * @og.rev 4.0.0.0 (2007/11/30) if の評価方法を変更します。 317 * 318 * @param request ServletRequestオブジェクト 319 * @param relativePath ファイル名 320 * 321 * @return コンテキストパス 322 */ 323 private String getContextRelativePath( final ServletRequest request,final String relativePath ) { 324 // 6.1.0.0 (2014/12/26) refactoring 325 if( StringUtil.startsChar( relativePath , '/' ) // 6.2.0.0 (2015/02/27) 1文字 String.startsWith 326 || !(request instanceof HttpServletRequest) ) { 327 return relativePath ; 328 } 329 330 final HttpServletRequest hrequest = (HttpServletRequest) request; 331 String uri = (String)request.getAttribute("javax.servlet.include.servlet_path"); 332 if( uri != null && uri.lastIndexOf('/') >= 0 ) { 333 final String pathInfo = (String)request.getAttribute("javax.servlet.include.path_info"); 334 if( pathInfo == null ) { 335 uri = uri.substring(0, uri.lastIndexOf('/')); 336 } 337 } 338 else { 339 uri = hrequest.getServletPath(); 340 if( uri.lastIndexOf('/') >= 0 ) { 341 uri = uri.substring(0, uri.lastIndexOf('/')); 342 } 343 } 344 return uri + '/' + relativePath; 345 } 346}