File indexing completed on 2025-01-05 04:55:53

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     utils/hex.cpp
0003 
0004     This file is part of libkleopatra
0005     SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-libkleo.h>
0011 
0012 #include "hex.h"
0013 
0014 #include <libkleo/kleoexception.h>
0015 
0016 #include <KLocalizedString>
0017 
0018 #include <QByteArray>
0019 #include <QString>
0020 
0021 using namespace Kleo;
0022 
0023 static unsigned char unhex(unsigned char ch)
0024 {
0025     if (ch >= '0' && ch <= '9') {
0026         return ch - '0';
0027     }
0028     if (ch >= 'A' && ch <= 'F') {
0029         return ch - 'A' + 10;
0030     }
0031     if (ch >= 'a' && ch <= 'f') {
0032         return ch - 'a' + 10;
0033     }
0034     const char cch = ch;
0035     throw Kleo::Exception(gpg_error(GPG_ERR_ASS_SYNTAX), i18n("Invalid hex char '%1' in input stream.", QString::fromLatin1(&cch, 1)));
0036 }
0037 
0038 std::string Kleo::hexdecode(const std::string &in)
0039 {
0040     std::string result;
0041     result.reserve(in.size());
0042     for (std::string::const_iterator it = in.begin(), end = in.end(); it != end; ++it) {
0043         if (*it == '%') {
0044             ++it;
0045             unsigned char ch = '\0';
0046             if (it == end) {
0047                 throw Exception(gpg_error(GPG_ERR_ASS_SYNTAX), i18n("Premature end of hex-encoded char in input stream"));
0048             }
0049             ch |= unhex(*it) << 4;
0050             ++it;
0051             if (it == end) {
0052                 throw Exception(gpg_error(GPG_ERR_ASS_SYNTAX), i18n("Premature end of hex-encoded char in input stream"));
0053             }
0054             ch |= unhex(*it);
0055             result.push_back(ch);
0056         } else if (*it == '+') {
0057             result += ' ';
0058         } else {
0059             result.push_back(*it);
0060         }
0061     }
0062     return result;
0063 }
0064 
0065 std::string Kleo::hexencode(const std::string &in)
0066 {
0067     std::string result;
0068     result.reserve(3 * in.size());
0069 
0070     static const char hex[] = "0123456789ABCDEF";
0071 
0072     for (std::string::const_iterator it = in.begin(), end = in.end(); it != end; ++it) {
0073         switch (const unsigned char ch = *it) {
0074         default:
0075             if ((ch >= '!' && ch <= '~') || ch > 0xA0) {
0076                 result += ch;
0077                 break;
0078             }
0079         // else fall through
0080         case ' ':
0081             result += '+';
0082             break;
0083         case '"':
0084         case '#':
0085         case '$':
0086         case '%':
0087         case '\'':
0088         case '+':
0089         case '=':
0090             result += '%';
0091             result += hex[(ch & 0xF0) >> 4];
0092             result += hex[(ch & 0x0F)];
0093             break;
0094         }
0095     }
0096 
0097     return result;
0098 }
0099 
0100 std::string Kleo::hexdecode(const char *in)
0101 {
0102     if (!in) {
0103         return std::string();
0104     }
0105     return hexdecode(std::string(in));
0106 }
0107 
0108 std::string Kleo::hexencode(const char *in)
0109 {
0110     if (!in) {
0111         return std::string();
0112     }
0113     return hexencode(std::string(in));
0114 }
0115 
0116 QByteArray Kleo::hexdecode(const QByteArray &in)
0117 {
0118     if (in.isNull()) {
0119         return QByteArray();
0120     }
0121     const std::string result = hexdecode(std::string(in.constData()));
0122     return QByteArray(result.data(), result.size());
0123 }
0124 
0125 QByteArray Kleo::hexencode(const QByteArray &in)
0126 {
0127     if (in.isNull()) {
0128         return QByteArray();
0129     }
0130     const std::string result = hexencode(std::string(in.constData()));
0131     return QByteArray(result.data(), result.size());
0132 }