/*
To compile, save this code as wbz2jpg.c 
Then run the command: gcc wbz2jpg.c -o wbz2jpg 

A program to convert .wbz files from webshots.com
to .jpg files by stripping excess bytes before 
Jpeg Header and bytes for thumbnail image.

When parsing the first format (which doesn't have a JPEG header)
a thumbnail is in between, which gets stripped. 

- Stage 0 = don't write
- Search for JPEG header
                                                                                
- Stage 1 = write
- Search for delimiter (ffee000e)
                                                                                
- Stage 2 = don't write
- Search for two more occurrences of delimiter (to skip thumbnail)
                                                                                
- Stage 3 = write
- Search for JPEG footer.

The second type has encrypted header and so I decrypt
with one of two keys. the first 100 bytes after WWBB0000 
or WWBB1111 are replaced by the next 100 bytes which
need to be decrypted first
then the original 2nd 100 bytes then the rest of file.
By Gyrf on 22 March 2001
Updated by Dan Hersam 02 May 2005
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ALGO1 "WWBB0000"
#define ALGO2 "WWBB1111"
#define PREFIX 0xFF
#define HEADER 0xD8
#define FOOTER 0xD9
#define DELIMITER 0xEE

int main ( int argc, char *argv[] )
{
    FILE *fp1, *fp2;
    char *infile, *outfile;
    char isalgo1[ 9 ];
    int stage = 0;
    int letter, letter2;
    int delimiter = 0;
    int vals[ 2 ];
    int verwb = 0, cnt = 0, cnt1 = 0, A[ 100 ], B[ 100 ], counter = 0;
    int magicvalue = 0, C[ 100 ];

    if ( argc >= 3 )
    {
        infile = argv[ 1 ];
        outfile = argv[ 2 ];
    }
    else
    {
        printf( "Usage: wbz2 inputfile.wbz ouputfile.jpg\n" );
        exit( 1 );
    }

    if ( ( fp1 = fopen( infile, "r" ) ) == NULL )
    {
        fprintf( stderr, "Can't open infile %s\n", infile );
        exit( 1 );
    }

    if ( ( fp2 = fopen( outfile, "w" ) ) == NULL )
    {
        fprintf( stderr, "Can't open outfile %s\n", outfile );
        fclose( fp1 );  
        exit( 1 );
    }

    while ( ( letter = fgetc( fp1 ) ) != EOF )
    {
        /* Check for header, footer and delimiter. */

        if ( letter == PREFIX )
        {
            letter2 = fgetc( fp1 );

            switch ( stage )
            {
                case 0:
                    if ( HEADER == letter2 )
                    {
                        stage++;
                    }
                    break;

                case 1:
                case 2:
                    if ( DELIMITER == letter2 )
                    {
                        vals[ 0 ] = fgetc( fp1 );
                        vals[ 1 ] = fgetc( fp1 );

                        if ( vals[ 0 ] == 0x00 && vals[ 1 ] == 0x0E )
                        {
                            delimiter++;

                            if ( delimiter == 1 )
                            {
                                stage++;
                            }
                            else if ( delimiter == 3 )
                            {
                                stage++;
                            }
                        }

                        fseek( fp1, -2L, SEEK_CUR );
                    }
                    break;

                case 3:
                    if ( FOOTER == letter2 )
                    {
                        stage++;
                    }
                    break;
            }

            fseek( fp1, -1L, SEEK_CUR ); /* back up one */
        }

        if ( stage == 1 || stage == 3 )
        {
            fputc( letter ,fp2 );       /* Write the letter to the .jpg */
        }
    }

    fputc( PREFIX, fp2 );
    fputc( FOOTER, fp2 );

    if ( stage > 3 )
    {
        printf( "%s written, type 1 Adobe embedded.\n", outfile );
        fclose( fp1 );
        fclose( fp2 );
        return 0;
    }
    else
    { 
        rewind( fp1 );
        rewind( fp2 );
    }

    while ( cnt1 < 100 && ( ( letter = fgetc( fp1 ) ) != EOF ) )
    {
        if ( letter == 0x57 )       /* W in WWBBxxxx */
        {
            isalgo1[ 0 ] = letter;
            isalgo1[ 1 ] = fgetc( fp1 );
            isalgo1[ 2 ] = fgetc( fp1 );
            isalgo1[ 3 ] = fgetc( fp1 );
            isalgo1[ 4 ] = fgetc( fp1 );
            isalgo1[ 5 ] = fgetc( fp1 );
            isalgo1[ 6 ] = fgetc( fp1 );
            isalgo1[ 7 ] = fgetc( fp1 );
            isalgo1[ 8 ] = '\0';

            if ( strcmp( ALGO1, isalgo1 ) == 0 )
            {
                verwb = 1;
            }

            if ( strcmp( ALGO2, isalgo1 ) == 0 )
            {
                verwb = 2;
            }

            if ( !verwb )
            {
                fseek( fp1, -7L, SEEK_CUR );
            }
        }

        /* matrix stuff goes here. write now decrypt next */

        if ( verwb > 1 )
        {
            if ( verwb == 1 ) magicvalue = 0xA4;
            if ( verwb == 2 ) magicvalue = 0xF2;

            while ( cnt < 100 && ( ( letter = fgetc( fp1 ) ) != EOF ) )
            {
                A[ cnt ] = letter;
                cnt++;
            }

            while ( cnt1 < 100 && ( ( letter = fgetc( fp1 ) ) != EOF ) )
            {
                C[ cnt1 ] = letter;
                B[ cnt1 ] = letter;
                cnt1++;
            }

            /* Decryption algorithm */

            counter = 0;
            while ( counter < 100 )
            {
                A[ counter ] = ~A[ counter ];
                B[ counter ] = B[ counter ] ^ A[ counter ];
                B[ counter ] = B[ counter ] ^ magicvalue;
                counter++;
            }
        }
    }

    counter = 0;     /* altered 2nd 100 bytes */
    while ( counter < 100 )
    {
        letter = B[ counter ];
        fputc( letter, fp2 );
        counter++;
    }

    counter = 0;    /* saved 2nd 100 bytes */
    while ( counter < 100 )
    {
        letter = C[ counter ];
        fputc( letter, fp2 );
        counter++;
    }

    while ( ( letter = fgetc( fp1 ) ) != EOF )
    {
        fputc( letter, fp2 );
    }       

    printf( "%s written, type %s encrypted.\n", outfile, isalgo1 );
    fclose( fp1 );
    fclose( fp2 );

    return 0;
}

