/*
*  Naamari - an AES/SHA-based manual file crypto-synchronizer for cloud transfers
*  Copyright (c) 2015-2017 Sunkware
*  Key FP = 6B6D C8E9 3438 6E9C 3D97  56E5 2CE9 A476 99EF 28F6
*
*  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/>.
*
*  ----------------------------------------------------------------
*  WWW:       sunkware.org
*  E-mail:    sunkware@gmail.com
*  ----------------------------------------------------------------
*/

#include "omenwork.h"

namespace cryptrav
{

namespace OMEN
{


int            clearNomenData(NomenData* pNomenData)
{
 if (pNomenData == NULL)
  return CTERR_NULL_POINTER;

 memset(pNomenData, 0, sizeof(NomenData));

 return CTERR_OK;
}

int            readNomen(QString absoluteFilePath, NomenData* pNomenData)
{
 if (pNomenData == NULL)
  return CTERR_NULL_POINTER;


 QFile nomenFile(absoluteFilePath);

 if ( !nomenFile.exists() )
  return CTERR_FILE_NOT_FOUND;

 if ( QFileInfo(nomenFile).size() != HASH_SIZE )
  return CTERR_FILE_WRONG_SIZE;


 if ( !nomenFile.open(QIODevice::ReadOnly) )
  return CTERR_FILE_CANNOT_OPEN;

 if ( !nomenFile.isOpen() )
  return CTERR_FILE_NOT_OPEN;

 if ( !nomenFile.isReadable() )
  return CTERR_FILE_WRONG_MODE;


 nomenFile.read( (char *)(pNomenData -> randomen), HASH_SIZE);

 nomenFile.close();


 return CTERR_OK;
}


int            writeNomen(QString absoluteFilePath, NomenData* pNomenData)
{
 if (pNomenData == NULL)
  return CTERR_NULL_POINTER;


 QFile nomenFile(absoluteFilePath);

 if ( !nomenFile.open(QIODevice::WriteOnly) )
  return CTERR_FILE_CANNOT_OPEN;

 if ( !nomenFile.isOpen() )
  return CTERR_FILE_NOT_OPEN;

 if ( !nomenFile.isWritable() )
  return CTERR_FILE_WRONG_MODE;


 nomenFile.write( (char *)(pNomenData -> randomen), HASH_SIZE);

 nomenFile.close();


 return CTERR_OK;
}


int            clearCryptomenData(CryptomenData* pCryptomenData)
{
 if (pCryptomenData == NULL)
  return CTERR_NULL_POINTER;

 memset(pCryptomenData, 0, sizeof(CryptomenData));

 return CTERR_OK;
}


int            readCryptomen(QString absoluteFilePath, CryptomenData* pCryptomenData)
{
 if (pCryptomenData == NULL)
  return CTERR_NULL_POINTER;


 QFile cryptomenFile(absoluteFilePath);

 if ( !cryptomenFile.exists() )
  return CTERR_FILE_NOT_FOUND;

 if ( QFileInfo(cryptomenFile).size() != PACKED_CRYPTOMEN_DATA_SIZE )
  return CTERR_FILE_WRONG_SIZE;


 if ( !cryptomenFile.open(QIODevice::ReadOnly) )
  return CTERR_FILE_CANNOT_OPEN;

 if ( !cryptomenFile.isOpen() )
  return CTERR_FILE_NOT_OPEN;

 if ( !cryptomenFile.isReadable() )
  return CTERR_FILE_WRONG_MODE;


 QBuffer   packedCryptomenData;
 packedCryptomenData.setData(cryptomenFile.read(cryptomenFile.size())); // file's opened by now

 cryptomenFile.close();


 if ( !packedCryptomenData.open(QBuffer::ReadOnly) )
  {
   packedCryptomenData.buffer().clear();
   return CTERR_BUFFER_CANNOT_OPEN;
  }


 quint8        boolByte;

 packedCryptomenData.read( (char*)&(pCryptomenData -> formatVer), 1);


 switch (pCryptomenData -> formatVer)
  {
   case CRYPTOMEN_FORMAT_INITIAL_VER:

    packedCryptomenData.read( (char*)&boolByte, 1);
    pCryptomenData -> isNear = (boolByte != 0);

    packedCryptomenData.read( (char*)pCryptomenData -> nearSalt, HASH_SIZE);
    packedCryptomenData.read( (char*)&(pCryptomenData -> nearTime), 8);
    packedCryptomenData.read( (char*)&(pCryptomenData -> nearSize), 8);


    packedCryptomenData.read( (char*)&boolByte, 1);
    pCryptomenData -> isFar = (boolByte != 0);

    packedCryptomenData.read( (char*)pCryptomenData -> farSalt, HASH_SIZE);
    packedCryptomenData.read( (char*)&(pCryptomenData -> farTime), 8);
    packedCryptomenData.read( (char*)&(pCryptomenData -> farSize), 8);


    packedCryptomenData.read( (char*)&(pCryptomenData -> action), 1);

   break;


   default:

    boolByte = 0;

    packedCryptomenData.close();
    packedCryptomenData.buffer().clear();

    return CTERR_FORMAT_UNKNOWN;

   break;
  }


 packedCryptomenData.close();


 boolByte = 0;
 packedCryptomenData.buffer().clear();


 return CTERR_OK;
}


int            writeCryptomen(QString absoluteFilePath, CryptomenData* pCryptomenData)
{
 if (pCryptomenData == NULL)
  return CTERR_NULL_POINTER;


 QBuffer   packedCryptomenData;
 packedCryptomenData.buffer().resize(PACKED_CRYPTOMEN_DATA_SIZE);


 packedCryptomenData.buffer().clear();


 if ( !packedCryptomenData.open(QBuffer::WriteOnly) )
  return CTERR_BUFFER_CANNOT_OPEN;


 quint8        boolByte;

 packedCryptomenData.write( (char*)&(pCryptomenData -> formatVer), 1);


 boolByte = (pCryptomenData -> isNear) ? 1 : 0;
 packedCryptomenData.write( (char*)&boolByte, 1);

 packedCryptomenData.write( (char*)pCryptomenData -> nearSalt, HASH_SIZE);
 packedCryptomenData.write( (char*)&(pCryptomenData -> nearTime), 8);
 packedCryptomenData.write( (char*)&(pCryptomenData -> nearSize), 8);


 boolByte = (pCryptomenData -> isFar) ? 1 : 0;
 packedCryptomenData.write( (char*)&boolByte, 1);

 packedCryptomenData.write( (char*)pCryptomenData -> farSalt, HASH_SIZE);
 packedCryptomenData.write( (char*)&(pCryptomenData -> farTime), 8);
 packedCryptomenData.write( (char*)&(pCryptomenData -> farSize), 8);


 packedCryptomenData.write( (char*)&(pCryptomenData -> action), 1);


 packedCryptomenData.close();


 QFile cryptomenFile(absoluteFilePath);

 if ( !cryptomenFile.open(QIODevice::WriteOnly) )
  return CTERR_FILE_CANNOT_OPEN;

 if ( !cryptomenFile.isOpen() )
  return CTERR_FILE_NOT_OPEN;

 if ( !cryptomenFile.isWritable() )
  return CTERR_FILE_WRONG_MODE;

 if ( cryptomenFile.write( packedCryptomenData.buffer() ) != packedCryptomenData.size() )
  return CTERR_FILE_WRONG_SIZE;

 cryptomenFile.close();


 boolByte = 0;
 packedCryptomenData.buffer().clear();


 return CTERR_OK;
}


} // namespace "OMEN"

} // namespace "cryptrav"
