C / C ++ библиотека URL-декодирования - PullRequest
10 голосов
/ 20 апреля 2010

Я занимаюсь разработкой программы на языке c / c ++ для Linux. Подскажите, пожалуйста, есть ли библиотека c / c ++, которая декодирует url?

Я ищу библиотеки, которые перерабатывать "HTTP% 3A% 2F% 2F" чтобы: «http://"

или "a + t +% 26 + t" до "a t & t"

Спасибо.

Ответы [ 10 ]

23 голосов
/ 26 января 2013

Я фактически использовал функцию Саула в программе анализа, которую я писал (анализируя миллионы строк, закодированных в URL), и, хотя она работает, в таком масштабе она ужасно замедляла мою программу, поэтому я решил написать более быструю версию. Это в тысячи раз быстрее при компиляции с GCC и опцией -O2. Он также может использовать тот же выходной буфер, что и вход (например, urldecode2 (buf, buf) будет работать, если исходная строка была в buf и должна быть перезаписана его декодированным аналогом).

Редактировать: Он не принимает размер буфера в качестве входных данных, поскольку предполагается, что буфер будет достаточно большим, это безопасно, поскольку известно, что длина выходных данных всегда будет <= входного, поэтому либо используйте один и тот же буфер для вывода, либо создайте такой, который по крайней мере будет иметь размер ввода + 1 для нулевого терминатора, например: </p>

char *output = malloc(strlen(input)+1);
urldecode2(output, input);
printf("Decoded string: %s\n", output);

Редактировать 2: Анонимный пользователь попытался отредактировать этот ответ, чтобы обработать перевод «+» символа на «», что, я думаю, должно быть, опять же, это не то, что мне было нужно мое заявление, но я добавил его ниже.

Вот процедура:

#include <stdlib.h>
#include <ctype.h>

void urldecode2(char *dst, const char *src)
{
        char a, b;
        while (*src) {
                if ((*src == '%') &&
                    ((a = src[1]) && (b = src[2])) &&
                    (isxdigit(a) && isxdigit(b))) {
                        if (a >= 'a')
                                a -= 'a'-'A';
                        if (a >= 'A')
                                a -= ('A' - 10);
                        else
                                a -= '0';
                        if (b >= 'a')
                                b -= 'a'-'A';
                        if (b >= 'A')
                                b -= ('A' - 10);
                        else
                                b -= '0';
                        *dst++ = 16*a+b;
                        src+=3;
                } else if (*src == '+') {
                        *dst++ = ' ';
                        src++;
                } else {
                        *dst++ = *src++;
                }
        }
        *dst++ = '\0';
}
5 голосов
/ 17 июня 2015

Вот C-декодер для строки, закодированной в процентах. Возвращает -1, если кодировка неверна, и 0 в противном случае. Декодированная строка сохраняется в out. Я совершенно уверен, что это самый быстрый код ответов, данных до сих пор.

int percent_decode(char* out, const char* in) {
{
    static const char tbl[256] = {
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
         0, 1, 2, 3, 4, 5, 6, 7,  8, 9,-1,-1,-1,-1,-1,-1,
        -1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1
    };
    char c, v1, v2, *beg=out;
    if(in != NULL) {
        while((c=*in++) != '\0') {
            if(c == '%') {
                if((v1=tbl[(unsigned char)*in++])<0 || 
                   (v2=tbl[(unsigned char)*in++])<0) {
                    *beg = '\0';
                    return -1;
                }
                c = (v1<<4)|v2;
            }
            *out++ = c;
        }
    }
    *out = '\0';
    return 0;
}
3 голосов
/ 04 мая 2010

Эта функция, которую я только что выполнил, очень легкая и должна выполнять, как вы хотите, обратите внимание, что я не запрограммировал ее на строгие стандарты URI (использовал то, что я знаю из головы). Это буферно-безопасный и не переполняет, насколько я вижу; адаптироваться по своему усмотрению:

#include <assert.h>

void urldecode(char *pszDecodedOut, size_t nBufferSize, const char *pszEncodedIn)
{
    memset(pszDecodedOut, 0, nBufferSize);

    enum DecodeState_e
    {
        STATE_SEARCH = 0, ///< searching for an ampersand to convert
        STATE_CONVERTING, ///< convert the two proceeding characters from hex
    };

    DecodeState_e state = STATE_SEARCH;

    for(unsigned int i = 0; i < strlen(pszEncodedIn)-1; ++i)
    {
        switch(state)
        {
        case STATE_SEARCH:
            {
                if(pszEncodedIn[i] != '%')
                {
                    strncat(pszDecodedOut, &pszEncodedIn[i], 1);
                    assert(strlen(pszDecodedOut) < nBufferSize);
                    break;
                }

                // We are now converting
                state = STATE_CONVERTING;
            }
            break;

        case STATE_CONVERTING:
            {
                // Conversion complete (i.e. don't convert again next iter)
                state = STATE_SEARCH;

                // Create a buffer to hold the hex. For example, if %20, this
                // buffer would hold 20 (in ASCII)
                char pszTempNumBuf[3] = {0};
                strncpy(pszTempNumBuf, &pszEncodedIn[i], 2);

                // Ensure both characters are hexadecimal
                bool bBothDigits = true;

                for(int j = 0; j < 2; ++j)
                {
                    if(!isxdigit(pszTempNumBuf[j]))
                        bBothDigits = false;
                }

                if(!bBothDigits)
                    break;

                // Convert two hexadecimal characters into one character
                int nAsciiCharacter;
                sscanf(pszTempNumBuf, "%x", &nAsciiCharacter);

                // Ensure we aren't going to overflow
                assert(strlen(pszDecodedOut) < nBufferSize);

                // Concatenate this character onto the output
                strncat(pszDecodedOut, (char*)&nAsciiCharacter, 1);

                // Skip the next character
                i++;
            }
            break;
        }
    }
}
3 голосов
/ 20 апреля 2010

uriparser библиотека небольшая и легкая.

3 голосов
/ 20 апреля 2010

Всегда превосходный glib имеет некоторые функции URI , включая извлечение схем, экранирование и экранирование.

1 голос
/ 08 ноября 2013

Я бы предложил curl и libcurl . Он широко используется и должен помочь вам. Просто зайдите на их сайт.

1 голос
/ 08 ноября 2013

Попробуйте urlcpp https://github.com/larroy/urlcpp Это модуль C ++, который вы можете легко интегрировать в ваш проект, зависит от boost :: regex

0 голосов
/ 23 августа 2018

Наткнулся на этот 8-летний вопрос, когда я искал то же самое. Основываясь на предыдущих ответах, я также написал свою собственную версию, которая не зависит от библиотек, проста для понимания и, вероятно, быстра (без теста) Протестированный код с gcc, он должен декодироваться до конца или недопустимый символ (не тестировался). Просто не забудьте освободить выделенное пространство.

const char ascii_hex_4bit[23] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};

static inline char to_upper(char c)
{
    if ((c >= 'a') && (c <= 'z')) return c ^ 0x20;
    return c;
}

char *url_decode(const char *str)
{
    size_t i, j, len = strlen(str);
    char c, d, url_hex;
    char *decoded = malloc(len + 1);

    if (decoded == NULL) return NULL;

    i = 0;
    j = 0;
    do
    {
        c = str[i];
        d = 0;

        if (c == '%')
        {
            url_hex = to_upper(str[++i]);
            if (((url_hex >= '0') && (url_hex <= '9')) || ((url_hex >= 'A') && (url_hex <= 'F')))
            {
                d = ascii_hex_4bit[url_hex - 48] << 4;

                url_hex = to_upper(str[++i]);
                if (((url_hex >= '0') && (url_hex <= '9')) || ((url_hex >= 'A') && (url_hex <= 'F')))
                {
                    d |= ascii_hex_4bit[url_hex - 48];
                }
                else
                {
                    d = 0;
                }
            }
        }
        else if (c == '+')
        {
            d = ' ';
        }
        else if ((c == '*') || (c == '-') || (c == '.') || ((c >= '0') && (c <= '9')) ||
        ((c >= 'A') && (c <= 'Z')) || (c == '_') || ((c >= 'a') && (c <= 'z')))
        {
            d = c;
        }

        decoded[j++] = d;
        ++i;
    } while ((i < len) && (d != 0));

    decoded[j] = 0;
    return decoded;
}
0 голосов
/ 07 декабря 2013

Спасибо @ThomasH за ответ. Я хотел бы предложить здесь лучшее форматирование ...

И…, поскольку декодированный компонент URI всегда меньше, чем тот же кодированный компонент URI, всегда можно развернуть его в массиве символов * (строка aka: " «). Итак, я предложу здесь две возможности :

#include <stdio.h>

int decodeURIComponent (char *sSource, char *sDest) {
    int nLength;
    for (nLength = 0; *sSource; nLength++) {
        if (*sSource == '%' && sSource[1] && sSource[2] && isxdigit(sSource[1]) && isxdigit(sSource[2])) {
            sSource[1] -= sSource[1] <= '9' ? '0' : (sSource[1] <= 'F' ? 'A' : 'a')-10;
            sSource[2] -= sSource[2] <= '9' ? '0' : (sSource[2] <= 'F' ? 'A' : 'a')-10;
            sDest[nLength] = 16 * sSource[1] + sSource[2];
            sSource += 3;
            continue;
        }
        sDest[nLength] = *sSource++;
    }
    sDest[nLength] = '\0';
    return nLength;
}

#define implodeURIComponent(url) decodeURIComponent(url, url)

И, наконец ...:

int main () {

    char sMyUrl[] = "http%3a%2F%2ffoo+bar%2fabcd";

    int nNewLength = implodeURIComponent(sMyUrl);

    /* Let's print: "http://foo+bar/abcd\nLength: 19" */
    printf("%s\nLength: %d\n", sMyUrl, nNewLength);

    return 0;

}

Ste *

0 голосов
/ 07 ноября 2013
/**
 * Locale-independent conversion of ASCII characters to lowercase.
 */
int av_tolower(int c)
{
    if (c >= 'A' && c <= 'Z')
        c ^= 0x20;
    return c;
}
/**
 * Decodes an URL from its percent-encoded form back into normal
 * representation. This function returns the decoded URL in a string.
 * The URL to be decoded does not necessarily have to be encoded but
 * in that case the original string is duplicated.
 *
 * @param url a string to be decoded.
 * @return new string with the URL decoded or NULL if decoding failed.
 * Note that the returned string should be explicitly freed when not
 * used anymore.
 */
char *urldecode(const char *url)
{
    int s = 0, d = 0, url_len = 0;
    char c;
    char *dest = NULL;

    if (!url)
        return NULL;

    url_len = strlen(url) + 1;
    dest = av_malloc(url_len);

    if (!dest)
        return NULL;

    while (s < url_len) {
        c = url[s++];

        if (c == '%' && s + 2 < url_len) {
            char c2 = url[s++];
            char c3 = url[s++];
            if (isxdigit(c2) && isxdigit(c3)) {
                c2 = av_tolower(c2);
                c3 = av_tolower(c3);

                if (c2 <= '9')
                    c2 = c2 - '0';
                else
                    c2 = c2 - 'a' + 10;

                if (c3 <= '9')
                    c3 = c3 - '0';
                else
                    c3 = c3 - 'a' + 10;

                dest[d++] = 16 * c2 + c3;

            } else { /* %zz or something other invalid */
                dest[d++] = c;
                dest[d++] = c2;
                dest[d++] = c3;
            }
        } else if (c == '+') {
            dest[d++] = ' ';
        } else {
            dest[d++] = c;
        }

    }

    return dest;
}

by
www.elesos.com
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...