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 <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "kmime_types.h"
11 #include "kmime_codecs.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 
23 namespace KMime
24 {
25 
26 namespace 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...
31 static inline QString QUrl_fromAce_wrapper(const QString &domain)
32 {
33  if (domain.contains(QLatin1String("xn--"))) {
34  return QUrl::fromAce(domain.toLatin1());
35  } else {
36  return domain;
37  }
38 }
39 
40 static QString addr_spec_as_string(const AddrSpec &as, bool pretty)
41 {
42  if (as.isEmpty()) {
43  return QString();
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 
78 QString AddrSpec::asString() const
79 {
80  return addr_spec_as_string(*this, false);
81 }
82 
83 QString AddrSpec::asPrettyString() const
84 {
85  return addr_spec_as_string(*this, true);
86 }
87 
88 bool 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 
104 AddrSpec Mailbox::addrSpec() const
105 {
106  return mAddrSpec;
107 }
108 
110 {
111  return mDisplayName;
112 }
113 
114 void 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 
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 
149 bool Mailbox::hasName() const
150 {
151  return !mDisplayName.isEmpty();
152 }
153 
155 {
156  if (!hasName()) {
157  return QLatin1String(address());
158  }
159  QString s = name();
160  if (quoting != QuoteNever) {
161  addQuotes(s, quoting == QuoteAlways /*bool force*/);
162  }
163 
164  if (hasAddress()) {
165  s += QLatin1String(" <") + QLatin1String(address()) + QLatin1Char('>');
166  }
167  return s;
168 }
169 
171 {
172  from7BitString(encodeRFC2047Sentence(s, "utf-8"));
173 }
174 
176 {
177  const char *cursor = s.constData();
178  HeaderParsing::parseMailbox(cursor, cursor + s.length(), *this);
179 }
180 
182 {
183  if (!hasName()) {
184  return address();
185  }
186  QByteArray rv;
187  if (isUsAscii(name())) {
188  QByteArray tmp = name().toLatin1();
189  addQuotes(tmp, false);
190  rv += tmp;
191  } else {
192  rv += encodeRFC2047String(name(), encCharset, true);
193  }
194  if (hasAddress()) {
195  rv += " <" + address() + '>';
196  }
197  return rv;
198 }
199 
201 {
202  return listFrom7BitString(encodeRFC2047Sentence(s, "utf-8"));
203 }
204 
206 {
208  QVector<KMime::Types::Address> maybeAddressList;
209  const char *scursor = s.constData();
210  if (!HeaderParsing::parseAddressList(scursor, scursor + s.size(), maybeAddressList)) {
211  return res;
212  }
213 
214  res.reserve(maybeAddressList.size());
215  for (const auto &it : qAsConst(maybeAddressList)) {
216  res += (it).mailboxList;
217  }
218  return res;
219 }
220 
222 {
223  if (mailboxes.size() == 1) // QStringList free fast-path for the common case
224  return mailboxes.at(0).prettyAddress();
225 
226  QStringList rv;
227  rv.reserve(mailboxes.count());
228  for (const Types::Mailbox &mbox : mailboxes) {
229  rv.append(mbox.prettyAddress());
230  }
231  return rv.join(QLatin1String(", "));
232 }
233 
234 } // namespace Types
235 
236 } // namespace KMime
static QVector< Mailbox > listFromUnicodeString(const QString &s)
Returns a list of mailboxes from an unicode string.
QString fromAce(const QByteArray &domain)
QByteArray address() const
Returns a string representation of the email address, without the angle brackets. ...
Definition: kmime_types.cpp:93
Represents an (email address, display name) pair according RFC 2822, section 3.4. ...
Definition: kmime_types.h:38
void reserve(int alloc)
QByteArray as7BitString(const QByteArray &encCharset) const
Returns a 7bit transport encoded representation of this mailbox.
QString prettyAddress(Quoting quoting=QuoteNever) const
Overloaded method that gives more control over the quoting of the display name.
KCODECS_EXPORT QString decodeRFC2047String(const QString &text)
QString join(const QString &separator) const const
int length() const const
void from7BitString(const QByteArray &s)
Parses the given 7bit encoded string.
void append(const T &value)
void setAddress(const AddrSpec &addr)
Sets the email address.
static QString listToUnicodeString(const QVector< Mailbox > &mailboxes)
Returns a unicode string representing the given list of mailboxes.
void fromUnicodeString(const QString &s)
Parses the given unicode string.
bool isEmpty() const const
const char * constData() const const
static QVector< Mailbox > listFrom7BitString(const QByteArray &s)
Returns a list of mailboxes from an encoded 7bit string.
void reserve(int size)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
char toLatin1() const const
Don&#39;t quote display names at all.
Definition: kmime_types.h:93
const T & at(int i) const const
KIMAP_EXPORT const QString encodeRFC2047String(const QString &str)
QByteArray toLatin1() const const
void setNameFrom7Bit(const QByteArray &name, const QByteArray &defaultCharset=QByteArray())
Sets the name based on a 7bit encoded string.
quoted, like commas or quote signs.
Definition: kmime_types.h:98
Quoting
Describes how display names should be quoted.
Definition: kmime_types.h:92
int count(const T &value) const const
bool hasAddress() const
Returns true if this mailbox has an address.
void reserve(int size)
void setName(const QString &name)
Sets the name.
bool hasName() const
Returns true if this mailbox has a display name.
int size() const const
int size() const const
QString name() const
Returns the display name.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Sep 21 2020 23:12:58 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.