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 static org.opengion.fukurou.util.StringUtil.nval;
019
020import org.opengion.hayabusa.common.HybsSystem;
021import org.opengion.hayabusa.common.HybsSystemException;
022import org.opengion.fukurou.util.LogWriter;
023import org.opengion.fukurou.util.FileString;
024
025import javax.servlet.ServletRequest ;
026import javax.servlet.http.HttpServletRequest ;
027
028/**
029 * BODY部に記述されたエンジン固有の文字列({@XXXX}など)を、
030 *  ユーザー情報のエンコーディングに変換するタグです。
031 *
032 * XML形式で 日本語コードのパースが、JSPエンジン(Tomcat)でサポート
033 * されるまでの、暫定的なタグです。
034 * なお、このタグの内部に存在するカスタムタグは、先に実行されるため
035 * 漢字コードは、変換されません。
036 *
037 * @og.formSample
038 * ●形式:<og:text >・・・</og:text>
039 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
040 *
041 * ●Tag定義:
042 *   <og:text
043 *       value              【TAG】value 値に直接書かれた漢字コードをShift_JIS に変換します
044 *       include            【TAG】動的にファイルを include します
045 *       xssCheck           【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true])
046 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
047 *   >   ... Body ...
048 *   </og:text>
049 *
050 * ●使用例
051 *      ・<og:text >
052 *            <p>あいおえお:<input name="PN" value="{@PN}" /> </p>
053 *        </og:text>
054 *      ・<og:text value="あいうえお" />
055 *
056 *     動的にファイルを include することが出来ます。
057 *      ・<og:text include="{@query}.txt" />
058 *
059 * @og.group 画面部品
060 *
061 * @version  4.0
062 * @author   Kazuhiko Hasegawa
063 * @since    JDK5.0,
064 */
065public class TextTag extends CommonTagSupport {
066        //* このプログラムのVERSION文字列を設定します。   {@value} */
067        private static final String VERSION = "4.0.0.0 (2007/11/30)" ;
068
069        private static final long serialVersionUID = 400020071130L ;
070
071        private String  value   = null;
072        private boolean useInclude = false;
073        
074        private boolean xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.9.10.5 (2010/06/01) XSS対策
075
076        /**
077         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
078         *
079         * @og.rev 5.9.10.5 (2016/07/22) xssCheck
080         *
081         * @return      後続処理の指示( EVAL_BODY_BUFFERED )
082         */
083        @Override
084        public int doStartTag() {
085                useXssCheck( xssCheck ); // 5.9.10.5 (2016/07/22)
086                return( EVAL_BODY_BUFFERED );   // Body を評価する。( extends BodyTagSupport 時)
087        }
088
089        /**
090         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
091         *
092         * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
093         * @og.rev 3.0.0.0 (2002/12/25) StringUtil#changeString 廃止
094         * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
095         * @og.rev 4.0.0.0 (2007/10/12) 処理中にエラーを発生させないようにしする。
096         *
097         * @return      後続処理の指示(SKIP_BODY)
098         */
099        @Override
100        public int doAfterBody() {
101                if( !useInclude && value == null ) {
102                        // 4.0.0.0 (2007/10/12) 処理中にエラーを発生させない
103                        try {
104                                value = getBodyString();
105                        }
106                        catch( HybsSystemException ex ) {       // 主に、UserInfo が見つからない場合
107                                value = getBodyContent().getString() ;
108                        }
109
110                        if( value != null && value.indexOf( "<og:" ) >= 0 ) {
111                                String errMsg = "このタグの BODY部に opengion タグが記述されています。"
112                                                        + "BODY部ではopengion タグは使用できません。";
113                                throw new HybsSystemException( errMsg );
114                        }
115                }
116
117                return(SKIP_BODY);
118        }
119
120        /**
121         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
122         *
123         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
124         *
125         * @return      後続処理の指示
126         */
127        @Override
128        public int doEndTag() {
129                debugPrint();           // 4.0.0 (2005/02/28)
130                jspPrint( value );
131
132                return(EVAL_PAGE);
133        }
134
135        /**
136         * タグリブオブジェクトをリリースします。
137         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
138         *
139         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
140         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
141         * @og.rev 5.9.10.5 (2016/07/22) xssCheck
142         *
143         */
144        @Override
145        protected void release2() {
146                super.release2();
147                value           = null;
148                useInclude      = false;
149                xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" );        // 5.9.10.5 (2016/07/22)
150        }
151
152        /**
153         * 【TAG】value 値に設定します。
154         *
155         * @og.tag
156         * ここで、value に設定した場合は、BODY 部は無視されます。
157         * なお、このタグでは、エラー発生時でも継続して処理を続けられるようにします。
158         * error.jsp などのエラー処理画面で、このタグを使用するケースがある為です。
159         *
160         *  &lt;og:text value="あいうえお" /&gt;
161         *
162         * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
163         * @og.rev 3.0.0.0 (2002/12/25) StringUtil#changeString 廃止
164         * @og.rev 4.0.0.0 (2005/12/31) エラー発生時でも異常終了させずに処理を続けます。
165         *
166         * @param   val 設定値
167         */
168        public void setValue( final String val ) {
169                if( !useInclude ) {
170                        try {
171                                value = getRequestParameter( val );
172                        }
173                        catch( HybsSystemException ex ) {
174                                value = val ;
175                                LogWriter.log( "val=" + val + " [" + ex.getMessage() + "]" );
176                        }
177                }
178        }
179        
180        /**
181         * 【TAG】リクエスト情報の HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか[true/false]を設定します
182         *              (初期値:USE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。
183         *
184         * @og.tag
185         * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。
186         * (&gt;&lt;) が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。
187         * (初期値:システム定数のUSE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。
188         *
189         * @og.rev 5.9.10.5 (2016/07/22) xssCheck
190         *
191         * @param       flag    XSSチェック [true:する/false:しない]
192         * @see         org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK
193         */
194        public void setXssCheck( final String flag ) {
195                xssCheck = nval( getRequestParameter( flag ),xssCheck );
196        }
197
198        /**
199         * 【TAG】動的にファイルを include します。
200         *
201         * @og.tag
202         * 指定のファイル名は、自身のディレクトリからの相対パスで表されます。
203         *
204         * @og.rev 4.0.0.0 (2007/05/25) 新規追加
205         *
206         * @param   file ファイル名
207         */
208        public void setInclude( final String file ) {
209                useInclude = true;
210
211                String relativePath = getRequestParameter( file );
212                String resourcePath = getContextRelativePath(getRequest(), relativePath);
213                String realPath = HybsSystem.url2dir( resourcePath.substring(1) );
214
215                FileString fs = new FileString();
216                fs.setFilename( realPath );
217                value = fs.getValue();
218        }
219
220        /**
221         * このオブジェクトの文字列表現を返します。
222         * 基本的にデバッグ目的に使用します。
223         *
224         * @return このクラスの文字列表現
225         */
226        @Override
227        public String toString() {
228                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
229                                .println( "VERSION"             ,VERSION        )
230                                .println( "value"               ,value          )
231                                .println( "Other..."    ,getAttributes().getAttribute() )
232                                .fixForm().toString() ;
233        }
234
235        /**
236         * 動的にファイルを include する為の、コンテキストパスを求めます。
237         *
238         * 指定のファイル名は、自身のディレクトリからの相対パスで表されます。
239         *
240         * @og.rev 4.0.0.0 (2007/05/25) 新規追加
241         * @og.rev 4.0.0.0 (2007/11/30) if の評価方法を変更します。
242         *
243         * @param       request                 ServletRequestオブジェクト
244         * @param       relativePath    ファイル名
245         *
246         * @return      コンテキストパス
247         */
248        private String getContextRelativePath( final ServletRequest request,
249                                                                                        final String relativePath) {
250                if(relativePath.startsWith("/")) {
251                        return (relativePath);
252                }
253                if(!(request instanceof HttpServletRequest)) {
254                        return (relativePath);
255                }
256                HttpServletRequest hrequest = (HttpServletRequest) request;
257                String uri = (String)request.getAttribute("javax.servlet.include.servlet_path");
258//              if(uri != null) {
259//                      String pathInfo = (String)request.getAttribute("javax.servlet.include.path_info");
260//                      if(pathInfo == null) {
261//                              if(uri.lastIndexOf('/') >= 0) {
262//                                      uri = uri.substring(0, uri.lastIndexOf('/'));
263//                              }
264//                      }
265//              }
266                if( uri != null && uri.lastIndexOf('/') >= 0 ) {
267                        String pathInfo = (String)request.getAttribute("javax.servlet.include.path_info");
268                        if(pathInfo == null) {
269                                uri = uri.substring(0, uri.lastIndexOf('/'));
270                        }
271                }
272                else {
273                        uri = hrequest.getServletPath();
274                        if(uri.lastIndexOf('/') >= 0) {
275                                uri = uri.substring(0, uri.lastIndexOf('/'));
276                        }
277                }
278                return uri + '/' + relativePath;
279        }
280}