Commit | Line | Data |
---|---|---|
a78b44b5 | 1 | /** @file |
ca5d6889 | 2 | * @brief Util namespace header. |
a78b44b5 BS |
3 | * |
4 | * | |
5 | * | |
6 | * @copyright Intra2net AG | |
7 | * @license GPLv2 | |
8 | */ | |
9 | ||
4de6a9b8 | 10 | #include "util.hpp" |
a78b44b5 | 11 | |
a2f5be94 | 12 | #include <sstream> |
55d580e8 | 13 | #include <iomanip> |
a78b44b5 | 14 | #include <openssl/evp.h> |
ca5d6889 | 15 | #include <boost/algorithm/string.hpp> |
a78b44b5 | 16 | |
ca5d6889 BS |
17 | namespace Util |
18 | { | |
a78b44b5 BS |
19 | /** |
20 | * Computes a MD5 Digest from the given string and returns the HEX representation | |
21 | * @param data The string to compute the md5 for | |
22 | * @return The computed md5 in hex | |
23 | */ | |
c730deea | 24 | std::string compute_md5_digest(std::string data) |
a78b44b5 BS |
25 | { |
26 | // compute an MD5 digest. | |
27 | ||
a78b44b5 BS |
28 | EVP_MD_CTX mdctx; |
29 | const EVP_MD *md; | |
30 | unsigned char md_value[EVP_MAX_MD_SIZE]; | |
a2f5be94 | 31 | unsigned int md_len = 0; |
a78b44b5 | 32 | |
a2f5be94 | 33 | // Add all digest algorithms to the internal table. |
a78b44b5 BS |
34 | OpenSSL_add_all_digests(); |
35 | ||
a2f5be94 | 36 | // Get the md5 digest algorithm from the internal table. |
a78b44b5 BS |
37 | md = EVP_get_digestbyname("md5"); |
38 | ||
a2f5be94 BS |
39 | // Test if md is initialized. |
40 | if ( (md == NULL) || (EVP_MD_size(md) == 0) ) | |
ca5d6889 | 41 | throw std::invalid_argument("NULL pointer: md"); |
a2f5be94 BS |
42 | |
43 | // Initalize digest content mdctx. | |
a78b44b5 | 44 | EVP_MD_CTX_init(&mdctx); |
a2f5be94 BS |
45 | |
46 | // Now we can call init_ex. | |
c730deea BS |
47 | if ( EVP_DigestInit_ex(&mdctx, md, NULL) == 0 ) |
48 | { | |
557b6f56 | 49 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
c730deea BS |
50 | throw std::invalid_argument("Could not set up digest context correctly"); |
51 | } | |
a2f5be94 BS |
52 | |
53 | // Test if data is empty. | |
54 | if ( data.empty() ) | |
c730deea | 55 | { |
557b6f56 | 56 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
ca5d6889 | 57 | throw std::invalid_argument("Passed data is empty"); |
c730deea | 58 | } |
a2f5be94 BS |
59 | |
60 | // Hash the data. At this point data is not empty and &mdctx is initialized. | |
c730deea BS |
61 | if ( EVP_DigestUpdate(&mdctx, data.c_str(), data.size()) == 0 ) |
62 | { | |
557b6f56 | 63 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
c730deea BS |
64 | throw std::invalid_argument("Could not hash data into digest context"); |
65 | } | |
a2f5be94 BS |
66 | |
67 | // Retrieve the digest value from &mdctx and place it in md_value. | |
c730deea BS |
68 | if ( EVP_DigestFinal_ex(&mdctx, md_value, &md_len) == 0 ) |
69 | { | |
557b6f56 | 70 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
c730deea BS |
71 | throw std::invalid_argument("Could not retrieve digest value"); |
72 | } | |
a78b44b5 | 73 | |
a2f5be94 | 74 | // Test if md_value is filled correctly and md_len is not zero. |
1f0d13b9 | 75 | if ( (md_len == 0) || (EVP_MD_CTX_size(&mdctx) == 0) ) |
c730deea | 76 | { |
557b6f56 | 77 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
ca5d6889 | 78 | throw std::invalid_argument("Retrieved invalid digest value"); |
c730deea | 79 | } |
a2f5be94 BS |
80 | |
81 | // Internal cleanup of the digest content. | |
557b6f56 | 82 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
a78b44b5 | 83 | |
a2f5be94 | 84 | // Convert md5 digest C string to hex. |
ca5d6889 | 85 | std::ostringstream oss_digest_md5_hex; |
a2f5be94 | 86 | for(unsigned int i = 0; i < md_len; ++i) |
a78b44b5 | 87 | { |
a2f5be94 BS |
88 | // We have to do a static cast to an decimal representation, cause otherwise ostringstream would interpret |
89 | // the stream as a character and output the character representation of the hex value. | |
55d580e8 TJ |
90 | oss_digest_md5_hex << std::nouppercase << std::setw(2) << std::setfill('0') |
91 | << std::hex << static_cast<int>(static_cast<unsigned char>(md_value[i])); | |
a78b44b5 BS |
92 | } |
93 | ||
a2f5be94 | 94 | return oss_digest_md5_hex.str(); |
a78b44b5 | 95 | } |
52e7ca71 BS |
96 | |
97 | ||
98 | /** | |
99 | * Get the status code from the given data. | |
797a735d | 100 | * @param data The data containing the status code at front, limited by delimiter. |
8fb7a083 | 101 | * @param delimiter The delimiter to use. |
797a735d | 102 | * @return The parsed status code |
8fb7a083 BS |
103 | */ |
104 | std::string parse_status_code(std::string data, std::string delimiter) | |
105 | { | |
106 | std::list<std::string> tokens; | |
107 | boost::algorithm::split(tokens,data,boost::is_any_of(delimiter)); | |
557b6f56 BS |
108 | if ( tokens.empty() ) |
109 | return ""; | |
8fb7a083 BS |
110 | return tokens.front(); |
111 | } | |
557b6f56 BS |
112 | |
113 | } |