Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > C and Base64_decode binary


Автор: pyqt 12.5.2008, 18:33
Привет всем!
Необходимо на С декодировать строку из Base64 и записать ее просто в переменную. В С я новичок, поэтому сильно не критикуйте smile

Пробовал разные имплементации base64, и самой быстрой и простой оказалась внутри PHP. Я вытащил эту функцию из PHP5.2.6 и попытался декодировать.
Просто текст - декодирует нормально, а вот бинарный - до определенного символа доходит - и все.

вот код:
Код

#include <string.h>
/* {{{ */

static const char base64_pad = '=';

static const short base64_reverse_table[256] = {
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -2, -1, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
    -2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2,
    -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
};
/* }}} */
unsigned char *unbase64(const unsigned char *str, int length, int *ret_length)
{
    const unsigned char *current = str;
    int ch, i = 0, j = 0, k;
    int strict = 0;
    /* this sucks for threaded environments */
    unsigned char *result;
    
    result = (unsigned char *)malloc(length + 1);

    /* run through the whole string, converting as we go */
    while ((ch = *current++) != '\0' && length-- > 0) {
        if (ch == base64_pad) break;

        ch = base64_reverse_table[ch];
        if ((!strict && ch < 0) || ch == -1) { /* a space or some other separator character, we simply skip over */
            continue;
        } else if (ch == -2) {
            free(result);
            return NULL;
        }

        switch(i % 4) {
        case 0:
            result[j] = ch << 2;
            break;
        case 1:
            result[j++] |= ch >> 4;
            result[j] = (ch & 0x0f) << 4;
            break;
        case 2:
            result[j++] |= ch >>2;
            result[j] = (ch & 0x03) << 6;
            break;
        case 3:
            result[j++] |= ch;
            break;
        }
        i++;
    }

    k = j;
    /* mop things up if we ended on a boundary */
    if (ch == base64_pad) {
        switch(i % 4) {
        case 1:
            free(result);
            return NULL;
        case 2:
            k++;
        case 3:
            result[k++] = 0;
        }
    }
    if(ret_length) {
        *ret_length = j;
    }
    result[j] = '\0';
    return result;
}


int main()
{
    unsigned char *input = "s/INCuVKJ0hjAAAAAAAAAAAKAAAAQAAAAHNWAQAAZAAAZAEAawAAWgAAZAAAZAEAawEAWgEAZAAAZAEAawIAWg==";
    char *output;
    output=unbase64(input, strlen(input),0);
    puts(output);
    printf("%d,%d\n",strlen(input),strlen(output));
}


Тут выводяться первые 9 символов из декодированной строки, и strlen(output) тоже выводит 9...

При чем если в цикле выводить каждый символ в терминал с помощью putchar() - тоже все будет нормально.
Как записать бинарный текст в переменную?

Заранее спасибо!

P.S. в php тоже декодирует нормально...
P.P.S Linux 2.6.24, gcc 

Автор: jonie 12.5.2008, 20:59
мда... я уже боюсь использовать пхп) тут есть куда оптимизировать...
Цитата

Как записать бинарный текст в переменную?


Код

unsigned char* p = {0,1,2,3,4,5,6,7,9}; 

?
у тебя уже будет указатель на буфер бинарных данных, просто работай с ним. char это один байт всего лишь.

ну вот чета типа такого:
Код

    const char *input =("s/INCuVKJ0hjAAAAAAAAAAAKAAAAQAAAAHNWAQAAZAAAZAEAawAAWgAAZAAAZAEAawEAWgEAZAAAZAEAawIAWg==");
    unsigned char *output;
    int rv;
    output=unbase64(reinterpret_cast<const unsigned char*>(input), strlen(input),&rv);
    for (int i=0;i<rv;++i)
    {
        printf("0x%x ",output[i]);     //вот тебе hex значения байтов...
    }
    free(output);  //не забываем о необходимости проверки на NULL и т.п.

Автор: pyqt 12.5.2008, 22:49
Спасибо! 
strlen() и puts() выводил первые символы, потому что в тексте содержался \0, а эти функции работают до этого символа

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)