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 }