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.plugin.column;
017
018import org.opengion.fukurou.util.ErrorMessage;
019import org.opengion.fukurou.util.StringUtil;
020import org.opengion.hayabusa.db.AbstractDBType;
021import org.opengion.hayabusa.db.DBTypeCheckUtil;
022
023import java.util.Locale ;
024
025/**
026 * 半角文字+半角カタカナの大文字のみに制限された文字列を扱う為の、カラム属性を定義します。
027 *
028 * ホスト送信用なので、半角カタカナ小文字を半角カタカナ大文字に変換します。
029 * 通常の半角文字や半角カタカナを入力すると、大文字に変換後に、チェックを行います。
030 * 半角カタカナの小文字とは、「ァ,ィ,ゥ,ェ,ォ,ャ,ュ,ョ,ッ」のことで、これらの文字列を、
031 * 「ア,イ,ウ,エ,オ,ヤ,ユ,ヨ,シ」に置き換えます。
032 *
033 * タイプチェックとして、以下の条件を判定します。
034 * ・文字列長は、Byte換算での文字数との比較
035 * ・半角文字+半角カタカナチェック
036 * ・文字パラメータの 正規表現チェック
037 * ・クロスサイトスクリプティングチェック
038 *
039 * @og.group データ属性
040 *
041 * @version  4.0
042 * @author   Kazuhiko Hasegawa
043 * @since    JDK5.0,
044 */
045public class DBType_XHU extends AbstractDBType {
046        /** このプログラムのVERSION文字列を設定します。   {@value} */
047        private static final String VERSION = "6.4.2.0 (2016/01/29)" ;
048
049        /**
050         * デフォルトコンストラクター
051         *
052         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
053         */
054        public DBType_XHU() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
055
056        /**
057         * エディターで編集されたデータを登録する場合に、データそのものを
058         * 変換して、実登録データを作成します。
059         * 例えば,大文字のみのフィールドなら、大文字化します。
060         * 実登録データの作成は、DBType オブジェクトを利用しますので,
061         * これと Editor とがアンマッチの場合は、うまくデータ変換
062         * されない可能性がありますので、注意願います。
063         *
064         * @og.rev 3.3.3.0 (2003/07/09) 前後のスペースを取り除いておく。
065         * @og.rev 3.3.3.1 (2003/07/18) 後ろスペースを取り除く。(StringUtil#rTrim)
066         * @og.rev 3.4.0.0 (2003/09/01) 半角カナ文字化け対策(ア,エ,カ,ー,ラ)の変換処理の廃止
067         *
068         * @param       value   (一般に編集データとして登録されたデータ)
069         *
070         * @return  修正後の文字列(一般にデータベースに登録するデータ)
071         */
072        @Override
073        public String valueSet( final String value ) {
074                if( value == null ) { return null; }
075                String rtnVal = StringUtil.rTrim( value );
076                char[] ch = rtnVal.toCharArray();               // 3.3.3.1 (2003/07/18)
077
078                boolean flag = false;
079                for( int i=0; i<ch.length; i++ ) {
080                        switch( ch[i] ) {
081        // 3.4.0.0 (2003/09/01) 半角カナ文字化け対策(ア,エ,カ,ー,ラ)の変換処理の廃止
082        //                      case '±' : ch[i] = 'ア'; flag = true; break;
083        //                      case '´' : ch[i] = 'エ'; flag = true; break;
084        //                      case '¶' : ch[i] = 'カ'; flag = true; break;
085        //                      case '°' : ch[i] = 'ー'; flag = true; break;
086        //                      case '×' : ch[i] = 'ラ'; flag = true; break;
087                                case 'ァ'  : ch[i] = 'ア'; flag = true; break;
088                                case 'ィ'  : ch[i] = 'イ'; flag = true; break;
089                                case 'ゥ'  : ch[i] = 'ウ'; flag = true; break;
090                                case 'ェ'  : ch[i] = 'エ'; flag = true; break;
091                                case 'ォ'  : ch[i] = 'オ'; flag = true; break;
092                                case 'ャ'  : ch[i] = 'ヤ'; flag = true; break;
093                                case 'ュ'  : ch[i] = 'ユ'; flag = true; break;
094                                case 'ョ'  : ch[i] = 'ヨ'; flag = true; break;
095                                case 'ッ'  : ch[i] = 'シ'; flag = true; break;
096                                default   : break;
097                        }
098                }
099                if( flag ) {
100                        rtnVal = new String( ch );
101                }
102                return rtnVal.toUpperCase(Locale.JAPAN);
103        }
104
105        /**
106         * データが登録可能かどうかをチェックします。
107         * データがエラーの場合は、そのエラー内容を返します。
108         *
109         * @og.rev 3.0.1.3 (2003/03/11) DBTypeCheckUtilクラスを利用するように修正
110         * @og.rev 3.6.0.0 (2004/09/22) dbType パラメータ(文字パラメータ)を引数に追加
111         * @og.rev 3.6.1.0 (2005/01/05) 半角カタカナに、『、』を含めます。(0xff65 以上 → 0xff64以上)
112         * @og.rev 5.2.2.0 (2010/11/01) 厳密にチェック(isStrict=true)するフラグを追加
113         *
114         * @param   key         キー
115         * @param   value       値
116         * @param   sizeX       整数部分の文字列の長さ
117         * @param   sizeY       小数部分の文字列の長さ
118         * @param   typeParam   dbType パラメータ(文字パラメータ)
119         * @param   isStrict    厳密にチェックするかどうか[true:する/false:標準的]
120         *
121         * @return  エラー内容
122         * @og.rtnNotNull
123         */
124        @Override
125        public ErrorMessage valueCheck( final String key ,final String value ,
126                                                                        final int sizeX ,final int sizeY ,final String typeParam ,final boolean isStrict) {
127
128                // 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
129                final ErrorMessage msg = new ErrorMessage();
130                if( value == null || value.isEmpty() ) { return msg; }
131
132                final int len = (sizeY == 0) ? sizeX : sizeX + sizeY + 1;
133                String check = DBTypeCheckUtil.byteLengthCheck( value,len );
134                if( check != null ) {
135                        // 文字列の長さが指定の長さよりも長いです。
136                        msg.addMessage( 0,ErrorMessage.NG,"ERR0006",key,value,check,String.valueOf( len ) );
137                }
138
139                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
140                boolean isError = false;
141                for( int i=0; i<value.length(); i++ ) {
142                        final char ch = value.charAt( i );
143                        // 半角カタカナの小文字(ァ ィ ゥ ェ ォ ャ ュ ョ ッ)も、NG
144                        if(             ch < 0x20                                                                                               // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
145                                ||      ch > 0x7e   && ch < 0xff64
146                                ||      ch > 0xff66 && ch < 0xff70
147                                ||      ch >= 0xffa0 ) {
148                                        buf.append( "<span class=\"NG\">" ).append( ch ).append( "</span>" );
149                                        isError = true;
150                        }
151                        else {
152                                buf.append( ch );
153                        }
154                }
155                if( isError ) {
156                        // 指定の文字以外の文字が使われています。
157                        msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,buf.toString() );
158                }
159
160                // 3.6.0.0 (2004/09/22) dbType パラメータ(文字パラメータ)を使用したマッチチェック
161                check = DBTypeCheckUtil.matcheCheck( value,typeParam );
162                if( check != null ) {
163                        // 指定の文字以外の文字が使われています。
164                        msg.addMessage( 0,ErrorMessage.NG,"ERR0009", key,check );
165                }
166
167                // クロスサイトスクリプティング対策:'<', '>' は登録させない。
168                // 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
169                return xssCheck( key ,value, msg );
170        }
171}