KMime

kmime_types.cpp
1/* -*- c++ -*-
2 kmime_header_types.cpp
3
4 KMime, the KDE Internet mail/usenet news message library.
5 SPDX-FileCopyrightText: 2001-2002 Marc Mutz <mutz@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#include "kmime_types.h"
11#include "kmime_codecs_p.h"
12#include "kmime_header_parsing.h"
13#include "kmime_header_parsing_p.h"
14#include "kmime_util.h"
15#include "kmime_util_p.h"
16#include "kmime_debug.h"
17
18#include <KCodecs>
19
20#include <QStringList>
21#include <QUrl>
22
23namespace KMime
24{
25
26namespace Types
27{
28
29// QUrl::fromAce is extremely expensive, so only use it when necessary.
30// Fortunately, the presence of IDNA is readily detected with a substring match...
31static inline QString QUrl_fromAce_wrapper(const QString &domain)
32{
33 if (domain.contains(QLatin1StringView("xn--"))) {
34 return QUrl::fromAce(domain.toLatin1());
35 } else {
36 return domain;
37 }
38}
39
40static QString addr_spec_as_string(const AddrSpec &as, bool pretty)
41{
42 if (as.isEmpty()) {
43 return {};
44 }
45
46 static const QChar dotChar = QLatin1Char('.');
47 static const QChar backslashChar = QLatin1Char('\\');
48 static const QChar quoteChar = QLatin1Char('"');
49
50 bool needsQuotes = false;
51 QString result;
52 result.reserve(as.localPart.length() + as.domain.length() + 1);
53 for (int i = 0 ; i < as.localPart.length() ; ++i) {
54 const QChar ch = as.localPart.at(i);
55 if (ch == dotChar || isAText(ch.toLatin1())) {
56 result += ch;
57 } else {
58 needsQuotes = true;
59 if (ch == backslashChar || ch == quoteChar) {
60 result += backslashChar;
61 }
62 result += ch;
63 }
64 }
65 const QString dom = pretty ? QUrl_fromAce_wrapper(as.domain) : as.domain ;
66 if (needsQuotes) {
67 result = quoteChar + result + quoteChar;
68 }
69 if (dom.isEmpty()) {
70 return result;
71 } else {
72 result += QLatin1Char('@');
73 result += dom;
74 return result;
75 }
76}
77
78QString AddrSpec::asString() const
79{
80 return addr_spec_as_string(*this, false);
81}
82
83QString AddrSpec::asPrettyString() const
84{
85 return addr_spec_as_string(*this, true);
86}
87
88bool AddrSpec::isEmpty() const
89{
90 return localPart.isEmpty() && domain.isEmpty();
91}
92
94{
95 QByteArray result;
96 const QString asString = addr_spec_as_string(mAddrSpec, false);
97 if (!asString.isEmpty()) {
98 result = asString.toLatin1();
99 }
100 return result;
101 //return mAddrSpec.asString().toLatin1();
102}
103
104AddrSpec Mailbox::addrSpec() const
105{
106 return mAddrSpec;
107}
108
110{
111 return mDisplayName;
112}
113
114void Mailbox::setAddress(const AddrSpec &addr)
115{
116 mAddrSpec = addr;
117}
118
120{
121 const char *cursor = addr.constData();
122 if (!HeaderParsing::parseAngleAddr(cursor,
123 cursor + addr.length(), mAddrSpec)) {
124 if (!HeaderParsing::parseAddrSpec(cursor, cursor + addr.length(),
125 mAddrSpec)) {
126 qCWarning(KMIME_LOG) << "Mailbox: Invalid address";
127 return;
128 }
129 }
130}
131
132void Mailbox::setName(const QString &name)
133{
134 mDisplayName = removeBidiControlChars(name);
135}
136
138 const QByteArray &defaultCharset)
139{
140 QByteArray cs;
141 setName(KCodecs::decodeRFC2047String(name, &cs, defaultCharset));
142}
143
145{
146 return !mAddrSpec.isEmpty();
147}
148
150{
151 return !mDisplayName.isEmpty();
152}
153
155{
156 if (!hasName()) {
157 return QLatin1StringView(address());
158 }
159 QString s = name();
160 if (quoting != QuoteNever) {
161 addQuotes(s, quoting == QuoteAlways /*bool force*/);
162 }
163
164 if (hasAddress()) {
165 s +=
167 }
168 return s;
169}
170
172{
173 from7BitString(encodeRFC2047Sentence(s, "utf-8"));
174}
175
177{
178 const char *cursor = s.constData();
179 HeaderParsing::parseMailbox(cursor, cursor + s.length(), *this);
180}
181
183{
184 if (!hasName()) {
185 return address();
186 }
187 QByteArray rv;
188 if (isUsAscii(name())) {
189 QByteArray tmp = name().toLatin1();
190 addQuotes(tmp, false);
191 rv += tmp;
192 } else {
193 rv += encodeRFC2047String(name(), encCharset, true);
194 }
195 if (hasAddress()) {
196 rv += " <" + address() + '>';
197 }
198 return rv;
199}
200
202 return listFrom7BitString(encodeRFC2047Sentence(s, "utf-8"));
203}
204
207 QList<KMime::Types::Address> maybeAddressList;
208 const char *scursor = s.constData();
209 if (!HeaderParsing::parseAddressList(scursor, scursor + s.size(), maybeAddressList)) {
210 return res;
211 }
212
213 res.reserve(maybeAddressList.size());
214 for (const auto &it : std::as_const(maybeAddressList)) {
215 res += (it).mailboxList;
216 }
217 return res;
218}
219
221 if (mailboxes.size() == 1) { // QStringList free fast-path for the common case
222 return mailboxes.at(0).prettyAddress();
223 }
224
225 QStringList rv;
226 rv.reserve(mailboxes.count());
227 for (const Types::Mailbox &mbox : mailboxes) {
228 rv.append(mbox.prettyAddress());
229 }
230 return rv.join(QLatin1StringView(", "));
231}
232
233} // namespace Types
234
235} // namespace KMime
Represents an (email address, display name) pair according RFC 2822, section 3.4.
Definition kmime_types.h:38
void from7BitString(const QByteArray &s)
Parses the given 7bit encoded string.
void setName(const QString &name)
Sets the name.
QString name() const
Returns the display name.
bool hasAddress() const
Returns true if this mailbox has an address.
static QList< Mailbox > listFrom7BitString(const QByteArray &s)
Returns a list of mailboxes from an encoded 7bit string.
void setNameFrom7Bit(const QByteArray &name, const QByteArray &defaultCharset=QByteArray())
Sets the name based on a 7bit encoded string.
QByteArray as7BitString(const QByteArray &encCharset) const
Returns a 7bit transport encoded representation of this mailbox.
bool hasName() const
Returns true if this mailbox has a display name.
Quoting
Describes how display names should be quoted.
Definition kmime_types.h:91
@ QuoteAlways
quoted, like commas or quote signs.
Definition kmime_types.h:99
@ QuoteNever
Don't quote display names at all.
Definition kmime_types.h:92
QString prettyAddress(Quoting quoting=QuoteNever) const
Overloaded method that gives more control over the quoting of the display name.
void setAddress(const AddrSpec &addr)
Sets the email address.
static QList< Mailbox > listFromUnicodeString(const QString &s)
Returns a list of mailboxes from an unicode string.
void fromUnicodeString(const QString &s)
Parses the given unicode string.
QByteArray address() const
Returns a string representation of the email address, without the angle brackets.
static QString listToUnicodeString(const QList< Mailbox > &mailboxes)
Returns a unicode string representing the given list of mailboxes.
KCODECS_EXPORT QString decodeRFC2047String(QByteArrayView src, QByteArray *usedCS, const QByteArray &defaultCS=QByteArray(), CharsetOption option=NoOption)
const char * constData() const const
qsizetype length() const const
qsizetype size() const const
char toLatin1() const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype count() const const
void reserve(qsizetype size)
qsizetype size() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
void reserve(qsizetype size)
QByteArray toLatin1() const const
QString join(QChar separator) const const
QString fromAce(const QByteArray &domain, AceProcessingOptions options)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:12 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.