/*****************************************************************************
 * Author:   Valient Gough <vgough@pobox.com>
 *
 *****************************************************************************
 * Copyright (c) 2004, Valient Gough
 * 
 * This program is free software; you can distribute it and/or modify it under 
 * the terms of the GNU General Public License (GPL), 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.
 */
                             
#ifndef _FileUtils_incl_
#define _FileUtils_incl_

#include "encfs.h"
#include "Interface.h"
#include "DirNode.h"

#include "Ptr.h"

using rel::Ptr;

bool fileExists( const char *fileName );

bool isDirectory( const char *fileName );

bool isAbsolutePath( const char *fileName );

const char *lastPathElement( const char *name );

struct EncFSConfig
{
    std::string creator;
    int subVersion;

    // interface of cipher
    rel::Interface cipherIface;
    // interface used for file name coding
    rel::Interface nameIface;
    int keySize; // reported in bits
    int blockSize; // reported in bytes
    std::string keyData;

    int blockMACBytes; // MAC headers on blocks..
    int blockMACRandBytes; // number of random bytes in the block header

    bool uniqueIV; // per-file Initialization Vector
    bool externalIVChaining; // IV seeding by filename IV chaining

    bool chainedNameIV; // filename IV chaining
};

enum ConfigType
{
    Config_None = 0,
    Config_Prehistoric,
    Config_V3,
    Config_V4,
    Config_V5
};

class Cipher;
typedef rel::OpaqueValue CipherKey;

struct EncFS_Root
{
    Ptr<Cipher> cipher;
    CipherKey volumeKey;
    Ptr<DirNode> root;

    EncFS_Root();
    ~EncFS_Root();
};

typedef Ptr<EncFS_Root> RootPtr;

/*
    Read existing config file.  Looks for any supported configuration version.
*/
ConfigType readConfig( const std::string &rootDir, EncFSConfig *config ); 

/*
    Save the configuration.  Saves back as the same configuration type as was
    read from.
*/
bool saveConfig( ConfigType type, const std::string &rootdir, 
	EncFSConfig *config );


RootPtr initFS( const std::string &rootDir,
	bool enableIdleTracking,  // turn on idle monitoring of filesystem
	bool createIfNotFound, // create filesystem if not found
	bool checkKey, // check crypto key decoding..
	bool forceDecode, // force return on MAC block failures..
	const std::string &passwordProgram ); 

RootPtr createV5Config( const std::string &rootDir, 
	bool enableIdleTracking,
	bool forceDecode,
	const std::string &passwordProgram );


void showFSInfo( const EncFSConfig &config );

// Read specifically a version 4 configuration file. 
bool readV3Config( const char *configFile, EncFSConfig *config,
	struct ConfigInfo *);
bool writeV3Config( const char *configFile, EncFSConfig *config);

bool readV4Config( const char *configFile, EncFSConfig *config,
	struct ConfigInfo *);
bool writeV4Config( const char *configFile, EncFSConfig *config);

bool readV5Config( const char *configFile, EncFSConfig *config,
	struct ConfigInfo *);
bool writeV5Config( const char *configFile, EncFSConfig *config);



CipherKey getUserKey(const Ptr<Cipher> &cipher);
CipherKey getUserKey(const std::string &passwordProgram, 
	             const Ptr<Cipher> &cipher,
		     const std::string &rootDir );
CipherKey getNewUserKey(const Ptr<Cipher> &cipher);

#endif
