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