/* * Aipo is a groupware program developed by TOWN, Inc. * Copyright (C) 2004-2015 TOWN, Inc. * http://www.aipo.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.aimluck.commons.utils; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.aimluck.commons.field.ALNumberField; /** * 入力フィールドで取り扱う文字列に対するユーティリティクラスです。 <br /> * */ public class ALStringUtil { /** 半角カナの開始コード */ public static final int HANKAKU_KANA_FIRST = 0xff61; /** 半角カナの終了コード */ public static final int HANKAKU_KANA_LAST = 0xff9f; /** 濁音 */ private static final String DAKUON = "がぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽ"; /** 清音 */ private static final String SEION = "かきくけこさしすせそたちつてとはひふへほはひふへほ"; /** * メールアドレス形式であるかを判定します。 * * @param argStr * チェック対象文字列 * @return メールアドレス形式であればtrue、それ以外はfalse。 */ public static boolean isMailAddress(String str) { Pattern mailPattern = Pattern.compile( "[\\w\\.\\-\\+]+@([\\w\\-]+\\.)+[\\w\\-]+", Pattern.CASE_INSENSITIVE); Matcher objMch = mailPattern.matcher(str); return objMch.matches(); } /** * 携帯電話のメールアドレス形式であるかを判定します。 * * @param argStr * チェック対象文字列 * @return メールアドレス形式であればtrue、それ以外はfalse。 */ public static boolean isCellPhoneMailAddress(String str) { Pattern mailPattern = Pattern.compile( "[\\w\\.\\-\\_\\+\\p{Punct}]+@([\\w\\-]+\\.)+[\\w\\-]+", Pattern.CASE_INSENSITIVE); Matcher objMch = mailPattern.matcher(str); return objMch.matches(); } /** * 指定文字が半角カナかどうかを判定します。 * * @param chr * チェック対象文字 * @return 半角カナならば true,それ以外は false */ public static boolean isHankakuKana(char chr) { return (chr >= HANKAKU_KANA_FIRST && chr <= HANKAKU_KANA_LAST); } /** * 指定文字列が半角数字のみかをどうかを判定します。 * * @param String * str チェックする文字列 * @return 半角数字のみであればtrue、それ以外はfalse。 */ public static boolean isNumber(String str) { for (int i = 0; i < str.length(); i++) { if (str.charAt(i) < 0x0030 || str.charAt(i) > 0x0039) { return false; } } return true; } /** * 指定文字列に含まれるひらがなをカタカナに変換します。 * * @param str * @return */ public static String convertHiragana2Katakana(String str) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < str.length(); i++) { char code = str.charAt(i); if ((code >= 0x3041) && (code <= 0x3093)) { buf.append((char) (code + 0x60)); } else { buf.append(code); } } return buf.toString(); } public static String convertKatakana2Hiragana(String str) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < str.length(); i++) { char code = str.charAt(i); if ((code >= 0x30a1) && (code <= 0x30f3)) { buf.append((char) (code - 0x60)); } else { buf.append(code); } } return buf.toString(); } /** * 指定文字列に含まれる半角カナを全角カナに変換します。 * * @param str * @return */ public static String convertH2ZKana(String str) { if (str == null) { return null; } return convertH2ZKana(str, 0, str.length()); } /** * 指定文字列に含まれる半角カナを全角カナに変換します。 * * @param str * @param pos * @param length * @return */ public static String convertH2ZKana(String str, int pos, int length) { char[][][] table = ALKanaMapTable.TABLE_HANKAKU2ZENKAKU; Comparator<Object> comp = new ALHankakuComparator<Object>(); int retIdx = 0; int maxPos = pos + length; char[] base = new char[1]; char[] daku = new char[2]; char[] nChars = str.toCharArray(); char[] nRets = new char[length]; while (pos < maxPos) { char currChar = nChars[pos++]; if (!isHankakuKana(currChar)) { nRets[retIdx++] = currChar; continue; } char[] res; if (pos < maxPos) { char nextChar = nChars[pos]; if (nextChar == '゛' || nextChar == '゜') { pos++; daku[ALKanaMapTable.INDEX_HANKAKU_BASE] = currChar; daku[ALKanaMapTable.INDEX_HANKAKU_DAKUTEN] = nextChar; res = convertH2ZKanaChar(daku, table, comp); retIdx += putCharactors(nRets, res, retIdx); continue; } } base[0] = currChar; res = convertH2ZKanaChar(base, table, comp); retIdx += putCharactors(nRets, res, retIdx); } return new String(nRets, 0, retIdx); } /** * HTML文字列におけるメタ文字を置き換え、無害化します。 * * @param argStr * メタ文字列 * @return 変換後文字列 */ public static String sanitizing(String str) { if (str == null) { return ""; } StringBuffer buff = new StringBuffer(); int len = str.length(); for (int i = 0; i < len; i++) { char originalCharacter = str.charAt(i); switch (originalCharacter) { case '<': buff.append("<"); break; case '>': buff.append(">"); break; case '\'': buff.append("'"); break; case '\"': buff.append("""); break; case '&': buff.append("&"); break; default: buff.append(originalCharacter); } } return buff.toString(); } /** * 無害化(サニタイジング)された文字列を復元します。 * * @param str * サニタイジングされた文字を含む文字列 * @return サニタイジング前文字列 */ public static String unsanitizing(String str) { if (str == null) { return ""; } StringBuffer buff = new StringBuffer(); int len = str.length(); for (int i = 0; i < len; i++) { char originalChar = str.charAt(i); if (originalChar != '&') { buff.append(originalChar); continue; } if (len > i + 5) { if ("<".equals(str.substring(i, i + 4))) { buff.append('<'); i = i + 3; } else if (">".equals(str.substring(i, i + 4))) { buff.append('>'); i = i + 3; } else if ("'".equals(str.substring(i, i + 5))) { buff.append('\''); i = i + 4; } else if ("&".equals(str.substring(i, i + 5))) { buff.append('&'); i = i + 4; } else if (""".equals(str.substring(i, i + 6))) { buff.append('\"'); i = i + 5; } else { buff.append(originalChar); continue; } } else if (i + 4 == len) { if ("<".equals(str.substring(i))) { buff.append('<'); } else if (">".equals(str.substring(i))) { buff.append('>'); } else { buff.append(str.substring(i)); break; } i = i + 3; } else if (i + 5 == len) { if ("'".equals(str.substring(i))) { buff.append('\''); } else if ("&".equals(str.substring(i))) { buff.append('&'); } else { buff.append(str.substring(i)); break; } i = i + 4; } else if (i + 6 == len) { if (""".equals(str.substring(i))) { buff.append('\"'); } else { buff.append(str.substring(i)); break; } i = i + 5; } else { buff.append('&'); } } return buff.toString(); } private static int putCharactors(char[] chars, char[] newchars, int inpos) { int pos = inpos; for (int i = 0; i < newchars.length; i++) { if (newchars[i] != (char) 0) { chars[pos++] = newchars[i]; } } return pos - inpos; } private static char[] convertH2ZKanaChar(char[] chars, char[][][] mapTable, Comparator<Object> comparator) { int index = Arrays.binarySearch((Object[]) mapTable, chars, comparator); if (index >= 0) { return mapTable[index][ALKanaMapTable.INDEX_ZENKAKU]; } else if (chars.length == 1) { return chars; } int len = chars.length; for (int i = 0; i < len; i++) { if (chars[i] == (char) 0) { continue; } char[] atom = new char[] { chars[i] }; chars[i] = convertH2ZKanaChar(atom, mapTable, comparator)[0]; } return chars; } /** * 指定した文字が記号であるかを返します * * @param ch * @return */ public static boolean isSymbol(char ch) { byte[] chars; try { chars = (Character.valueOf(ch).toString()).getBytes("shift_jis"); } catch (UnsupportedEncodingException ex) { return false; } if (chars == null || chars.length == 2 || Character.isDigit(ch) || Character.isLetter(ch)) { return false; } else { return true; } } public static String toTwoDigitString(ALNumberField num) { if (num != null) { return String.format("%02d", num.getValue()); } return ""; } public static String convertDakuon2Seion(String str) { int size = DAKUON.length(); String result = str; for (int i = 0; i < size; i++) { String s1 = DAKUON.substring(i, i + 1); String s2 = SEION.substring(i, i + 1); result = result.replaceAll(s1, s2); } return result; } }