File indexing completed on 2024-04-21 03:53:01

0001 /*  -*- c++ -*-
0002     SPDX-FileCopyrightText: 2001-2002 Marc Mutz <mutz@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 /**
0007   @file
0008   This file is part of the API for handling @ref MIME data and
0009   defines the @ref Base64 and @ref RFC2047B @ref Codec classes.
0010 
0011   @brief
0012   Defines the Base64Codec and Rfc2047BEncodingCodec classes.
0013 
0014   @authors Marc Mutz \<mutz@kde.org\>
0015 
0016   @glossary @anchor Base64 @anchor base64 @b base64:
0017   a binary to text encoding scheme based on @ref RFC1421.
0018 
0019   @glossary @anchor RFC1421 @anchor rfc1421 @b RFC @b 1421:
0020   RFC that defines the <a href="http://tools.ietf.org/html/rfc1421">
0021   Privacy Enhancement for Internet Electronic Mail:  Part I:
0022   Message Encryption and Authentication Procedures</a>.
0023 
0024   @glossary @anchor RFC2045 @anchor rfc2045 @b RFC @b 2045:
0025   RFC that defines the <a href="http://tools.ietf.org/html/rfc2045">
0026   MIME Part One: Format of Internet Message Bodies</a>.
0027 
0028   @glossary @anchor RFC2047 @anchor rfc2047 @b RFC @b 2047:
0029   RFC that defines the <a href="http://tools.ietf.org/html/rfc2047">
0030   MIME Part Three: Message Header Extensions for Non-ASCII Text</a>.
0031 
0032   @glossary @anchor RFC2047B @anchor rfc2047b @b RFC @b 2047B:
0033   Section 4.1 of @ref RFC2047.
0034 */
0035 
0036 #ifndef KCODECS_BASE64_H
0037 #define KCODECS_BASE64_H
0038 
0039 #include "kcodecs.h"
0040 
0041 namespace KCodecs
0042 {
0043 /**
0044   @brief
0045   A class representing the @ref codec for @ref Base64 as specified in
0046   @ref RFC2045
0047 */
0048 class Base64Codec : public Codec
0049 {
0050 public:
0051     /**
0052       Constructs a Base64 codec.
0053     */
0054     Base64Codec()
0055         : Codec()
0056     {
0057     }
0058 
0059     /**
0060       Destroys the codec.
0061     */
0062     ~Base64Codec() override
0063     {
0064     }
0065 
0066     /**
0067       @copydoc
0068       Codec::name()
0069     */
0070     const char *name() const override
0071     {
0072         return "base64";
0073     }
0074 
0075     /**
0076       @copydoc
0077       Codec::maxEncodedSizeFor()
0078     */
0079     qsizetype maxEncodedSizeFor(qsizetype insize, NewlineType newline) const override
0080     {
0081         // first, the total number of 4-char packets will be:
0082         qsizetype totalNumPackets = (insize + 2) / 3;
0083         // now, after every 76/4'th packet there needs to be a linebreak:
0084         qsizetype numLineBreaks = totalNumPackets / (76 / 4);
0085         // and at the very end, too:
0086         ++numLineBreaks;
0087         // putting it all together, we have:
0088         return 4 * totalNumPackets + (newline == Codec::NewlineCRLF ? 2 : 1) * numLineBreaks;
0089     }
0090 
0091     /**
0092       @copydoc
0093       Codec::maxDecodedSizeFor()
0094     */
0095     qsizetype maxDecodedSizeFor(qsizetype insize, NewlineType newline = Codec::NewlineLF) const override
0096     {
0097         // assuming all characters are part of the base64 stream (which
0098         // does almost never hold due to required linebreaking; but
0099         // additional non-base64 chars don't affect the output size), each
0100         // 4-tupel of them becomes a 3-tupel in the decoded octet
0101         // stream. So:
0102         qsizetype result = ((insize + 3) / 4) * 3;
0103         // but all of them may be \n, so
0104         if (newline == Codec::NewlineCRLF) {
0105             result *= 2; // :-o
0106         }
0107 
0108         return result;
0109     }
0110 
0111     /**
0112       @copydoc
0113       Codec::makeEncoder()
0114     */
0115     Encoder *makeEncoder(NewlineType newline = Codec::NewlineLF) const override;
0116 
0117     /**
0118       @copydoc
0119       Codec::makeDecoder()
0120     */
0121     Decoder *makeDecoder(NewlineType newline = Codec::NewlineLF) const override;
0122 };
0123 
0124 /**
0125   @brief
0126   A class representing the @ref codec for the B encoding as specified
0127   in @ref RFC2047B.
0128 */
0129 class Rfc2047BEncodingCodec : public Base64Codec
0130 {
0131 public:
0132     /**
0133       Constructs a RFC2047B codec.
0134     */
0135     Rfc2047BEncodingCodec()
0136         : Base64Codec()
0137     {
0138     }
0139 
0140     /**
0141       Destroys the codec.
0142     */
0143     ~Rfc2047BEncodingCodec() override
0144     {
0145     }
0146 
0147     /**
0148       @copydoc
0149       Codec::name()
0150     */
0151     const char *name() const override
0152     {
0153         return "b";
0154     }
0155 
0156     /**
0157       @copydoc
0158       Codec::maxEncodedSizeFor()
0159     */
0160     qsizetype maxEncodedSizeFor(qsizetype insize, NewlineType newline = Codec::NewlineLF) const override
0161     {
0162         Q_UNUSED(newline);
0163         // Each (begun) 3-octet triple becomes a 4 char quartet, so:
0164         return ((insize + 2) / 3) * 4;
0165     }
0166 
0167     /**
0168       @copydoc
0169       Codec::maxDecodedSizeFor()
0170     */
0171     qsizetype maxDecodedSizeFor(qsizetype insize, NewlineType newline = Codec::NewlineLF) const override
0172     {
0173         Q_UNUSED(newline);
0174         // Each 4-char quartet becomes a 3-octet triple, the last one
0175         // possibly even less. So:
0176         return ((insize + 3) / 4) * 3;
0177     }
0178 
0179     /**
0180       @copydoc
0181       Codec::makeEncoder()
0182     */
0183     Encoder *makeEncoder(NewlineType newline = Codec::NewlineLF) const override;
0184 };
0185 
0186 } // namespace KCodecs
0187 
0188 #endif // KCODECS_BASE64_H