/*
*  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 "tester.h"

namespace cryptrav
{


Tester::Tester(ContextGlob* pContext, StateGlob* pState)
{
 contextP = pContext;
 stateP = pState;
}


int            Tester::test(QString pathInNominis, QString objName)
{
 Pather        pather(contextP);

 Translator    translator(contextP, stateP);


 QFile         nomen(pather.getNominisAbs(pathInNominis) + objName);

 if ( !nomen.exists() )
  return CTERR_OBJECT_NOT_FOUND;

 QFileInfo     nomenInfo(nomen);


 int err = CTERR_OK;


 if ( nomenInfo.isDir() ) // Dir. Additional checks and recursion for list of its elements follow...
  {
   PRINT::putLine("[" + nomenInfo.fileName() + "]...");

   QFileInfoList entryInfoList = QDir(pather.getNominisAbs(pathInNominis) + objName).entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::DirsFirst);

   for (int i = 0; i < entryInfoList.count(); i++)
    {
     Tester tester(contextP, stateP);

     err = tester.test(pathInNominis + objName + "/", (entryInfoList.at(i)).fileName());

     if (err != CTERR_OK) { // hash comparison error or padding error or cannot read nomen/cryptomen
       return err;
      }

    }

   PRINT::putLine("...[" + nomenInfo.fileName() + "]");
  }

   else // File. Checking states...

  {
   PRINT::put("\"" + nomenInfo.fileName() + "\": ");

   OMEN::NomenData nomenData;
   OMEN::clearNomenData(&nomenData);

   if ( OMEN::readNomen(nomenInfo.absoluteFilePath(), &nomenData) == CTERR_OK )
    {
     QString cryptomenStr = translator.makeCryptomenStr(nomenData.randomen);

     OMEN::CryptomenData cryptomenData;
     OMEN::clearCryptomenData(&cryptomenData);

     if ( OMEN::readCryptomen(pather.getHarbourAbs("/." + cryptomenStr), &cryptomenData) == CTERR_OK )
      {

       if (cryptomenData.isNear)
        {
         PRINT::put("testing... ");

         QFile source(pather.getHarbourAbs("/" + cryptomenStr));


         err = translator.test(&source, cryptomenData.nearSalt);

         switch (err) {
           case CTERR_OK:
            PRINT::put("ok.");
           break;

           case CTERR_CHECKSUM_WRONG:
            PRINT::put("hash comparison failed.");
           break;

           case CTERR_PADDING_WRONG:
            PRINT::put("incorrect padding.");
           break;

           default:
            PRINT::put("failed.");
           break;
          }

        }
         else PRINT::put("not near.");

      }
       else
      {
       err = CTERR_FILE_CANNOT_READ;

       PRINT::put("cannot read cryptomen.");
      }


     OMEN::clearCryptomenData(&cryptomenData);

     cryptomenStr.clear();
    }
     else
    {
     err = CTERR_FILE_CANNOT_READ;

     PRINT::put("cannot read nomen.");
    }


   PRINT::LF();

   OMEN::clearNomenData(&nomenData);
  }


 return err;
}



Tester::~Tester()
{
 contextP = NULL;
 stateP = NULL;
}


} // namespace "cryptrav"
