    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.fukurou.mail;
    017
    018// import java.io.InputStream;
    019// import java.io.OutputStream;
    020import java.io.ByteArrayOutputStream;
    021// import java.io.ByteArrayInputStream;
    022import java.io.UnsupportedEncodingException;
    023// import java.io.IOException;
    024
    025// import javax.activation.DataHandler;
    026// import javax.activation.DataSource;
    027// import javax.mail.internet.InternetAddress;
    028// import javax.mail.internet.MimeMessage;
    029// import javax.mail.internet.MimeUtility;
    030// import javax.mail.MessagingException;
    031// import com.sun.mail.util.BASE64EncoderStream;
    032
    033// import java.nio.charset.Charset;             // 5.5.2.6 (2012/05/25)
    034
    035/**
    036 * 文字関係のコンバータです。
    037 * 一部コードのオリジナルは <a href="http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/CCGI/kanjicod.html">Japanese Kanji Code</a>にて公開されているものです。
    038 * また、http://www.sk-jp.com/cgi-bin/treebbs.cgi?kako=1&amp;all=644&amp;s=681
    039 * にて YOSI さんが公開されたコードも参考にしています(というか実質同じです)。
    040 *
    041 * @version  4.0
    042 * @author   Kazuhiko Hasegawa
    043 * @since    JDK5.0,
    044 */
    045class CharCodeConverter {
    046        private static final byte[] SJIS_KANA;  // 5.1.9.0 (2010/09/01) public ⇒ private へ変更
    047
    048        /**
    049         * インスタンスの生成を抑止します。
    050         */
    051        private CharCodeConverter() {
    052                // 何もありません。(PMD エラー回避)
    053        }
    054
    055        static {
    056                try {
    057                        // 全角への変換テーブル
    058                        SJIS_KANA = "。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜".getBytes("Shift_JIS");
    059                } catch( UnsupportedEncodingException ex ) {
    060                        throw new RuntimeException( "CANT HAPPEN",ex );
    061                }
    062        }
    063
    064        /**
    065         * Shift_JIS エンコーディングスキームに基づくバイト列を
    066         * ISO-2022-JP エンコーディングスキームに変換します。
    067         * 「半角カナ」は対応する全角文字に変換します。
    068         *
    069         * @param sjisBytes byte[] エンコードするShift_JISバイト配列
    070         *
    071         * @return byte[] 変換後のISO-2022-JP(JIS)バイト配列(not null)
    072         */
    073        public static byte[] sjisToJis( final byte[] sjisBytes ) {
    074                ByteArrayOutputStream out = new ByteArrayOutputStream();
    075                boolean nonAscii = false;
    076                int len = sjisBytes.length;
    077                for(int i = 0; i < len; i++ ) {
    078                        if(sjisBytes[i] >= 0) {
    079                                if(nonAscii) {
    080                                        nonAscii = false;
    081                                        out.write(0x1b);
    082                                        out.write('(');
    083                                        out.write('B');
    084                                }
    085                                out.write(sjisBytes[i]);
    086                        } else {
    087                                if(!nonAscii) {
    088                                        nonAscii = true;
    089                                        out.write(0x1b);
    090                                        out.write('$');
    091                                        out.write('B');
    092                                }
    093                                int bt = sjisBytes[i] & 0xff;
    094                                if(bt >= 0xa1 && bt <= 0xdf) {
    095                                        // 半角カナは全角に変換
    096                                        int kanaIndex = (bt - 0xA1) * 2;
    097                                        sjisToJis(out, SJIS_KANA[kanaIndex], SJIS_KANA[kanaIndex + 1]);
    098                                } else {
    099                                        i++;
    100                                        if(i == len) { break; }
    101                                        sjisToJis(out, sjisBytes[i - 1], sjisBytes[i]);
    102                                }
    103                        }
    104                }
    105                if(nonAscii) {
    106                        out.write(0x1b);
    107                        out.write('(');
    108                        out.write('B');
    109                }
    110                return out.toByteArray();
    111        }
    112
    113        /**
    114         * １文字の２バイト Shift_JIS コードを JIS コードに変換して書き出します。
    115         */
    116        private static void sjisToJis(
    117                                final ByteArrayOutputStream out, final byte bhi, final byte blo) {
    118                int hi = (bhi << 1) & 0xFF;
    119                int lo = blo & 0xFF;
    120                if(lo < 0x9F) {
    121                        if(hi < 0x3F) { hi += 0x1F; } else { hi -= 0x61; }
    122                        if(lo > 0x7E) { lo -= 0x20; } else { lo -= 0x1F; }
    123                } else {
    124                        if(hi < 0x3F) { hi += 0x20; } else { hi -= 0x60; }
    125                        lo -= 0x7E;
    126                }
    127                out.write(hi);
    128                out.write(lo);
    129        }
    130}