*}
codea teams

Base64 Decode



Decode a string from base64 encoding to ascii. The char * returned must be free'd after use. len is a return pointer with the length of the string returned.

    
char to_b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

char* b64dec(const char* string, int *len)
{

    /* return a decoded memchunk, or a null pointer in case of failure */
    int rc = 0;
    char *data = NULL;
    int count = 0, rem = 0;
    int i, vrfy;
    int qw = 0, tw = 0;
    int length;
    const char *tmp;
    int skip;
    char ch;
    char bits;

    if (!string)
        return NULL;

    if (len <= 0)
        return NULL;

    if (string)
    {
            length = strlen(string);
             /* do a format verification first */
            if (length > 0)
            {
                
                tmp = string;

                while (length > 0)
                {
                    skip = strspn(tmp, to_b64);
                        
                    count += skip;
                    length -= skip;
                    tmp += skip;
                    if (length > 0)
                    {
                        vrfy = strcspn(tmp, to_b64);

                        for (i = 0; i < vrfy; i++)
                        {
                            if (isspace(tmp[i]))
                                continue;

                            if (tmp[i] == '=')
                            {
                                /* we should check if we're close to the end of the string */
                                rem = count % 4;
                                /* rem must be either 2 or 3, otherwise no '=' should be here */
                                if (rem < 2)
                                    return 0;

                                /* end-of-message recognized */
                                break;
                            }
                            else
                            {
                                /* Transmission error; RFC tells us to ignore this, but:
                                 *  - the rest of the message is going to even more corrupt since we're sliding bits out of place
                                 * If a message is corrupt, it should be dropped. Period.
                                 */

                                return 0;
                            }
                        }
                        length -= vrfy;
                        tmp += vrfy;
                        
                    } //end of while loop
                }

                rc = ((count / 4) * 3 + (rem ? (rem - 1) : 0));

                if (rc)
                {
                    if (count > 0)
                    {
                        
                        qw = 0;
                        tw = 0;
                        data = (char *)malloc(rc + 1);
                        memset(data, '\0', rc + 1);
                        length = strlen(tmp = string);
                        
                        for (i = 0; i < length; i++)
                        {
                            ch = string[i];
                            //char bits;

                            if (isspace(ch))
                                continue;

                            bits = 0;
                            if ((ch >= 'A') && (ch <= 'Z'))
                            {
                                bits = (unsigned char)(ch - 'A');
                            }
                            else if ((ch >= 'a') && (ch <= 'z'))
                            {
                                bits = (unsigned char)(ch - 'a' + 26);
                            }
                            else if ((ch >= '0') && (ch <= '9'))
                            {
                                bits = (unsigned char)(ch - '0' + 52);
                            }
                            else if ( ch == '+')
                            {
                                bits = (unsigned char) 62;
                            }
                            else if ( ch == '/')
                            {
                                bits = (unsigned char) 63;
                            }
                            else if (ch == '=')
                            {
                                break;
                            }
                            else
                            {
                                bits = (unsigned char) 'y';
                            }
                            
                            
                            switch (qw++)
                            {
                            case 0:
                                data[tw+0] = (bits << 2) & 0xfc;
                                *len = tw;
                                break;
                            case 1:
                                data[tw+0] |= (bits >> 4) & 0x03;
                                data[tw+1] = (bits << 4) & 0xf0;
                                *len = tw + 1;
                                break;
                            case 2:
                                data[tw+1] |= (bits >> 2) & 0x0f;
                                data[tw+2] = (bits << 6) & 0xc0;
                                *len = tw + 2;
                                break;
                            case 3:
                                data[tw+2] |= bits & 0x3f;
                                *len = tw + 2;
                                break;
                            }

                            if (qw == 4)
                            {
                                qw = 0;
                                tw += 3;
                                *len = tw;
                            }
                        } //end if for loop
                        
                    }
                }
            }
        }

        return data;
}