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 BS |
49 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
50 | EVP_cleanup(); /*lint !e534 */ | |
c730deea BS |
51 | throw std::invalid_argument("Could not set up digest context correctly"); |
52 | } | |
a2f5be94 BS |
53 | |
54 | // Test if data is empty. | |
55 | if ( data.empty() ) | |
c730deea | 56 | { |
557b6f56 BS |
57 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
58 | EVP_cleanup(); /*lint !e534 */ | |
ca5d6889 | 59 | throw std::invalid_argument("Passed data is empty"); |
c730deea | 60 | } |
a2f5be94 BS |
61 | |
62 | // Hash the data. At this point data is not empty and &mdctx is initialized. | |
c730deea BS |
63 | if ( EVP_DigestUpdate(&mdctx, data.c_str(), data.size()) == 0 ) |
64 | { | |
557b6f56 BS |
65 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
66 | EVP_cleanup(); /*lint !e534 */ | |
c730deea BS |
67 | throw std::invalid_argument("Could not hash data into digest context"); |
68 | } | |
a2f5be94 BS |
69 | |
70 | // Retrieve the digest value from &mdctx and place it in md_value. | |
c730deea BS |
71 | if ( EVP_DigestFinal_ex(&mdctx, md_value, &md_len) == 0 ) |
72 | { | |
557b6f56 BS |
73 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
74 | EVP_cleanup(); /*lint !e534 */ | |
c730deea BS |
75 | throw std::invalid_argument("Could not retrieve digest value"); |
76 | } | |
a78b44b5 | 77 | |
a2f5be94 | 78 | // Test if md_value is filled correctly and md_len is not zero. |
1f0d13b9 | 79 | if ( (md_len == 0) || (EVP_MD_CTX_size(&mdctx) == 0) ) |
c730deea | 80 | { |
557b6f56 BS |
81 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
82 | EVP_cleanup(); /*lint !e534 */ | |
ca5d6889 | 83 | throw std::invalid_argument("Retrieved invalid digest value"); |
c730deea | 84 | } |
a2f5be94 BS |
85 | |
86 | // Internal cleanup of the digest content. | |
557b6f56 BS |
87 | EVP_MD_CTX_cleanup(&mdctx); /*lint !e534 */ |
88 | EVP_cleanup(); /*lint !e534 */ | |
a78b44b5 | 89 | |
a2f5be94 | 90 | // Convert md5 digest C string to hex. |
ca5d6889 | 91 | std::ostringstream oss_digest_md5_hex; |
a2f5be94 | 92 | for(unsigned int i = 0; i < md_len; ++i) |
a78b44b5 | 93 | { |
a2f5be94 BS |
94 | // We have to do a static cast to an decimal representation, cause otherwise ostringstream would interpret |
95 | // the stream as a character and output the character representation of the hex value. | |
55d580e8 TJ |
96 | oss_digest_md5_hex << std::nouppercase << std::setw(2) << std::setfill('0') |
97 | << std::hex << static_cast<int>(static_cast<unsigned char>(md_value[i])); | |
a78b44b5 BS |
98 | } |
99 | ||
a2f5be94 | 100 | return oss_digest_md5_hex.str(); |
a78b44b5 | 101 | } |
52e7ca71 BS |
102 | |
103 | ||
104 | /** | |
105 | * Get the status code from the given data. | |
797a735d | 106 | * @param data The data containing the status code at front, limited by delimiter. |
8fb7a083 | 107 | * @param delimiter The delimiter to use. |
797a735d | 108 | * @return The parsed status code |
8fb7a083 BS |
109 | */ |
110 | std::string parse_status_code(std::string data, std::string delimiter) | |
111 | { | |
112 | std::list<std::string> tokens; | |
113 | boost::algorithm::split(tokens,data,boost::is_any_of(delimiter)); | |
557b6f56 BS |
114 | if ( tokens.empty() ) |
115 | return ""; | |
8fb7a083 BS |
116 | return tokens.front(); |
117 | } | |
557b6f56 BS |
118 | |
119 | } |