// vim:sw=4 ts=4 et
// 
// by: willem hengeveld <itsme@xs4all.nl>
//     june 2003
//
// searching a 'known plain text' for a unnamed encrypted zip file.
//
#include <stdio.h>
#include <algorithm>
#include <string>
#include <vector>

// this is crc32.c from zlib
// just including the whole file, no need to look for matching header files.
#include "crc32.c"
using namespace std;
typedef vector<string> StringList;
typedef unsigned long ulong;
typedef unsigned char uchar;

ulong CalcCrc(const string& file)
{
    return crc32(0, (uchar*)file.c_str(), file.size());
}
string MakeFile(const StringList&  names)
{
    string str;
    for (StringList::const_iterator i= names.begin() ; i!=names.end() ; ++i)
    {
        if (!str.empty())
            str.append("\r\n");
        str.append(*i);
    }
    return str;
}
// see if I calculate the crc correctly
//    ( first go I had at crc I didn't, it seems the algorithm I use in 
//    http://www.xs4all.nl/~itsme/projects/sources/crc.c  is missing the final 'not' )
void test_crc()
{
    StringList names;
    // the names have been changed to protect, eeh. nobody really.
    names.push_back("filename1.txt");
    names.push_back("filename2.txt");
    names.push_back("morefiles.txt");

    string file= MakeFile(names);
    ulong crc= CalcCrc(file);

 
    printf("----------%08lx\n%s\n---------\n", crc, file.c_str());
}
long faculty(int n)
{
    long res= 1;
    while(n)
        res*= n--;
    return res;
}

// see if I use next_permutation correctly
//   ( first attempt at permuting, I stoped before getting them all, because
//     I had ordered the list in a way I assumed to be close to what I wanted
//     to find. this is not the lexicographucally first, and I first looped
//     until next_perm returned false. thus I added the faculty loop counter )
void test_perm()
{
    StringList names;
    // the names have been changed to protect, eeh. nobody really.
    names.push_back("filename1.txt");
    names.push_back("filename2.txt");
    names.push_back("morefiles.txt");
    printf("faculty(%d)= %ld\n", names.size(), faculty(names.size()));
    for (int i=faculty(names.size()) ; i>0 ; --i)
    {
        string file= MakeFile(names);
        printf("----------\n%s\n", file.c_str());
        next_permutation(names.begin(), names.end());
    }
}
// this was a list of 11 files, of which I only need to find the right order.
void findperm_file1()
{
    StringList names;
    // the names have been changed to protect, eeh. nobody really.
    names.push_back("filename1.txt");
    names.push_back("filename2.txt");
    names.push_back("morefiles.txt");
    ///..... 8 more files left out.

    for (int i=faculty(names.size()) ; i>0 ; --i)
    {
        string file= MakeFile(names);
        ulong crc= CalcCrc(file);
        if (crc==0xdc4a2aa6)
        {
            printf("----------\n%s\n---------\n", file.c_str());
        }
        next_permutation(names.begin(), names.end());
    }
}
// here the list of files came out 1 character short,
// trying all ascii characters either in front or after each name.
void findperm_file2()
{
    int tested=0;
    for (int ti=0 ; ti<2 ; ti++)
    for (int ni=0 ; ni<8 ; ni++)
    {
        for (int c=0 ; c<256 ; c++)
        {
            StringList names;
            // the names have been changed to protect, eeh. nobody really.
            names.push_back("filename1.txt");
            names.push_back("filename2.txt");
            names.push_back("morefiles.txt");
            // 5 more names left out.


            if (ti==0)
                names[ni].push_back((char)c);
            else
                names[ni]=((char)c) + names[ni];
            for (int i=faculty(names.size()) ; i>0 ; --i)
            {
                tested++;
                string file= MakeFile(names);
                ulong crc= CalcCrc(file);
                if (crc==0x44270fac)
                {
                    printf("----------\n%s\n---------\n", file.c_str());
                }
                next_permutation(names.begin(), names.end());
            }
        }
    }
    printf("did %d tests\n", tested);
}
int main(int argc, char **argv)
{
    findperm_file2();
}

