Comment encoder une chaîne en base64 en utilisant uniquement le boost?

J’essaie d’encoder rapidement une simple chaîne ASCII en base64 (authentification HTTP de base en utilisant boost :: asio) et de ne pas coller de nouveau code ou d’utiliser des bibliothèques au-delà du boost.

La signature simple ressemblerait à: ssortingng Base64Encode (chaîne et texte const);

Encore une fois, je réalise que l’algorithme est simple et que beaucoup de bibliothèques / exemples font cela, mais je cherche un exemple de boost propre. J’ai trouvé la sérialisation de boost mais pas d’exemples clairs là ou de Google. http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/dataflow.html

Est-ce possible sans append explicitement l’algorithme base64 à mon code?

J’ai amélioré l’exemple dans le lien que vous avez fourni un peu:

#include  #include  #include  #include  #include  #include  int main() { using namespace boost::archive::iterators; std::ssortingng test = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ornare ullamcorper ipsum ac gravida."; std::ssortingngstream os; typedef insert_linebreaks< // insert line breaks every 72 characters base64_from_binary< // convert binary values to base64 characters transform_width< // retrieve 6 bit integers from a sequence of 8 bit bytes const char *, 6, 8 > > ,72 > base64_text; // compose all the above operations in to a new iterator std::copy( base64_text(test.c_str()), base64_text(test.c_str() + test.size()), ostream_iterator(os) ); std::cout << os.str(); } 

Ceci imprime la chaîne codée base64 joliment formulée avec un saut de ligne tous les 72 caractères sur la console, prête à être placée dans un courrier électronique. Si vous n'aimez pas les sauts de ligne, restz avec ceci:

  typedef base64_from_binary< transform_width< const char *, 6, 8 > > base64_text; 

Voici ma solution Il utilise la même technique de base que les autres solutions de cette page, mais résout le problème du remplissage dans ce que j’estime être une manière plus élégante. Cette solution utilise également C ++ 11.

Je pense que la plupart du code est explicite. Le bit mathématique de la fonction d’encodage calcule le nombre de caractères à append. Le modulo 3 de val.size () le rest, mais ce que nous voulons vraiment, c’est la différence entre val.size () et le prochain nombre divisible par trois. Comme nous avons le rest, nous pouvons simplement soustraire le rest de 3, mais cela laisse 3 dans le cas où nous voulons 0, donc nous devons modulo 3 une fois de plus.

 #include  #include  #include  #include  std::ssortingng decode64(const std::ssortingng &val) { using namespace boost::archive::iterators; using It = transform_width, 8, 6>; return boost::algorithm::sortingm_right_copy_if(std::ssortingng(It(std::begin(val)), It(std::end(val))), [](char c) { return c == '\0'; }); } std::ssortingng encode64(const std::ssortingng &val) { using namespace boost::archive::iterators; using It = base64_from_binary>; auto tmp = std::ssortingng(It(std::begin(val)), It(std::end(val))); return tmp.append((3 - val.size() % 3) % 3, '='); } 

Une autre solution utilisant le décodage d’encodage boost base64:

 const std::ssortingng base64_padding[] = {"", "==","="}; std::ssortingng base64_encode(const std::ssortingng& s) { namespace bai = boost::archive::iterators; std::ssortingngstream os; // convert binary values to base64 characters typedef bai::base64_from_binary // resortingeve 6 bit integers from a sequence of 8 bit bytes  > base64_enc; // compose all the above operations in to a new iterator std::copy(base64_enc(s.c_str()), base64_enc(s.c_str() + s.size()), std::ostream_iterator(os)); os << base64_padding[s.size() % 3]; return os.str(); } std::string base64_decode(const std::string& s) { namespace bai = boost::archive::iterators; std::stringstream os; typedef bai::transform_width, 8, 6> base64_dec; unsigned int size = s.size(); // Remove the padding characters, cf. https://svn.boost.org/trac/boost/ticket/5629 if (size && s[size - 1] == '=') { --size; if (size && s[size - 1] == '=') --size; } if (size == 0) return std::ssortingng(); std::copy(base64_dec(s.data()), base64_dec(s.data() + size), std::ostream_iterator(os)); return os.str(); } 

Et voici les cas de test:

  std::ssortingng t_e[TESTSET_SIZE] = { "" , "M" , "Ma" , "Man" , "pleasure." , "leasure." , "easure." , "asure." , "sure." }; std::ssortingng t_d[TESTSET_SIZE] = { "" , "TQ==" , "TWE=" , "TWFu" , "cGxlYXN1cmUu" , "bGVhc3VyZS4=" , "ZWFzdXJlLg==" , "YXN1cmUu" , "c3VyZS4=" }; 

J’espère que cela t’aides

Pour ceux qui viennent ici de Google, voici mes fonctions d’encodage / décodage base64 basées sur le boost. Il gère correctement le remplissage selon le commentaire de DanDan ci-dessus. Les fonctions de décodage s’arrêtent lorsqu’il rencontre un caractère illégal et renvoie un pointeur sur ce caractère, ce qui est bien si vous parsingz base64 en json ou xml.

 /// /// Convert up to len bytes of binary data in src to base64 and store it in dest /// /// \param dest Destination buffer to hold the base64 data. /// \param src Source binary data. /// \param len The number of bytes of src to convert. /// /// \return The number of characters written to dest. /// \remarks Does not store a terminating null in dest. /// uint base64_encode(char* dest, const char* src, uint len) { char tail[3] = {0,0,0}; typedef base64_from_binary > base64_enc; uint one_third_len = len/3; uint len_rounded_down = one_third_len*3; uint j = len_rounded_down + one_third_len; std::copy(base64_enc(src), base64_enc(src + len_rounded_down), dest); if (len_rounded_down != len) { uint i=0; for(; i < len - len_rounded_down; ++i) { tail[i] = src[len_rounded_down+i]; } std::copy(base64_enc(tail), base64_enc(tail + 3), dest + j); for(i=len + one_third_len + 1; i < j+4; ++i) { dest[i] = '='; } return i; } return j; } /// /// Convert null-terminated string src from base64 to binary and store it in dest. /// /// \param dest Destination buffer /// \param src Source base64 string /// \param len Pointer to unsigned int representing size of dest buffer. After function returns this is set to the number of character written to dest. /// /// \return Pointer to first character in source that could not be converted (the terminating null on success) /// const char* base64_decode(char* dest, const char* src, uint* len) { uint output_len = *len; typedef transform_width, 8, 6> base64_dec; uint i=0; try { base64_dec src_it(src); for(; i < output_len; ++i) { *dest++ = *src_it; ++src_it; } } catch(dataflow_exception&) { } *len = i; return src + (i+2)/3*4; // bytes in = bytes out / 3 rounded up * 4 } 

Maintenant que le boost a atteint 1,66 et que la bête est incluse, vous pouvez utiliser l’implémentation de la bête.

Les fonctions principales que vous voudrez sont: boost::beast::detail::base64_encode() boost::beast::detail::base64_decode()

De #include < boost / beast / core / detail / base64.hpp >

Pendant que l’encodage fonctionne, le décodeur est certainement cassé. Il y a aussi un bogue ouvert: https://svn.boost.org/trac/boost/ticket/5629 . Je n’ai pas trouvé de solution pour cela.

J’ai modifié la réponse 8 car elle n’est pas fonctionnelle sur ma plate-forme.

 const std::ssortingng base64_padding[] = {"", "==","="}; std::ssortingng *m_ArchiveData; /// \brief To Base64 ssortingng bool Base64Encode(ssortingng* output) { try { UInt32 iPadding_Mask = 0; typedef boost::archive::iterators::base64_from_binary  > Base64EncodeIterator; UInt32 len = m_ArchiveData->size(); std::ssortingngstream os; std::copy(Base64EncodeIterator(m_ArchiveData->c_str()), Base64EncodeIterator(m_ArchiveData->c_str()+len), std::ostream_iterator(os)); iPadding_Mask = m_ArchiveData->size() % 3; os << base64_padding[iPadding_Pask]; *output = os.str(); return output->empty() == false; } catch (...) { PLOG_ERROR_DEV("unknown error happens"); return false; } } /// \brief From Base64 ssortingng bool mcsf_data_header_byte_stream_archive::Base64Decode(const std::ssortingng *input) { try { std::ssortingngstream os; bool bPaded = false; typedef boost::archive::iterators::transform_width, 8, 6> Base64DecodeIterator; UInt32 iLength = input->length(); // Remove the padding characters, cf. https://svn.boost.org/trac/boost/ticket/5629 if (iLength && (*input)[iLength-1] == '=') { bPaded = true; --iLength; if (iLength && (*input)[iLength - 1] == '=') { --iLength; } } if (iLength == 0) { return false; } if(bPaded) { iLength --; } copy(Base64DecodeIterator(input->c_str()) , Base64DecodeIterator(input->c_str()+iLength), ostream_iterator(os)); *m_ArchiveData = os.str(); return m_ArchiveData->empty() == false; } catch (...) { PLOG_ERROR_DEV("unknown error happens"); return false; } } 

Base64 encoder du texte et des données

 const std::ssortingng base64_padding[] = {"", "==","="}; std::ssortingng base64EncodeText(std::ssortingng text) { using namespace boost::archive::iterators; typedef std::ssortingng::const_iterator iterator_type; typedef base64_from_binary > base64_enc; std::ssortingngstream ss; std::copy(base64_enc(text.begin()), base64_enc(text.end()), ostream_iterator(ss)); ss << base64_padding[text.size() % 3]; return ss.str(); } std::string base64EncodeData(std::vector data) { using namespace boost::archive::iterators; typedef std::vector::const_iterator iterator_type; typedef base64_from_binary > base64_enc; std::ssortingngstream ss; std::copy(base64_enc(data.begin()), base64_enc(data.end()), ostream_iterator(ss)); ss << base64_padding[data.size() % 3]; return ss.str(); }