// g++ -g -Wall `pkg-config --cflags dclib` `pkg-config --libs dclib` -o dclib-dump-database dclib-dump-database.cpp

/***************************************************************************
      dclib-dump-database.cpp  -  Dump the contents of dclib's database
                             -------------------
    begin                : Sun Aug 24 2008
    copyright            : (C) 2008 by Edward Sheldrake
    email                : ejs1920@yahoo.co.uk
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

/*
 * Print out the contents of dclib's files and hash database.
 */

#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif

#include <dclib/core/cstring.h>
#include <dclib/core/cbytearray.h>
#include <dclib/core/cbase32.h>

// only for struct fbo/hbo
#include <dclib/core/types.h>
#include <dclib/csearchindex.h>

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

int main( int argc, char *argv[] )
{
	if ( argc != 2 )
	{
		printf("Usage: %s [directory containing your .dc directory]\n",argv[0]);
		return 100;
	}
	
	CString prefix = argv[1];
	prefix += "/.dc/";
	
	/* because ctime adds an \n */
	CString s;
	
	CByteArray filebase, filepaths, filenames;
	CByteArray hashbase;
	struct filebaseobject fbo;
	
	if ( filebase.LoadFromFile(prefix + "database.bin") == false )
	{
		printf("Failed to load database.bin from %s\n",prefix.Data());
		return 200;
	}
	
	filepaths.LoadFromFile(prefix + "pathbase.bin");
	filenames.LoadFromFile(prefix + "filebase.bin");
	hashbase.LoadFromFile(prefix + "hashbase.bin");

	printf("***** Files database *****\n\n");
	
	for ( unsigned long i = 0; i < filebase.Size(); i += sizeof(struct filebaseobject) )
	{
		memcpy( &fbo, filebase.Data()+i, sizeof(struct filebaseobject) );
		
		printf("%lu ",i);
		printf("filetype=%u ",fbo.m_eFileType);
		printf("size=%llu ",fbo.m_nSize);
		printf("pathindex=%lu ",fbo.m_nPathIndex);
		printf("fileindex=%lu ",fbo.m_nFileIndex);
		printf("hashindex=%lu ",fbo.m_nHashIndex);
		printf("modtime=%lu ",fbo.m_tModTime);
		
		printf("pathname=");
		if ( fbo.m_nPathIndex < filepaths.Size() )
		{
			printf( "'%s'", (char*) filepaths.Data()+fbo.m_nPathIndex );
		}
		else
		{
			printf("(invalid index)");
		}
		
		printf(" filename=");
		if ( fbo.m_nFileIndex < filenames.Size() )
		{
			printf( "'%s'", (char*) filenames.Data()+fbo.m_nFileIndex );
		}
		else
		{
			printf("(invalid index)");
		}
		
		if ( (fbo.m_nHashIndex != (unsigned long)-1) && (fbo.m_nHashIndex + sizeof(struct hashbaseobject) > hashbase.Size()) )
		{
			printf(" *** invalid hashindex ***");
		}
		
		s = ctime(&fbo.m_tModTime);
		s = s.Left( s.Length()-1 );
		printf(" modified='%s'\n",s.Data());
		
	}
	
	CByteArray hashpaths, hashnames, hashindex;
	CByteArray hash;
	CString tth;
	struct hashbaseobject hbo;
	
	hashpaths.LoadFromFile(prefix + "hashpathbase.bin");
	hashnames.LoadFromFile(prefix + "hashfilebase.bin");
	hashindex.LoadFromFile(prefix + "hashindex.bin");
	
	printf("\n\n***** Hash database *****\n\n");
	
	for ( unsigned long i = 0; i < hashbase.Size(); i += sizeof(struct hashbaseobject) )
	{
		memcpy( &hbo, hashbase.Data()+i, sizeof(struct hashbaseobject) );
		
		printf("%lu ",i);
		printf("size=%llu ",hbo.m_nSize);
		printf("pathindex=%lu ",hbo.m_nPathIndex);
		printf("fileindex=%lu ",hbo.m_nFileIndex);
		printf("hashindex=%lu ",hbo.m_nHashIndex);
		printf("leavesindex=%lu ",hbo.m_nHashLeavesIndex);
		printf("modtime=%lu ",hbo.m_tModTime);
		
		printf("pathname=");
		if ( hbo.m_nPathIndex < hashpaths.Size() )
		{
			printf( "'%s'", (char*) hashpaths.Data()+hbo.m_nPathIndex );
		}
		else
		{
			printf("(invalid index)");
		}
		
		printf(" filename=");
		if ( hbo.m_nFileIndex < hashnames.Size() )
		{
			printf( "'%s'", (char*) hashnames.Data()+hbo.m_nFileIndex );
		}
		else
		{
			printf("(invalid index)");
		}
		
		s = ctime(&hbo.m_tModTime);
		s = s.Left( s.Length()-1 );
		printf(" modified='%s' ", s.Data() );
		
		printf("tth=");
		if ( hbo.m_nHashIndex + 24 <= hashindex.Size() )
		{
			hash.SetSize(0);
			hash.Append( hashindex.Data()+hbo.m_nHashIndex, 24 );
			
			CBase32::Encode( &tth, &hash );
			printf( "'%s'", tth.Data() );
		}
		else
		{
			printf("(invalid index)");
		}
		
		printf("\n");
	}
	
	return 0;
}
