Codificar/Descodificar URLs en C++ [closed]

2 minutos de lectura

CodificarDescodificar URLs en C closed
usuario126593

¿Alguien sabe de algún buen código C++ que haga esto?

  • ¿Qué hay de aceptar una respuesta?

    – gsamaras

    13 de julio de 2016 a las 22:48

1646752096 470 CodificarDescodificar URLs en C closed
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 a isalnum((unsigned char) c)

    – Skywalker13

    1 de diciembre de 2016 a las 16:44


CodificarDescodificar URLs en C closed
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 de 37.

    – John Zwink

    27 mayo 2014 a las 13:05

  • Esto no convierte ‘+’ en espacio

    – xryl669

    3 de febrero de 2015 a las 8:55

CodificarDescodificar URLs en C closed
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

1646752099 88 CodificarDescodificar URLs en C closed
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

  • oh, aquí tienes github.com/cpp-netlib/cpp-netlib/issues/501

    – kreuzerkrieg

    08/07/2015 a las 14:50

  • ¡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

  • oh, aquí tienes github.com/cpp-netlib/cpp-netlib/issues/501

    – kreuzerkrieg

    08/07/2015 a las 14:50

  • ¡Gracias por aclararlo!

    – Craig M. Brandeburgo

    8 de julio de 2015 a las 15:26

CodificarDescodificar URLs en C closed
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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad