/*
    cookietool is (c) 1995-2001 by Wilhelm Noeker (wnoeker@t-online.de)

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA

 */


/*========================================================================*\
 |  File: cookietool.c                                 Date: 25 Oct 1997  |
 *------------------------------------------------------------------------*
 |             Remove duplicate entries from a cookie file,               |
 |                various options for sorting the output.                 |
 | Expected file format is plain text with a "%%" line ending each cookie.|
 |                     See help() for usage notes.                        |
 |                                                                        |
\*========================================================================*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "strstuff.h"
#include "cookio.h"
#include "compress.h"

char version[] = "$VER: cookietool 2.5 (22.03.2001)";


#define FBUFSIZE 16384          /* we'll use larger file buffers */



/*
 * Print a help text and nag about illegal parameter <s>
 */
void help( UBYTE *s )
    {
    if( s )
        printf( "illegal option '%s'\n", s );
    printf( "usage:  cookietool [options] <database> [logfile]\n" );
    printf( "where options are:\n" );
    printf( " -p      passive, don't delete anything\n" );
    printf( " -b      treat 'abbreviations' as doubles (i.e. delete them, too)\n" );
    printf( " -s      sort cookies\n" );
    printf( " -sl      \" , looking at the last line only\n" );
    printf( " -sw      \" , looking at the last word only\n" );
    printf( " -s<sep>  \" , starting after the last <sep>, e.g. '-s--'\n" );
    printf( " -ss      \" , by size\n" );
    printf( " -f[0-3] cookie format: words, lines, %%, %%%% (default: %d)\n", DEF_FMT );
    printf( " -F[0-3] force output in a different format\n" );
    printf( " -d[0-3] how fussy about word delimiters? (default: 2)\n" );
    printf( " -c      case sensitive comparisons\n" );
    printf( " -a      if <logfile> exists, append to it\n" );
    printf( " -o      overwrite directly, no tempfile (caution!)\n" );
    }



int main( int argc, char *argv[] )
    {
    UBYTE *s;
    int dirty = 0, append = 0, action = DUPDEL_MATCH, finalsort = SORT_RESTORE;
    int case_sense = 0, bordermode = 2;
    int i_fmt = DEF_FMT, o_fmt = DEF_FMT;
    int force_fmt = -1;
    UBYTE name1[ 100 ], name2[ 100 ], name3[ 100 ];
    UBYTE hooktarget[ 16 ];
    FILE *infile, *outfile, *logfile;

    name1[ 0 ] = name2[ 0 ] = name3[ 0 ] = '\0';
    if( argc < 2 )
        {
        help( NULL );
        return 5;
        }
    while( --argc )
        {
        s = *++argv;
        if( *s != '-' )
            {
            if( name1[ 0 ] == '\0' )
                strcpy( name1, s );
            else
                strcpy( name3, s );
            }
        else
            {
            s++;
            switch( *s++ )
                {
                case 's':
                    switch( *s )
                        {
                        case '\0':
                            finalsort = SORT_BODY;
                            break;
                        case 's':
                            finalsort = SORT_SIZE;
                            break;
                        case 'l':
                            finalsort = SORT_LASTLINE;
                            break;
                        case 'w':
                            finalsort = SORT_LASTWORD;
                            break;
                        default:
                            if( ispunct( *s ) )
                                {
                                finalsort = SORT_HOOKTARGET;
                                str_ncpy( hooktarget, s, sizeof( hooktarget ) );
                                }
                            else
                                goto bad_parm;
                        }
                    break;
                case 'd':
                    if( isdigit( *s ) )
                        bordermode = atoi( s );
                    else
                        goto bad_parm;
                    break;
                case 'f':
                    if( isdigit( *s ) )
                        i_fmt = atoi( s );
                    else
                        goto bad_parm;
                    break;
                case 'F':
                    if( isdigit( *s ) )
                        force_fmt = atoi( s );
                    else
                        goto bad_parm;
                    break;
                case 'c':
                    case_sense = 1;
                    break;
                case 'a':
                    append = 1;
                    break;
                case 'b':
                    action = DUPDEL_ABBREVS;
                    break;
                case 'p':
                    action = DUPDEL_NONE;
                    break;
                case 'o':
                    dirty = 1;
                    break;
                default:
                    goto bad_parm;
                }
            }
        }
    o_fmt = (force_fmt >= 0) ? force_fmt : i_fmt;
    /* important, before calling anything from strstuff: */
    str_setup( bordermode, case_sense );
    if( *name1 == '\0' )
        {
        help( NULL );
        return 5;
        }
    if( dirty )
        {
        strcpy( name2, name1 );
        printf( "Warning!  You have enabled direct writeback mode!\n" );
        printf( "\e[2mDon't break (or crash) cookietool now, " );
        printf( "or you will inevitably lose data!\e[0m\n" );
        }
    else
        strcpy( name2, "ct_temp_crunchfile" );
    printf( "CookieTool " );
    print_strstat();
    if( i_fmt == o_fmt )
        {
        printf( "File format: " );
        print_fmtinfo( i_fmt );
        }
    else
        {
        printf( "Input format: " );
        print_fmtinfo( i_fmt );
        printf( "Output format: " );
        print_fmtinfo( o_fmt );
        }
    if( !(infile = fopen( name1, "r" ) ) )
        {
        printf( "Can't open %s for input!\n", name1 );
        return 10;
        }
    setvbuf( infile, NULL, _IOFBF, FBUFSIZE );
    if( *name3 )
        {
        if( !append && (logfile = fopen( name3, "r" )) )
            {
            printf( "Error: '%s' exists!  Use -a to append.\n", name3 );
            return 10;
            }
        if( !(logfile = fopen( name3, "a" ) ) )
            {
            printf( "Can't open %s for output!\n", name3 );
            return 10;
            }
        }
    else
        logfile = NULL;
    read_cookies( infile, i_fmt );
    fclose( infile );
    one_cookie( action, finalsort, hooktarget, logfile, o_fmt );
    if( logfile )
        fclose( logfile );
    if( !(outfile = fopen( name2, "w" ) ) )
        {
        printf( "Can't open %s for output!\n", name2 );
        return 10;
        }
    setvbuf( outfile, NULL, _IOFBF, FBUFSIZE );
    write_cookies( outfile, o_fmt, 0 );
    fclose( outfile );
    if( !dirty )
        {                       /* replace the input file */
        if( remove( name1 ) != 0 || rename( name2, name1 ) != 0 )
            {
            printf( "Couldn't overwrite the input file!  Your cookies are in '%s'.\n", name2 );
            return 5;
            }
        }
    return 0;
bad_parm:
    help( argv[ 0 ] );
    return 5;
    }

