//
// tardy - a tar post-processor
// Copyright (C) 1998, 1999, 2002, 2008, 2009, 2011 Peter Miller
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
//

#include <libtardy/ac/ctype.h>
#include <libtardy/ac/string.h>

#include <libtardy/tar/input/filter/clean.h>


tar_input_filter_clean::~tar_input_filter_clean()
{
}


tar_input_filter_clean::tar_input_filter_clean(
    const tar_input::pointer &a_deeper,
    int a_flag
) :
    tar_input_filter(a_deeper),
    flag(a_flag)
{
}


tar_input::pointer
tar_input_filter_clean::create(const tar_input::pointer &a_deeper, int a_flag)
{
    return pointer(new tar_input_filter_clean(a_deeper, a_flag));
}


static rcstring
launder(const rcstring &s, int flag)
{
    //
    // temporary buffer to hold string while being constructed
    //
    static char *buffer;
    static size_t buffer_max;
    if (buffer_max < s.size())
    {
        delete [] buffer;
        buffer_max = 16;
        while (buffer_max < s.size())
            buffer_max <<= 1;
        buffer = new char [buffer_max];
    }

    char *bp = buffer;
    const char *sp = s.c_str();
    for (;;)
    {
        unsigned char c = *sp++;
        if (!c)
            break;
        if ((flag & tar_input_filter_clean::flag_space) && isspace(c))
            c = '-';
        if ((flag & tar_input_filter_clean::flag_print) && !isprint(c))
            c = '-';
        if
        (
            (flag & tar_input_filter_clean::flag_shell)
        &&
            strchr("\"#$&'()*:;<=>?[\\]^`{|}", c)
        )
            c = '-';
        if ((flag & tar_input_filter_clean::flag_down) && isupper(c))
            c = tolower(c);
        if ((flag & tar_input_filter_clean::flag_up) && islower(c))
            c = toupper(c);
        *bp++ = c;
    }
    return rcstring(buffer, bp - buffer);
}


bool
tar_input_filter_clean::read_header(tar_header &h)
{
    bool ok = tar_input_filter::read_header(h);
    if (ok)
        h.name = launder(h.name, flag);
    return ok;
}
