File indexing completed on 2024-04-21 16:06:19

0001 /*
0002     SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 class QByteArray;
0010 class QByteArrayView;
0011 class QString;
0012 
0013 #include <cstdlib>
0014 
0015 // @cond PRIVATE
0016 
0017 /* Internal helper functions. Not part of the public API. */
0018 
0019 namespace KMime
0020 {
0021 
0022 /**
0023  *  Consult the charset cache. Only used for reducing mem usage by
0024  *  keeping strings in a common repository.
0025  *  @param name
0026  */
0027 extern QByteArray cachedCharset(const QByteArray &name);
0028 
0029 /**
0030   Finds the header end in @p src. Aligns the @p dataBegin if needed.
0031   @param dataBegin beginning of the data part of the header
0032   @param folded true if the headder is folded into multiple lines
0033   @returns the end index of the header, -1 if the @p dataBegin was -1.
0034 */
0035 extern int findHeaderLineEnd(QByteArrayView src, int &dataBegin, bool *folded = nullptr);
0036 
0037 /**
0038   Tries to extract the header with name @p name from the string
0039   @p src, unfolding it if necessary.
0040 
0041   @param src  the source string.
0042   @param name the name of the header to search for.
0043 
0044   @return the first instance of the header @p name in @p src
0045           or a null QByteArray if no such header was found.
0046 */
0047 QByteArray extractHeader(const QByteArray &src, const QByteArray &name);
0048 
0049 /**
0050   Finds the first header of type @p name in @p src.
0051   @param end The end index of the header.
0052   @param dataBegin begin of the data part of the header, -1 if not found.
0053   @param folded true if the headder is folded into multiple lines
0054   @returns the begin index of the header, -1 if not found.
0055 */
0056 extern int indexOfHeader(const QByteArray &src, const QByteArray &name, int &end, int &dataBegin, bool *folded = nullptr);
0057 
0058 /**
0059  *  Uses current time, pid and random numbers to construct a string
0060  *  that aims to be unique on a per-host basis (ie. for the local
0061  *  part of a message-id or for multipart boundaries.
0062  *
0063  *  @return the unique string.
0064  *  @see multiPartBoundary
0065  */
0066 extern QByteArray uniqueString();
0067 
0068 /**
0069   Unfolds the given header if necessary.
0070   @param header The header to unfold.
0071 */
0072 QByteArray unfoldHeader(const QByteArray &header);
0073 QByteArray unfoldHeader(const char *header, size_t headerSize);
0074 
0075 /**
0076   Folds the given header if necessary.
0077   @param header The header to fold.
0078 */
0079 QByteArray foldHeader(const QByteArray &header);
0080 
0081 /**
0082   Removes quote (DQUOTE) characters and decodes "quoted-pairs"
0083   (ie. backslash-escaped characters)
0084 
0085   @param str the string to work on.
0086   @see addQuotes
0087 */
0088 void removeQuotes(QByteArray &str);
0089 
0090 /**
0091   Removes quote (DQUOTE) characters and decodes "quoted-pairs"
0092   (ie. backslash-escaped characters)
0093 
0094   @param str the string to work on.
0095   @see addQuotes
0096 */
0097 void removeQuotes(QString &str);
0098 
0099 /**
0100   Converts the given string into a quoted-string if the string contains
0101   any special characters (ie. one of ()<>@,.;:[]=\").
0102 
0103   @param str us-ascii string to work on.
0104   @param forceQuotes if @c true, always add quote characters.
0105 */
0106 void addQuotes(QByteArray &str, bool forceQuotes);
0107 
0108 /**
0109  * Overloaded method, behaves same as the above.
0110  * @param str us-ascii string to work on.
0111  * @param forceQuotes if @c true, always add quote characters.
0112  * @since 4.5
0113  */
0114 void addQuotes(QString &str, bool forceQuotes);
0115 
0116 /**
0117  * Makes sure that the bidirectional state at the end of the string is the
0118  * same as at the beginning of the string.
0119  *
0120  * This is useful so that Unicode control characters that can change the text
0121  * direction can not spill over to following strings.
0122  *
0123  * As an example, consider a mailbox in the form "display name" <local@domain.com>.
0124  * If the display name here contains unbalanced control characters that change the
0125  * text direction, it would also have an effect on the addrspec, which could lead to
0126  * spoofing.
0127  *
0128  * By passing the display name to this function, one can make sure that no change of
0129  * the bidi state can spill over to the next strings, in this case the addrspec.
0130  *
0131  * Example: The string "Hello <RLO>World" is unbalanced, as it contains a right-to-left
0132  *          override character, which is never followed by a <PDF>, the "pop directional
0133  *          formatting" character. This function adds the missing <PDF> at the end, and
0134  *          the output of this function would be "Hello <RLO>World<PDF>".
0135  *
0136  * Example of spoofing:
0137  *   Consider "Firstname Lastname<RLO>" <moc.mitciv@attacker.com>. Because of the RLO,
0138  *   it is displayed as "Firstname Lastname <moc.rekcatta@victim.com>", which spoofs the
0139  *   domain name.
0140  *   By passing "Firstname Lastname<RLO>" to this function, one can balance the <RLO>,
0141  *   leading to "Firstname Lastname<RLO><PDF>", so the whole mailbox is displayed
0142  *   correctly as "Firstname Lastname" <moc.mitciv@attacker.com> again.
0143  *
0144  * See https://unicode.org/reports/tr9 for more information on bidi control chars.
0145  *
0146  * @param input the display name of a mailbox, which is checked for unbalanced Unicode
0147  *              direction control characters
0148  * @return the display name which now contains a balanced state of direction control
0149  *         characters
0150  *
0151  * Note that this function does not do any parsing related to mailboxes, it only works
0152  * on plain strings. Therefore, passing the complete mailbox will not lead to any results,
0153  * only the display name should be passed.
0154  *
0155  * @since 4.5
0156  */
0157 QString balanceBidiState(const QString &input);
0158 
0159 /**
0160  * Similar to the above function. Instead of trying to balance the Bidi chars, it outright
0161  * removes them from the string.
0162  *
0163  * @param input the display name of a mailbox, which is checked for unbalanced Unicode
0164  * direction control characters
0165  * Reason: KHTML seems to ignore the PDF character, so adding them doesn't fix things :(
0166  */
0167 QString removeBidiControlChars(const QString &input);
0168 
0169 //@cond PRIVATE
0170 extern const unsigned char aTextMap[16];
0171 extern const unsigned char tTextMap[16];
0172 
0173 inline bool isOfSet(const unsigned char map[16], unsigned char ch)
0174 {
0175     return (ch < 128) && (map[ ch / 8 ] & 0x80 >> ch % 8);
0176 }
0177 inline bool isAText(char ch)
0178 {
0179     return isOfSet(aTextMap, ch);
0180 }
0181 inline bool isTText(char ch)
0182 {
0183     return isOfSet(tTextMap, ch);
0184 }
0185 //@endcond
0186 
0187 }
0188 
0189 // @endcond
0190