1 | /* -*- c++ -*- |
2 | SPDX-FileCopyrightText: 2001-2002 Marc Mutz <mutz@kde.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | /** |
7 | @file |
8 | This file is part of the API for handling @ref MIME data and |
9 | defines the @ref Base64 and @ref RFC2047B @ref Codec classes. |
10 | |
11 | @brief |
12 | Defines the Base64Codec and Rfc2047BEncodingCodec classes. |
13 | |
14 | @authors Marc Mutz \<mutz@kde.org\> |
15 | |
16 | @glossary @anchor Base64 @anchor base64 @b base64: |
17 | a binary to text encoding scheme based on @ref RFC1421. |
18 | |
19 | @glossary @anchor RFC1421 @anchor rfc1421 @b RFC @b 1421: |
20 | RFC that defines the <a href="http://tools.ietf.org/html/rfc1421"> |
21 | Privacy Enhancement for Internet Electronic Mail: Part I: |
22 | Message Encryption and Authentication Procedures</a>. |
23 | |
24 | @glossary @anchor RFC2045 @anchor rfc2045 @b RFC @b 2045: |
25 | RFC that defines the <a href="http://tools.ietf.org/html/rfc2045"> |
26 | MIME Part One: Format of Internet Message Bodies</a>. |
27 | |
28 | @glossary @anchor RFC2047 @anchor rfc2047 @b RFC @b 2047: |
29 | RFC that defines the <a href="http://tools.ietf.org/html/rfc2047"> |
30 | MIME Part Three: Message Header Extensions for Non-ASCII Text</a>. |
31 | |
32 | @glossary @anchor RFC2047B @anchor rfc2047b @b RFC @b 2047B: |
33 | Section 4.1 of @ref RFC2047. |
34 | */ |
35 | |
36 | #ifndef KCODECS_BASE64_H |
37 | #define KCODECS_BASE64_H |
38 | |
39 | #include "kcodecs.h" |
40 | |
41 | namespace KCodecs |
42 | { |
43 | /** |
44 | @brief |
45 | A class representing the @ref codec for @ref Base64 as specified in |
46 | @ref RFC2045 |
47 | */ |
48 | class Base64Codec : public Codec |
49 | { |
50 | public: |
51 | /** |
52 | Constructs a Base64 codec. |
53 | */ |
54 | Base64Codec() |
55 | : Codec() |
56 | { |
57 | } |
58 | |
59 | /** |
60 | Destroys the codec. |
61 | */ |
62 | ~Base64Codec() override |
63 | { |
64 | } |
65 | |
66 | /** |
67 | @copydoc |
68 | Codec::name() |
69 | */ |
70 | const char *name() const override |
71 | { |
72 | return "base64" ; |
73 | } |
74 | |
75 | /** |
76 | @copydoc |
77 | Codec::maxEncodedSizeFor() |
78 | */ |
79 | qsizetype maxEncodedSizeFor(qsizetype insize, NewlineType newline) const override |
80 | { |
81 | // first, the total number of 4-char packets will be: |
82 | qsizetype totalNumPackets = (insize + 2) / 3; |
83 | // now, after every 76/4'th packet there needs to be a linebreak: |
84 | qsizetype numLineBreaks = totalNumPackets / (76 / 4); |
85 | // and at the very end, too: |
86 | ++numLineBreaks; |
87 | // putting it all together, we have: |
88 | return 4 * totalNumPackets + (newline == Codec::NewlineCRLF ? 2 : 1) * numLineBreaks; |
89 | } |
90 | |
91 | /** |
92 | @copydoc |
93 | Codec::maxDecodedSizeFor() |
94 | */ |
95 | qsizetype maxDecodedSizeFor(qsizetype insize, NewlineType newline = Codec::NewlineLF) const override |
96 | { |
97 | // assuming all characters are part of the base64 stream (which |
98 | // does almost never hold due to required linebreaking; but |
99 | // additional non-base64 chars don't affect the output size), each |
100 | // 4-tupel of them becomes a 3-tupel in the decoded octet |
101 | // stream. So: |
102 | qsizetype result = ((insize + 3) / 4) * 3; |
103 | // but all of them may be \n, so |
104 | if (newline == Codec::NewlineCRLF) { |
105 | result *= 2; // :-o |
106 | } |
107 | |
108 | return result; |
109 | } |
110 | |
111 | /** |
112 | @copydoc |
113 | Codec::makeEncoder() |
114 | */ |
115 | Encoder *makeEncoder(NewlineType newline = Codec::NewlineLF) const override; |
116 | |
117 | /** |
118 | @copydoc |
119 | Codec::makeDecoder() |
120 | */ |
121 | Decoder *makeDecoder(NewlineType newline = Codec::NewlineLF) const override; |
122 | }; |
123 | |
124 | /** |
125 | @brief |
126 | A class representing the @ref codec for the B encoding as specified |
127 | in @ref RFC2047B. |
128 | */ |
129 | class Rfc2047BEncodingCodec : public Base64Codec |
130 | { |
131 | public: |
132 | /** |
133 | Constructs a RFC2047B codec. |
134 | */ |
135 | Rfc2047BEncodingCodec() |
136 | : Base64Codec() |
137 | { |
138 | } |
139 | |
140 | /** |
141 | Destroys the codec. |
142 | */ |
143 | ~Rfc2047BEncodingCodec() override |
144 | { |
145 | } |
146 | |
147 | /** |
148 | @copydoc |
149 | Codec::name() |
150 | */ |
151 | const char *name() const override |
152 | { |
153 | return "b" ; |
154 | } |
155 | |
156 | /** |
157 | @copydoc |
158 | Codec::maxEncodedSizeFor() |
159 | */ |
160 | qsizetype maxEncodedSizeFor(qsizetype insize, NewlineType newline = Codec::NewlineLF) const override |
161 | { |
162 | Q_UNUSED(newline); |
163 | // Each (begun) 3-octet triple becomes a 4 char quartet, so: |
164 | return ((insize + 2) / 3) * 4; |
165 | } |
166 | |
167 | /** |
168 | @copydoc |
169 | Codec::maxDecodedSizeFor() |
170 | */ |
171 | qsizetype maxDecodedSizeFor(qsizetype insize, NewlineType newline = Codec::NewlineLF) const override |
172 | { |
173 | Q_UNUSED(newline); |
174 | // Each 4-char quartet becomes a 3-octet triple, the last one |
175 | // possibly even less. So: |
176 | return ((insize + 3) / 4) * 3; |
177 | } |
178 | |
179 | /** |
180 | @copydoc |
181 | Codec::makeEncoder() |
182 | */ |
183 | Encoder *makeEncoder(NewlineType newline = Codec::NewlineLF) const override; |
184 | }; |
185 | |
186 | } // namespace KCodecs |
187 | |
188 | #endif // KCODECS_BASE64_H |
189 | |