前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3
SFXMailField
[内部的に利用されるクラスです] メールヘッダーのフィールド値をデコード/エンコードするのためのクラスです。
#include <SFXMailField.h.hpp>
class SFXMailField;
SFMTYPEDEFCLASS(SFXMailField)

解説

SFXMailField クラスは、 以下のようにしてメールヘッダーのフィールド値をデコード/エンコードするためのクラスです。

  1. メールヘッダーのフィールド値を B/Q デコードし、 エスケープシーケンスで区切られた文字列毎に「テキストとエンコード名」のペアの配列として内部で保持します。
  2. 内部で保持する「テキストとエンコード名」のペアの配列を B エンコードしてメールヘッダーのフィールド値を作成します。

デコード時、JIS コードの文字列は ShiftJIS コードに変換されます。 逆に、エンコード時、ShiftJIS コードの文字列は JIS コードに変換されます。

[Note] B / Q エンコード

B / Q エンコードの詳細については、 RFC2047: 4.1. The "B" encoding / RFC2047: 4.2. The "Q" encoding を参照してください。

[Note] 注意

SFXMailField クラスは、 SFXMailMessage クラス内で内部的に使用されています。

開発者がこのクラスを利用する必要性はほとんどありません。

[Note] 注意

SFXMailField クラスは、 SFXMailMessage クラスを実装するときに使用される内部実装クラスです。

SFXSMTPSender クラスに代わる開発者独自のメールメッセージ作成クラスを実装する場合に使用します。

参照

SFXMailMessage

メンバ

コンストラクタ/デストラクタ
SFXMailField( Void )
SFXMailField クラスのコンストラクタです。
~SFXMailField( Void )
SFXMailField クラスのデストラクタです。
パブリック関数
SFCError Add( SFXAnsiStringConstRef charset , SFXAnsiStringConstRef text )
指定されたテキストとエンコード名のペアを内部で保持する「テキストとエンコード名」のペアの配列に追加します。
Void Clear( Void )
内部で保持している「テキストとエンコード名」のペアの配列を解放します。
SFCError Decode( SFXAnsiStringConstRef string )
指定された文字列をデコードし、「テキストとエンコード名」のペアの配列として内部で保持します。
SFCError Encode( SFXAnsiStringPtr string )
内部で保持している「テキストとエンコード名」のペアの配列をエンコードして送信するメールヘッダー内のフィールド値を作成します。
CharsetTextPtr GetCharsetText( SInt32 index )
指定されたインデックスの「テキストとエンコード名」のペアを取得します。
SInt32 GetSize( Void )
内部に保持されている「テキストとエンコード名」のペアの総数を取得します。
プロテクト関数
SFCError AddNonEncodedText( ACharConstPtr start , ACharConstPtr end )
指定された US-ASCII テキストを内部で保持する「テキストとエンコード名」のペアの配列に追加します。
SFCError AddNonEncodedText( SFXAnsiStringConstRef text )
指定された US-ASCII テキストを内部で保持する「テキストとエンコード名」のペアの配列に追加します。
SFCError DecodeTextB( SFXAnsiStringPtr decoded , ACharConstPtr start , ACharConstPtr end )
指定された文字列を B デコードします。
SFCError DecodeTextQ( SFXAnsiStringPtr decoded , ACharConstPtr start , ACharConstPtr end )
指定された文字列を Q デコードします。
static
Bool
IsLWSP( AChar c )
指定された文字が LWSP(空白文字、水平タブ、改行文字、または復帰文字)であるかどうかを判定します。
static
Void
SkipLWSP( ACharConstHandle start , ACharConstPtr end )
ポインタを LWSP(空白文字、水平タブ、改行文字、または復帰文字)以外の文字まで進めます。
CharsetText
「テキストとエンコード名」のペアを表す構造体です。

SFXMailField::SFXMailField
SFXMailField クラスのコンストラクタです。
[ public, explicit ]
SFXMailField(Void);

解説

このコンストラクタは、何も行いません。

内部実装

このコンストラクタの内部実装は以下の通りです。

/*public */SFXMailField::SFXMailField(Void)
{
}// SFXMailField::SFXMailField //

SFXMailField::~SFXMailField
SFXMailField クラスのデストラクタです。
[ public ]
~SFXMailField(Void);

解説

このデストラクタは、 SFXMailField::Clear 関数を呼び出して内部で保持している「テキストとエンコード名」のペアの配列を解放します。

内部実装

このデストラクタの内部実装は以下の通りです。

/*public */SFXMailField::~SFXMailField(Void)
{
    Clear();
}// SFXMailField::~SFXMailField //

参照

SFXMailField::Clear


SFXMailField::Add
指定されたテキストとエンコード名のペアを内部で保持する「テキストとエンコード名」のペアの配列に追加します。
[ public ]
SFCError Add(
    SFXAnsiStringConstRef charset   // [入力] エンコード名
    SFXAnsiStringConstRef text      // [入力] テキスト
);

引数

charset

エンコード名を指定します(通常、"ISO-2022-JP")。

text

メールヘッダーに追加する文字列を指定します(通常、JIS コードの文字列)。

戻り値

  • 成功したとき: SFERR_NO_ERROR
  • メモリ不足のとき: SFERR_NO_MEMORY

解説

この関数は、 指定されたテキストとエンコード名のペア(SFXMailField::CharsetText) を内部で保持する「テキストとエンコード名」のペアの配列に追加します。

[Note] 注意

charset 引数に指定するエンコード名は "ISO-2022-JP" や "Shift_JIS" など IANA に登録された文字列を指定します。 また、text 引数で指定する文字列はこのエンコーディングでエンコードされている必要があります。

日本語の場合、一般にエンコードは "ISO-2022-JP" を利用します。

Shift_JIS の文字列をメールヘッダーのフィールド値に追加するには、 SFXMailUtility::ShiftJISToJIS 関数を使用して JIS コード("ISO-2022-JP")に変換してから text 引数に渡します。

"US-ASCII" の文字列の場合は、 SFXMailField::AddNonEncodedText 関数を利用します。

内部実装

この関数の内部実装は以下の通りです。

/*public */SFCError SFXMailField::Add(SFXAnsiStringConstRef charset, SFXAnsiStringConstRef text)
{
    SFCError error;
    CharsetTextPtr cstr;

    if ((cstr = ::new CharsetText) != null) {
        if ((error = cstr->charset.Set(charset)) == SFERR_NO_ERROR) {
            cstr->charset.ToLower();
            if ((error = cstr->text.Set(text)) == SFERR_NO_ERROR) {
                error = _array.InsertLast(cstr);
            }
        }
        if (error != SFERR_NO_ERROR) {
            ::delete cstr;
        }
    }
    else {
        error = SFERR_NO_MEMORY;
    }
    return error;
}// SFXMailField::Add //

参照

SFXMailField::AddNonEncodedText | SFXMailField::GetCharsetText | SFXMailField::CharsetText


SFXMailField::AddNonEncodedText
指定された US-ASCII テキストを内部で保持する「テキストとエンコード名」のペアの配列に追加します。
[ protected ]
SFCError AddNonEncodedText(
    ACharConstPtr start   // [入力] 追加する US-ASCII テキストの先頭へのポインタ
    ACharConstPtr end     // [入力] 追加する US-ASCII の終端へのポインタ
);
[ protected ]
SFCError AddNonEncodedText(
    SFXAnsiStringConstRef text   // [入力] 追加する US-ASCII テキスト
);

引数

text

追加する US-ASCII テキストを指定します。

textStart

追加する US-ASCII テキストの先頭へのポインタを指定します。

textEnd

追加する US-ASCII テキストの終端へのポインタを指定します。

戻り値

  • 成功したとき: SFERR_NO_ERROR
  • メモリ不足のとき: SFERR_NO_MEMORY

解説

この関数は、指定された US-ASCII テキストを内部で保持する「テキストとエンコード名」のペアの配列に追加します。

このとき、エンコード名は空文字列として追加されます。

[Note] 注意

引数には、US-ASCII コードのテキストを指定します。

日本語が含まれる場合は、 SFXMailField::Add 関数を使用します。

内部実装

この関数の内部実装は以下の通りです。

/*protected */SFCError SFXMailField::AddNonEncodedText(SFXAnsiStringConstRef text)
{
    SFCError error(SFERR_NO_ERROR);
    CharsetTextPtr cstr;

    if ((cstr = ::new CharsetText) != null) {
        if ((error = cstr->text.Set(text)) == SFERR_NO_ERROR) {
            error = _array.InsertLast(cstr);
        }
        if (error != SFERR_NO_ERROR) {
            ::delete cstr;
        }
    }
    else {
        error = false;
    }
    return error;
}// SFXMailField::AddNonEncodedText //

参照

SFXMailField::Add | SFXMailField::GetCharsetText | SFXMailField::CharsetText


SFXMailField::Clear
内部で保持している「テキストとエンコード名」のペアの配列を解放します。
[ public ]
Void Clear(Void);

解説

この関数は、内部で保持している「テキストとエンコード名」のペアの配列を解放します。

[Note] 注意

この関数は、内部的に SFXMailField::~SFXMailField デストラクタから呼び出されます。

内部実装

この関数の内部実装は以下の通りです。

/*public */Void SFXMailField::Clear(Void)
{
    CharsetTextArray::Iterator itor;
    CharsetTextPtr text;

    itor = _array.GetFirstIterator();
    while (itor.HasNext()) {
        text = itor.GetNext();
        ::delete text;
    }
    _array.Clear();
}// SFXMailField::Clear //

参照

SFXMailField::~SFXMailField


SFXMailField::Decode
指定された文字列をデコードし、「テキストとエンコード名」のペアの配列として内部で保持します。
[ public ]
SFCError Decode(
    SFXAnsiStringConstRef string   // [入力] デコードする文字列
);

引数

string

デコードする文字列を指定します。

戻り値

  • 成功したとき: SFERR_NO_ERROR
  • B / Q デコードの際に不正な文字があったとき: SFERR_INVALID_FORMAT
  • メモリ不足のとき: SFERR_NO_MEMORY

解説

この関数は、 指定された文字列をデコードし、 「テキストとエンコード名」のペアの配列として内部で保持します。

B / Q エンコードされているテキストは、 内部的に SFXMailField::DecodeTextB / SFXMailField::DecodeTextQ 関数によりデコードされます。

デコードされた文字列は、 「テキストとエンコード名」のペアの配列に変換されて内部で保持されます。

[Note] 注意

string 引数に指定する文字列は、受信したメールのヘッダー内のフィールド値です。

文字コードの変換は行われません。

[Note] 注意

この関数実行後に内部で保持される「テキストとエンコード名」のペアとその総数は SFXMailField::GetCharsetText 関数と SFXMailField::GetSize 関数を使用して取得します。

使用例

以下は、 指定されたフィールド名の値をデコードして返却するコードです (元のフィールド値に含まれる日本語は B / Q エンコードされた JIS コードで表現されています)。

/*public */SFXAnsiString SFXMailMessage::GetField(SFXAnsiStringConstRef name, Bool isDecoding, BoolPtr found) const
{
    SFCError error;
    SFXAnsiString temp;
    SFXAnsiString result;
    SFXMailField decoder;
    SFXMailField::CharsetTextConstPtr f;
    SInt32 i;

    if (found != null) {

        *found = _header.Contains(name);
    }
    if (isDecoding) {

        // 指定されたメールヘッダー文字列をデコードし、「テキストとエンコード名」のペアの配列として内部で保持する
        if ((error = decoder.Decode(_header.Get(name, false))) == SFERR_NO_ERROR) {

            for (i = 0; error == SFERR_NO_ERROR && i < decoder.GetSize(); ++i) {

                // i 番目の「テキストとエンコード名」のペアを取得する
                f = decoder.GetCharsetText(i);
                if (f->charset.Equals("iso-2022-jp", false)) {

                    // 文字コードが JISコード(iso-2022-jp)の場合
                    SFXAnsiString decodedText;
                    if ((error = SFXMailUtility::JISToShiftJIS(f->text, &decodedText)) == SFERR_NO_ERROR) {

                        // result に追加する
                        error = result.Add(decodedText);
                    }
                }
                else if (f->charset.Equals("us-ascii", false) || f->charset.IsEmpty()) {

                    // result に追加する
                    error = result.Add(f->text);
                }
                else {

                    /* IMPLEMENT HERE ERROR CHECK */
                }
            }
        }
    }
    else {
        result.Set(_header.Get(name, false));
    }
    return result;
}// SFXMailMessage::GetField //

内部実装

この関数の内部実装は以下の通りです。

/*public */SFCError SFXMailField::Decode(SFXAnsiStringConstRef string)
{
    SFCError error(SFERR_NO_ERROR);
    SFCError last;
    ACharConstPtr pos(string.GetBuffer());
    const ACharConstPtr end(pos + string.GetLength());
    ACharConstPtr nonEncodedStart;
    ACharConstPtr p;
    SFXAnsiString charset;
    AChar         method;
    ACharConstPtr encodedStart;
    ACharConstPtr encodedEnd;
    ACharConstPtr charsetStart;
    ACharConstPtr charsetEnd;
    ACharConstPtr textStart;
    ACharConstPtr textEnd;
    CharsetTextPtr cstr;

    Clear();
    if (!string.IsEmpty()) {
        SkipLWSP(&pos, end);
        nonEncodedStart = pos;
        for (; pos < end; ++pos) {
            if (*pos == '=' && pos + 1 < end && *(pos + 1) == '?') {// if "=?" found ...
                charsetEnd = null;
                textStart = null;
                encodedStart = pos; // hold start position of encoded word.
                charsetStart = pos + 2; // hold start position of charset name.
                method = 0; // find '?B?' or '?Q?'
                for (p = charsetStart; p < end; ++p) {
                    if (*p == '?' && p + 2 < end && *(p + 2) == '?') {
                        charsetEnd = p; // hold end position of charset.
                        method = SFXAscii::AsUpper(*(p + 1)); // get encoding method.
                        textStart = p + 3; // hold start position of encoded string.
                        break;
                    }
                }
                if (method == 'Q' || method == 'B') {
                    textEnd = null;
                    for (p = textStart; p < end; ++p) {// find "?=" position.
                        if (*p == '?' && p + 1 < end && *(p + 1) == '=') {// if "?=" found ...
                            textEnd = p;
                            break;
                        }
                        if (*p == CR && p + 1 < end && *(p + 1) == LF) {// if CRLF found ...
                            break;
                        }
                    }
                    if (textEnd != null) {
                        encodedEnd = textEnd + 2; // hold end position of encoded string.
                        if ((error = AddNonEncodedText(nonEncodedStart, encodedStart)) == SFERR_NO_ERROR) {
                            if ((cstr = ::new CharsetText) != null) {
                                if ((error = cstr->charset.Set(charsetStart, charsetEnd - charsetStart)) == SFERR_NO_ERROR) {
                                    cstr->charset.ToLower();
                                    if (method == 'Q') {
                                        error = DecodeTextQ(&cstr->text, textStart, textEnd);
                                    }
                                    else if (method == 'B') {
                                        error = DecodeTextB(&cstr->text, textStart, textEnd);
                                    }
                                    else {
                                        ASSERT(false);
                                    }
                                    if (error == SFERR_NO_ERROR) {
                                        if ((error = _array.InsertLast(cstr)) == SFERR_NO_ERROR) {
                                            pos = encodedEnd;
                                            //SkipLWSP(&pos, end);
                                            nonEncodedStart = pos;
                                            --pos;
                                        }
                                    }
                                }
                                if (error != SFERR_NO_ERROR) {
                                    ::delete cstr;
                                    break;
                                }
                            }
                            else {
                                error = SFERR_NO_MEMORY;
                                break;
                            }
                        }
                        else {
                            break;
                        }
                    }
                }
                else {
                    error = SFERR_INVALID_FORMAT;
                }
            }
        }
        last = AddNonEncodedText(nonEncodedStart, end);
        if (last != SFERR_NO_ERROR) {
            error = last;
        }
    }
    return error;
}// SFXMailField::Decode //

参照

SFXMailField::DecodeTextB | SFXMailField::DecodeTextQ | SFXMailField::GetSize | SFXMailField::GetCharsetText | SFXMailField::Encode | SFXMailField::CharsetText | RFC2047 ( MIME : Message Header Extensions for Non-ASCII Text )


SFXMailField::DecodeTextB
指定された文字列を B デコードします。
[ protected, const ]
SFCError DecodeTextB(
    SFXAnsiStringPtr decoded   // [出力] B デコードされた文字列が格納された場所へのポインタ
    ACharConstPtr start        // [入力] B デコードする文字列の先頭へのポインタ
    ACharConstPtr end          // [入力] B デコードする文字列の終端へのポインタ
);

戻り値

  • 成功したとき: SFERR_NO_ERROR
  • 不正な文字があるとき(正確には 4 による剰余が 1 である位置にある文字が "=" のとき): SFERR_INVALID_FORMAT
  • decoded 引数が null であるとき: SFERR_INVALID_PARAM
  • メモリ不足のとき: SFERR_NO_MEMORY

解説

この関数は、 指定された文字列を B デコードします。

※ start / end 引数には B エンコード文字列を指定する必要があります。 B エンコードされていない場合(正確には 4 による剰余が 1 である位置にある文字が "=" のとき)、 SFERR_INVALID_FORMAT が返却されます。

[Caution] 注意

指定されたデータが B エンコードされていない場合も SFERR_NO_ERROR で終了する可能性があることに注意してください。

[Note] B エンコードについて

B エンコードは、RFC 2045 で定義されれいる Base64 エンコードと同じです。

B エンコードの詳細については RFC2047: 4.1. The "B" encoding を参照してください。

使用例

この関数は、以下のように SFXMailField::Decode 関数から呼び出されます。

/*public */SFCError SFXMailField::Decode(SFXAnsiStringConstRef string)
{
    SFCError error(SFERR_NO_ERROR);
    SFCError last;
    ACharConstPtr pos(string.GetBuffer());
    const ACharConstPtr end(pos + string.GetLength());
    ACharConstPtr nonEncodedStart;
    ACharConstPtr p;
    SFXAnsiString charset;
    AChar         method;
    ACharConstPtr encodedStart;
    ACharConstPtr encodedEnd;
    ACharConstPtr charsetStart;
    ACharConstPtr charsetEnd;
    ACharConstPtr textStart;
    ACharConstPtr textEnd;
    CharsetTextPtr cstr;

    Clear();
    if (!string.IsEmpty()) {
        SkipLWSP(&pos, end);
        nonEncodedStart = pos;
        for (; pos < end; ++pos) {
            if (*pos == '=' && pos + 1 < end && *(pos + 1) == '?') {// if "=?" found ...
                charsetEnd = null;
                textStart = null;
                encodedStart = pos; // hold start position of encoded word.
                charsetStart = pos + 2; // hold start position of charset name.
                method = 0; // find '?B?' or '?Q?'
                for (p = charsetStart; p < end; ++p) {
                    if (*p == '?' && p + 2 < end && *(p + 2) == '?') {
                        charsetEnd = p; // hold end position of charset.
                        method = SFXAscii::AsUpper(*(p + 1)); // get encoding method.
                        textStart = p + 3; // hold start position of encoded string.
                        break;
                    }
                }
                if (method == 'Q' || method == 'B') {
                    textEnd = null;
                    for (p = textStart; p < end; ++p) {// find "?=" position.
                        if (*p == '?' && p + 1 < end && *(p + 1) == '=') {// if "?=" found ...
                            textEnd = p;
                            break;
                        }
                        if (*p == CR && p + 1 < end && *(p + 1) == LF) {// if CRLF found ...
                            break;
                        }
                    }
                    if (textEnd != null) {
                        encodedEnd = textEnd + 2; // hold end position of encoded string.
                        if ((error = AddNonEncodedText(nonEncodedStart, encodedStart)) == SFERR_NO_ERROR) {
                            if ((cstr = ::new CharsetText) != null) {
                                if ((error = cstr->charset.Set(charsetStart, charsetEnd - charsetStart)) == SFERR_NO_ERROR) {
                                    cstr->charset.ToLower();
                                    if (method == 'Q') {
                                        error = DecodeTextQ(&cstr->text, textStart, textEnd);
                                    }
                                    else if (method == 'B') {
                                        error = DecodeTextB(&cstr->text, textStart, textEnd);
                                    }
                                    else {
                                        ASSERT(false);
                                    }
                                    if (error == SFERR_NO_ERROR) {
                                        if ((error = _array.InsertLast(cstr)) == SFERR_NO_ERROR) {
                                            pos = encodedEnd;
                                            //SkipLWSP(&pos, end);
                                            nonEncodedStart = pos;
                                            --pos;
                                        }
                                    }
                                }
                                if (error != SFERR_NO_ERROR) {
                                    ::delete cstr;
                                    break;
                                }
                            }
                            else {
                                error = SFERR_NO_MEMORY;
                                break;
                            }
                        }
                        else {
                            break;
                        }
                    }
                }
                else {
                    error = SFERR_INVALID_FORMAT;
                }
            }
        }
        last = AddNonEncodedText(nonEncodedStart, end);
        if (last != SFERR_NO_ERROR) {
            error = last;
        }
    }
    return error;
}// SFXMailField::Decode //

内部実装

この関数の内部実装は以下の通りです。

/*protected */SFCError SFXMailField::DecodeTextB(SFXAnsiStringPtr decoded, ACharConstPtr start, ACharConstPtr end) const
{
    SFCError error(SFERR_NO_ERROR);
    SFXBuffer out;

    if (decoded != null) {
        if (start < end) {
            if ((error = SFXMailUtility::DecodeBase64(start, end - start, &out)) == SFERR_NO_ERROR) {
                error = decoded->Attach(static_cast<ACharPtr>(out.GetBuffer()), out.GetSize() + 1);
                out.Detach();
            }
        }
        else {
            decoded->Clear();
        }
    }
    else {
        error = SFERR_INVALID_PARAM;
    }
    return error;
}// SFXMailField::DecodeTextB //

参照

SFXMailField::Decode | SFXMailField::DecodeTextQ | RFC2047: 4.1. The "B" encoding


SFXMailField::DecodeTextQ
指定された文字列を Q デコードします。
[ protected, const ]
SFCError DecodeTextQ(
    SFXAnsiStringPtr decoded   // [出力] デコードされた文字列が格納された場所へのポインタ
    ACharConstPtr start        // [入力] Q デコードする文字列の先頭へのポインタ
    ACharConstPtr end          // [入力] Q デコードする文字列の終端へのポインタ
);

戻り値

  • 成功したとき: SFERR_NO_ERROR
  • 不正な文字があるとき("=" に続く 2 文字が 16 進数の文字でないとき): SFERR_INVALID_FORMAT
  • decoded 引数が null であるとき: SFERR_INVALID_PARAM
  • メモリ不足のとき: SFERR_NO_MEMORY

解説

この関数は、 指定された文字列を Q デコードします。

※ start / end 引数に指定する文字列は Q エンコードされている必要があります。 Q エンコードで使用しない文字が含まれる場合(但し CRLF 改行文字を除く)、 SFERR_INVALID_FORMAT が返却されます。

[Note] 注意

引数に指定された入力データに含まれる CRLF 改行文字("\r\n")は飛ばされて処理されます。 この場合は SFERR_INVALID_FORMAT になりません。

[Note] 注意

Quoted-Printable エンコードの場合と異なり、 "_" 文字は空白文字(" ")にデコードされます。

[Note] Q エンコードについて

Q エンコードは、RFC 2045 で定義されれいる Quoted-Printable エンコードの変形です。

Quoted-Printable エンコードと同様に表示できない US-ASCII 文字はその文字の 2 桁の 16 進数に置き換えられ、 その前に "=" が置かれます。ただ、Q エンコードでは、空白文字は "=20" の代わりに "_" 文字に置き換えることも可能です。 そのため、"_" 文字は "=5F" で符号化されます(Quoted-Printable エンコードでは、"_" 文字は符号化する必要はありません)。

Q エンコードの詳細については RFC2047: 4.2. The "Q" encoding を参照してください。

使用例

この関数は、以下のように SFXMailField::Decode 関数から呼び出されます。

/*public */SFCError SFXMailField::Decode(SFXAnsiStringConstRef string)
{
    SFCError error(SFERR_NO_ERROR);
    SFCError last;
    ACharConstPtr pos(string.GetBuffer());
    const ACharConstPtr end(pos + string.GetLength());
    ACharConstPtr nonEncodedStart;
    ACharConstPtr p;
    SFXAnsiString charset;
    AChar         method;
    ACharConstPtr encodedStart;
    ACharConstPtr encodedEnd;
    ACharConstPtr charsetStart;
    ACharConstPtr charsetEnd;
    ACharConstPtr textStart;
    ACharConstPtr textEnd;
    CharsetTextPtr cstr;

    Clear();
    if (!string.IsEmpty()) {
        SkipLWSP(&pos, end);
        nonEncodedStart = pos;
        for (; pos < end; ++pos) {
            if (*pos == '=' && pos + 1 < end && *(pos + 1) == '?') {// if "=?" found ...
                charsetEnd = null;
                textStart = null;
                encodedStart = pos; // hold start position of encoded word.
                charsetStart = pos + 2; // hold start position of charset name.
                method = 0; // find '?B?' or '?Q?'
                for (p = charsetStart; p < end; ++p) {
                    if (*p == '?' && p + 2 < end && *(p + 2) == '?') {
                        charsetEnd = p; // hold end position of charset.
                        method = SFXAscii::AsUpper(*(p + 1)); // get encoding method.
                        textStart = p + 3; // hold start position of encoded string.
                        break;
                    }
                }
                if (method == 'Q' || method == 'B') {
                    textEnd = null;
                    for (p = textStart; p < end; ++p) {// find "?=" position.
                        if (*p == '?' && p + 1 < end && *(p + 1) == '=') {// if "?=" found ...
                            textEnd = p;
                            break;
                        }
                        if (*p == CR && p + 1 < end && *(p + 1) == LF) {// if CRLF found ...
                            break;
                        }
                    }
                    if (textEnd != null) {
                        encodedEnd = textEnd + 2; // hold end position of encoded string.
                        if ((error = AddNonEncodedText(nonEncodedStart, encodedStart)) == SFERR_NO_ERROR) {
                            if ((cstr = ::new CharsetText) != null) {
                                if ((error = cstr->charset.Set(charsetStart, charsetEnd - charsetStart)) == SFERR_NO_ERROR) {
                                    cstr->charset.ToLower();
                                    if (method == 'Q') {
                                        error = DecodeTextQ(&cstr->text, textStart, textEnd);
                                    }
                                    else if (method == 'B') {
                                        error = DecodeTextB(&cstr->text, textStart, textEnd);
                                    }
                                    else {
                                        ASSERT(false);
                                    }
                                    if (error == SFERR_NO_ERROR) {
                                        if ((error = _array.InsertLast(cstr)) == SFERR_NO_ERROR) {
                                            pos = encodedEnd;
                                            //SkipLWSP(&pos, end);
                                            nonEncodedStart = pos;
                                            --pos;
                                        }
                                    }
                                }
                                if (error != SFERR_NO_ERROR) {
                                    ::delete cstr;
                                    break;
                                }
                            }
                            else {
                                error = SFERR_NO_MEMORY;
                                break;
                            }
                        }
                        else {
                            break;
                        }
                    }
                }
                else {
                    error = SFERR_INVALID_FORMAT;
                }
            }
        }
        last = AddNonEncodedText(nonEncodedStart, end);
        if (last != SFERR_NO_ERROR) {
            error = last;
        }
    }
    return error;
}// SFXMailField::Decode //

内部実装

この関数の内部実装は以下の通りです。

/*protected */SFCError SFXMailField::DecodeTextQ(SFXAnsiStringPtr decoded, ACharConstPtr start, ACharConstPtr end) const
{
    SFCError error(SFERR_NO_ERROR);
    ACharPtr buf;
    ACharConstPtr pos;
    SInt32 count(0);
    SInt16 c;

    if (decoded != null) {
        if (start < end) {
            if ((error = decoded->SetLength(end - start)) == SFERR_NO_ERROR) {// temporarily allocate sufficient memory.
                buf = decoded->GetBuffer();
                for (pos = start; pos < end; ++pos) {
                    if (*pos == '=' && pos + 2 < end) {
                        if ((c = SFXMailUtility::HexToByte(*(pos + 1), *(pos + 2))) == -1) {
                            error = SFERR_INVALID_FORMAT;
                            break;
                        }
                        buf[count] = static_cast<AChar>(c);
                        ++count;
                        pos += 2;
                    }
                    else if (*pos == '_') {
                        buf[count] = ' ';
                        ++count;
                    }
                    else {
                        buf[count] = *pos;
                        ++count;
                    }
                }
                error = decoded->SetLength(count);
            }
        }
        else {
            decoded->Clear();
        }
    }
    else {
        error = SFERR_INVALID_PARAM;
    }
    return error;
}// SFXMailField::DecodeTextQ //

参照

SFXMailField::Decode | SFXMailField::DecodeTextB | RFC2047: 4.2. The "Q" encoding


SFXMailField::Encode
内部で保持している「テキストとエンコード名」のペアの配列をエンコードして送信するメールヘッダー内のフィールド値を作成します。
[ public, const ]
SFCError Encode(
    SFXAnsiStringPtr string   // [出力] エンコードされた文字列が格納された場所へのポインタ
);

引数

string

出力先を指定します。

戻り値

  • 成功したとき: SFERR_NO_ERROR
  • string 引数が null であるとき: SFERR_INVALID_PARAM
  • メモリ不足のとき: SFERR_NO_MEMORY

解説

この関数は、 内部で保持している「テキストとエンコード名」のペアの配列から送信するメールのヘッダー内のフィールド値を作成します。

[Note] 注意

string 引数に出力される文字列は、送信するメールのヘッダー内のフィールド値です。

「テキストとエンコード名」のペアの「テキスト」が日本語である場合は、B エンコードが行われます。 エンコード名が空である場合(テキストが US-ASCII 文字列である場合)、B エンコードは行われません。

「テキスト」が日本語である場合、 その「テキスト」は JIS コード("ISO-2022-JP")でエンコードされています。

使用例

以下は、Shift_JIS コードの文字列をメールヘッダーのフィールド値に変換するコードです。

// Shift_JIS コードの文字列を JIS コードへ変換し、更に B エンコードする
/*private */SFCError SFXMailMessage::ConvertSjisToBEncode(SFXAnsiStringConstRef sjis, SFXAnsiStringPtr bCode) const
{
    SFCError error;
    SFXAnsiString jis;
    SFXAnsiString temp;
    SFXMailField encoder;
    ACharConstPtr pos;
    ACharConstPtr end;
    ACharConstPtr ip;
    Bool kanji(false);

    // Shift_JIS コードから JIS コードへ変換する
    if ((error = SFXMailUtility::ShiftJISToJIS(sjis, &jis)) == SFERR_NO_ERROR) {

        pos = jis.GetBuffer();
        end = pos + jis.GetLength();
        ip = pos;
        while (pos < end) {

            if (pos + 2 < end && *pos == 0x1B && *(pos + 1) == '$' && (*(pos + 2) == '@' || *(pos + 2) == 'B')) {

                kanji = true;
                if ((error = temp.Set(ip, pos - ip)) == SFERR_NO_ERROR) {

                    // US-ASCII 文字列の場合:
                    // 内部で保持する「テキストとエンコード名」のペアの配列に追加する
                    if ((error = encoder.Add(SFXAnsiString::EmptyInstance(), temp)) != SFERR_NO_ERROR) {

                        break;
                    }
                }
                else {

                    break;
                }
                ip = pos;
            }
            else if (pos + 2 < end && *pos == 0x1B && *(pos + 1) == '(' && (*(pos + 2) == 'B' || *(pos + 2) == 'J')) {

                pos += 3;
                if ((error = temp.Set(ip, pos - ip)) == SFERR_NO_ERROR) {

                    // JIS 日本語文字列の場合:
                    // 内部で保持する「テキストとエンコード名」のペアの配列に追加する
                    if ((error = encoder.Add("ISO-2022-JP", temp)) != SFERR_NO_ERROR) {

                        break;
                    }
                }
                else {

                    break;
                }
                ip = pos;
            }
            ++pos;
        }
        temp.Set(ip, pos - ip);

        // 内部で保持する「テキストとエンコード名」のペアの配列に追加する
        if (kanji) {

            error = encoder.Add("ISO-2022-JP", temp);
        }
        else {

            error = encoder.Add(SFXAnsiString::EmptyInstance(), temp);
        }
        if (error == SFERR_NO_ERROR) {

            // 内部で保持する「テキストとエンコード名」のペアの配列を、
            // 更に B エンコードし、メールヘッダーのフィールド値に変換する
            error = encoder.Encode(bCode);
        }
    }
    return error;
}// SFCError SFXMailMessage::ConvertSjisToBEncode //

内部実装

この関数の内部実装は以下の通りです。

/*public */SFCError SFXMailField::Encode(SFXAnsiStringPtr string) const
{
    SFCError error(SFERR_NO_ERROR);
    CharsetTextArray::Enumerator itor;
    SFXBuffer in;
    SFXBuffer out;
    CharsetTextPtr cstr;

    if (string != null) {
        string->Clear();
        if (_array.GetSize() > 0) {
            itor = _array.GetFirstEnumerator();
            while (itor.HasNext()) {
                cstr = itor.GetNext();
                if (cstr->charset.IsEmpty()) {
                    error = string->Add(cstr->text);
                }
                else {
                    if ((error = in.Attach(cstr->text.GetBuffer(), cstr->text.GetLength())) == SFERR_NO_ERROR) {
                        error = SFXMailUtility::EncodeBase64(in, &out, 0, SFXAnsiString::EmptyInstance());
                        in.Detach();
                        if (error == SFERR_NO_ERROR) {
                            if ((error = string->Add("=?")) == SFERR_NO_ERROR) {
                                if ((error = string->Add(cstr->charset)) == SFERR_NO_ERROR) {
                                    if ((error = string->Add("?B?")) == SFERR_NO_ERROR) {
                                        if ((error = string->Add(static_cast<ACharConstPtr>(out.GetBuffer()), out.GetSize())) == SFERR_NO_ERROR) {
                                            error = string->Add("?=");
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (error != SFERR_NO_ERROR) {
                        break;
                    }
                }
            }
        }
    }
    else {
        error = SFERR_INVALID_PARAM;
    }
    return error;
}// SFXMailField::Encode //

参照

SFXMailUtility::EncodeBase64 | SFXMailField::Decode | SFXMailField::Add


SFXMailField::GetCharsetText
指定されたインデックスの「テキストとエンコード名」のペアを取得します。
[ public, const ]
CharsetTextPtr GetCharsetText(
    SInt32 index   // [入力]「テキストとエンコード名」のペアのインデックス
);

引数

index

「テキストとエンコード名」のペアのインデックスを指定します。

戻り値

SFXMailField::CharsetText で表された内部表現を返します。

解説

この関数は、指定されたインデックスの「テキストとエンコード名」のペア (SFXMailField::CharsetText)を取得します。

[Note] 注意

インデックスは、0 から SFXMailField::GetSize 関数の戻り値まで指定できます。

内部実装

この関数の内部実装は以下の通りです。

/*public */inline SFXMailField::CharsetTextPtr SFXMailField::GetCharsetText(SInt32 index) const
{
    return (0 <= index && index < GetSize()) ? (_array[index]) : (null);
}// SFXMailField::GetCharsetText //

参照

SFXMailField::Add | SFXMailField::AddNonEncodedText | SFXMailField::GetSize | SFXMailField::CharsetText


SFXMailField::GetSize
内部に保持されている「テキストとエンコード名」のペアの総数を取得します。
[ public, const ]
SInt32 GetSize(Void);

戻り値

内部表現の断片数

解説

この関数は、内部に保持されている「テキストとエンコード名」のペア (SFXMailField::CharsetText)の総数を取得します。

内部実装

この関数の内部実装は以下の通りです。

/*public */inline SInt32 SFXMailField::GetSize(Void) const
{
    return _array.GetSize();
}// SFXMailField::GetSize //

参照

SFXMailField::Add | SFXMailField::AddNonEncodedText | SFXMailField::CharsetText


SFXMailField::IsLWSP
指定された文字が LWSP(空白文字、水平タブ、改行文字、または復帰文字)であるかどうかを判定します。
[ protected, static ]
Bool IsLWSP(
    AChar c   // [入力] 判定する文字
);

戻り値

  • LWSP(空白文字、水平タブ、改行文字、または復帰文字)であるとき: true
  • そうでないとき: false

解説

この関数は、 指定された文字が LWSP(空白文字、水平タブ、改行文字、または復帰文字)であるかどうかを判定します。

内部実装

この関数の内部実装は以下の通りです。

/*protected static */Bool SFXMailField::IsLWSP(AChar c)
{
    return (c == ' ' || c == '\t' || c == CR || c == LF);
}// SFXMailField::IsLWSP //

参照

SFXMailField::SkipLWSP


SFXMailField::SkipLWSP
ポインタを LWSP(空白文字、水平タブ、改行文字、または復帰文字)以外の文字まで進めます。
[ protected, static ]
Void SkipLWSP(
    ACharConstHandle start   // [入力] 探索のスタート位置へのポインタ、[出力] LWSP(空白文字、水平タブ、改行文字、または復帰文字)以外の文字の位置または探索対象の文字列の終端へのポインタ
    ACharConstPtr end        // [入力] 探索対象の文字列の終端へのポインタ
);

解説

この関数は、ポインタを start 引数に格納された位置からスタートして、次の LWSP(空白文字、水平タブ、改行文字、または復帰文字)以外の文字の位置まで進めます。

start 引数には、次の LWSP(空白文字、水平タブ、改行文字、または復帰文字)以外の文字を指すポインタが返却されます。 LWSP(空白文字、水平タブ、改行文字、または復帰文字)以外の文字が見つからなかった場合、 探索対象の文字列の終端へのポインタ(end 引数と同じ値)が返却されます。

[Note] 注意

探索のスタート位置が終了位置(end 引数に格納されている位置)よりも右にある場合は何も行いません。

内部実装

この関数の内部実装は以下の通りです。

/*protected static */Void SFXMailField::SkipLWSP(ACharConstHandle start, ACharConstPtr end)
{
    ACharConstPtr pos(*start);

    while (pos < end && IsLWSP(*pos)) {
        ++pos;
    }
    *start = pos;
}// SFXMailField::SkipLWSP //

参照

SFXMailField::IsLWSP


SFXMailField::CharsetText
「テキストとエンコード名」のペアを表す構造体です。
SFMTYPEDEFCLASS(CharsetText)
struct CharsetText {
  SFXAnsiString charset;  // エンコード名(文字コード)
  SFXAnsiString text;     // テキスト
};

解説

「テキストとエンコード名」のペアを表す構造体です。

エンコード名を保持する charset メンバと、テキストを保持する text メンバから構成されます。

文字コードとエンコード名の対応は以下の通りです。 エンコード名に空文字列[SFXAnsiString::EmptyInstance()]の指定も可能ですが、 この場合は、us-ascii として処理されます。

表 218. 文字コードとエンコード名

文字コード エンコード名
ANSI us-ascii
JIS iso-2022-jp
Shift_JIS shift_jis
EUC euc-jp
UTF-7 utf-7
UTF-8 utf-8
Latin 1 iso-8859-1
[Note] 注意

一般に、メールでは日本語の文字コードとしては JIS コード("iso-2022-jp")が利用されます。

参照

SFXMailField::Add | SFXMailField::AddNonEncodedText | SFXMailField::GetCharsetText