¿Alguien sabe de algún buen código C++ que haga esto?
Codificar/Descodificar URLs en C++ [closed]
usuario126593
xperroni
Me enfrenté a la codificación de la mitad de este problema el otro día. Descontento con las opciones disponibles, y después de echar un vistazo a este código de muestra Cdecidí implementar mi propia función de codificación de URL de C++:
#include <cctype>
#include <iomanip>
#include <sstream>
#include <string>
using namespace std;
string url_encode(const string &value) {
ostringstream escaped;
escaped.fill('0');
escaped << hex;
for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
string::value_type c = (*i);
// Keep alphanumeric and other accepted characters intact
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
escaped << c;
continue;
}
// Any other characters are percent-encoded
escaped << uppercase;
escaped << '%' << setw(2) << int((unsigned char) c);
escaped << nouppercase;
}
return escaped.str();
}
La implementación de la función de decodificación se deja como ejercicio para el lector. :PAGS
-
Creo que es más genérico (más generalmente correcto) reemplazar ‘ ‘ con “% 20”. He actualizado el código en consecuencia; siéntase libre de retroceder si no está de acuerdo.
–Josh Kelley
15 de julio de 2014 a las 17:48
-
No, estoy de acuerdo. También aproveché para quitar ese sinsentido.
setw(0)
llamada (en ese momento pensé que el ancho mínimo permanecería establecido hasta que lo volviera a cambiar, pero de hecho se restablece después de la siguiente entrada).– xperroni
15 de julio de 2014 a las 22:19
-
Tuve que agregar std::uppercase a la línea “escaped << '%' << std::uppercase << std::setw(2) << int((unsigned char) c);" En caso de que otras personas se pregunten por qué esto devuelve, por ejemplo, %3a en lugar de %3A
– gumlym
11 de septiembre de 2015 a las 9:06
-
Se ve mal porque las cadenas UTF-8 no son compatibles (w3schools.com/tags/ref_urlencode.asp). Parece que solo funciona para Windows-1252
– Skywalker13
1 de diciembre de 2016 a las 16:32
-
El problema era solo
isalnum(c)
se debe cambiar aisalnum((unsigned char) c)
– Skywalker13
1 de diciembre de 2016 a las 16:44
usuario126593
Respondiendo a mi propia pregunta…
libcurl tiene curl_fácil_escape para la codificación.
Para decodificar, curl_easy_unescape
-
Debe aceptar esta respuesta para que se muestre en la parte superior (y las personas puedan encontrarla más fácilmente).
– Mouagip
4 de noviembre de 2015 a las 13:47
-
necesitas usar curl para que esto funcione y tienes que liberar la memoria
– xinthose
5 de noviembre de 2017 a las 1:04
-
Pregunta relacionada: ¿por qué el unescape de curl no maneja el cambio de ‘+’ al espacio? ¿No es ese el procedimiento estándar cuando se decodifica una URL?
– Stéphane
27 de mayo de 2019 a las 6:59
string urlDecode(string &SRC) {
string ret;
char ch;
int i, ii;
for (i=0; i<SRC.length(); i++) {
if (int(SRC[i])==37) {
sscanf(SRC.substr(i+1,2).c_str(), "%x", &ii);
ch=static_cast<char>(ii);
ret+=ch;
i=i+2;
} else {
ret+=SRC[i];
}
}
return (ret);
}
no es el mejor, pero funciona bien 😉
-
Por supuesto que deberías usar
'%'
en lugar de37
.– John Zwink
27 mayo 2014 a las 13:05
-
Esto no convierte ‘+’ en espacio
– xryl669
3 de febrero de 2015 a las 8:55
tormuto
Por lo general, agregar ‘%’ al valor int de un carácter no funcionará al codificar, se supone que el valor es el equivalente hexadecimal. por ejemplo, “https://stackoverflow.com/” es ‘%2F’, no ‘%47’.
Creo que esta es la mejor y más concisa solución tanto para la codificación como para la decodificación de URL (no hay muchas dependencias de encabezado).
string urlEncode(string str){
string new_str = "";
char c;
int ic;
const char* chars = str.c_str();
char bufHex[10];
int len = strlen(chars);
for(int i=0;i<len;i++){
c = chars[i];
ic = c;
// uncomment this if you want to encode spaces with +
/*if (c==' ') new_str += '+';
else */if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') new_str += c;
else {
sprintf(bufHex,"%X",c);
if(ic < 16)
new_str += "%0";
else
new_str += "%";
new_str += bufHex;
}
}
return new_str;
}
string urlDecode(string str){
string ret;
char ch;
int i, ii, len = str.length();
for (i=0; i < len; i++){
if(str[i] != '%'){
if(str[i] == '+')
ret += ' ';
else
ret += str[i];
}else{
sscanf(str.substr(i + 1, 2).c_str(), "%x", &ii);
ch = static_cast<char>(ii);
ret += ch;
i = i + 2;
}
}
return ret;
}
-
Dios mío, gracias. la documentación sobre cpp-netlib es escasa. ¿Tiene algún enlace a buenas hojas de trucos?
– usuario249806
13 de mayo de 2017 a las 13:12
kreuzerkrieg
[Necromancer mode on]
Me topé con esta pregunta cuando buscaba una solución rápida, moderna, independiente de la plataforma y elegante. No me gustó ninguno de los anteriores, cpp-netlib sería el ganador, pero tiene una vulnerabilidad de memoria horrible en la función “decodificada”. Así que se me ocurrió la solución de qi/karma espiritual de boost.
namespace bsq = boost::spirit::qi;
namespace bk = boost::spirit::karma;
bsq::int_parser<unsigned char, 16, 2, 2> hex_byte;
template <typename InputIterator>
struct unescaped_string
: bsq::grammar<InputIterator, std::string(char const *)> {
unescaped_string() : unescaped_string::base_type(unesc_str) {
unesc_char.add("+", ' ');
unesc_str = *(unesc_char | "%" >> hex_byte | bsq::char_);
}
bsq::rule<InputIterator, std::string(char const *)> unesc_str;
bsq::symbols<char const, char const> unesc_char;
};
template <typename OutputIterator>
struct escaped_string : bk::grammar<OutputIterator, std::string(char const *)> {
escaped_string() : escaped_string::base_type(esc_str) {
esc_str = *(bk::char_("a-zA-Z0-9_.~-") | "%" << bk::right_align(2,0)[bk::hex]);
}
bk::rule<OutputIterator, std::string(char const *)> esc_str;
};
El uso de lo anterior de la siguiente manera:
std::string unescape(const std::string &input) {
std::string retVal;
retVal.reserve(input.size());
typedef std::string::const_iterator iterator_type;
char const *start = "";
iterator_type beg = input.begin();
iterator_type end = input.end();
unescaped_string<iterator_type> p;
if (!bsq::parse(beg, end, p(start), retVal))
retVal = input;
return retVal;
}
std::string escape(const std::string &input) {
typedef std::back_insert_iterator<std::string> sink_type;
std::string retVal;
retVal.reserve(input.size() * 3);
sink_type sink(retVal);
char const *start = "";
escaped_string<sink_type> g;
if (!bk::generate(sink, g(start), input))
retVal = input;
return retVal;
}
[Necromancer mode off]
EDIT01: corrigió las cosas de relleno cero – gracias especiales a Hartmut Kaiser
EDITAR02: En vivo en CoLiRu
-
¿Cuál es la “vulnerabilidad de la memoria horrible” de
cpp-netlib
? ¿Puede proporcionar una breve explicación o un enlace?– Craig M. Brandeburgo
7 julio 2015 a las 21:26
-
(El problema) ya se informó, así que no lo informé y en realidad no lo recuerdo… algo así como una violación de acceso al intentar analizar una secuencia de escape no válida, o algo así.
– kreuzerkrieg
8 de julio de 2015 a las 14:47
-
-
¡Gracias por aclararlo!
– Craig M. Brandeburgo
8 de julio de 2015 a las 15:26
Inspirándome en xperroni escribí un decodificador. Gracias por el puntero.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
char from_hex(char ch) {
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}
string url_decode(string text) {
char h;
ostringstream escaped;
escaped.fill('0');
for (auto i = text.begin(), n = text.end(); i != n; ++i) {
string::value_type c = (*i);
if (c == '%') {
if (i[1] && i[2]) {
h = from_hex(i[1]) << 4 | from_hex(i[2]);
escaped << h;
i += 2;
}
} else if (c == '+') {
escaped << ' ';
} else {
escaped << c;
}
}
return escaped.str();
}
int main(int argc, char** argv) {
string msg = "J%C3%B8rn!";
cout << msg << endl;
string decodemsg = url_decode(msg);
cout << decodemsg << endl;
return 0;
}
editar: Se eliminaron cctype e iomainip innecesarios incluidos.
-
¿Cuál es la “vulnerabilidad de la memoria horrible” de
cpp-netlib
? ¿Puede proporcionar una breve explicación o un enlace?– Craig M. Brandeburgo
7 julio 2015 a las 21:26
-
(El problema) ya se informó, así que no lo informé y en realidad no lo recuerdo… algo así como una violación de acceso al intentar analizar una secuencia de escape no válida, o algo así.
– kreuzerkrieg
8 de julio de 2015 a las 14:47
-
-
¡Gracias por aclararlo!
– Craig M. Brandeburgo
8 de julio de 2015 a las 15:26
alanc10n
CGICC incluye métodos para codificar y decodificar URL. form_urlencode y form_urldecode
-
Acabas de iniciar una conversación decente en nuestra oficina con esa biblioteca.
– JJ
30 de septiembre de 2008 a las 19:35
-
Este es en realidad, el código más simple y más correcto.
– xryl669
3 de febrero de 2015 a las 8:56
¿Qué hay de aceptar una respuesta?
– gsamaras
13 de julio de 2016 a las 22:48