| 
    
       /*
 
     | 
  
  
     | 
    
        Copyright (c) 2003, Dominik Reichl <dominik.reichl@t-online.de>
 
     | 
  
  
     | 
    
        All rights reserved.
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
        LICENSE TERMS
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
        Redistribution and use in source and binary forms, with or without
 
     | 
  
  
     | 
    
        modification, are permitted provided that the following conditions are met:
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
        * Redistributions of source code must retain the above copyright notice, this
 
     | 
  
  
     | 
    
          list of conditions and the following disclaimer.
 
     | 
  
  
     | 
    
        * Redistributions in binary form must reproduce the above copyright notice,
 
     | 
  
  
     | 
    
          this list of conditions and the following disclaimer in the documentation
 
     | 
  
  
     | 
    
          and/or other materials provided with the distribution.
 
     | 
  
  
     | 
    
        * Neither the name of ReichlSoft nor the names of its contributors may be used
 
     | 
  
  
     | 
    
          to endorse or promote products derived from this software without specific
 
     | 
  
  
     | 
    
          prior written permission.
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
        DISCLAIMER
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
     | 
  
  
     | 
    
        AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
     | 
  
  
     | 
    
        IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
     | 
  
  
     | 
    
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 
     | 
  
  
     | 
    
        FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
     | 
  
  
     | 
    
        DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
     | 
  
  
     | 
    
        SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
     | 
  
  
     | 
    
        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
     | 
  
  
     | 
    
        OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
     | 
  
  
     | 
    
        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
     | 
  
  
     | 
    
       */
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       #include "hashmgr.h"
 
     | 
  
  
     | 
    
       #include "clutil.h"
 
     | 
  
  
     | 
    
       #include "fnpattern.h"
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       CHashManager::CHashManager()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	INTPREF i;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	// Load all algorithms
 
     | 
  
  
     | 
    
       	FillAlgorithmList(m_pAlgorithms);
 
     | 
  
  
     | 
    
       	RH_ASSERT(m_pAlgorithms[0] != NULL);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	for(i = 0; i < RH_MAX_ALGORITHMS; i++)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		m_bUseAlgorithm[i] = true;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		m_pHMACs[i] = NULL;
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	m_bRecursiveScanning = true;
 
     | 
  
  
     | 
    
       	m_bTimings = true;
 
     | 
  
  
     | 
    
       	m_bShortNames = true;
 
     | 
  
  
     | 
    
       	m_bHMAC = false;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	m_output.SetOutputStyleN(HASHOUTPUT_TEXT);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       CHashManager::~CHashManager()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	INTPREF i = 0;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	while(1)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		if(m_pAlgorithms[i] == NULL) break;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if(m_bHMAC == true)
 
     | 
  
  
     | 
    
       		{
 
     | 
  
  
     | 
    
       			if(m_pHMACs[i] != NULL) delete m_pHMACs[i];
 
     | 
  
  
     | 
    
       			m_pHMACs[i] = NULL;
 
     | 
  
  
     | 
    
       		}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		delete m_pAlgorithms[i];
 
     | 
  
  
     | 
    
       		m_pAlgorithms[i] = NULL;
 
     | 
  
  
     | 
    
       		i++;
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       INTPREF CHashManager::FindAlgorithm(const char *pszName, bool bShortName)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	INTPREF i = 0;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	if(bShortName)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		while(1)
 
     | 
  
  
     | 
    
       		{
 
     | 
  
  
     | 
    
       			if(m_pAlgorithms[i] == NULL) return -1;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			if(stricmp(pszName, m_pAlgorithms[i]->GetShortName()) == 0)
 
     | 
  
  
     | 
    
       				return i;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			i++;
 
     | 
  
  
     | 
    
       		}
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       	else
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		while(1)
 
     | 
  
  
     | 
    
       		{
 
     | 
  
  
     | 
    
       			if(m_pAlgorithms[i] == NULL) return -1;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			if(stricmp(pszName, m_pAlgorithms[i]->GetName()) == 0)
 
     | 
  
  
     | 
    
       				return i;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			i++;
 
     | 
  
  
     | 
    
       		}
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	RH_ASSERT(false); // We should never get here
 
     | 
  
  
     | 
    
       	return -1;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       bool CHashManager::SelectAlgorithm(INTPREF nAlgorithm, bool bSelect)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	if((nAlgorithm < 0) || (nAlgorithm >= RH_MAX_ALGORITHMS))
 
     | 
  
  
     | 
    
       		return false;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	if(m_pAlgorithms[nAlgorithm] == NULL) return false;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	m_bUseAlgorithm[nAlgorithm] = bSelect;
 
     | 
  
  
     | 
    
       	return true;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void CHashManager::SelectAllAlgorithms(bool bSelect)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	UINTPREF i = 0;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	while(1)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		if(m_pAlgorithms[i] == NULL) break;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		m_bUseAlgorithm[i] = bSelect;
 
     | 
  
  
     | 
    
       		i++;
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void CHashManager::SetOutputStyle(const char *pszOutputSchemeName)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	RH_ASSERT(pszOutputSchemeName != NULL);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	m_output.SetOutputStyleA(pszOutputSchemeName);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void CHashManager::SetHMAC(bool bHMAC, UWORD8 *pKey, UINTPREF uKeySize)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	UINTPREF i = 0;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	RH_ASSERT((bHMAC == true) || (bHMAC == false)); // Only accept real bool
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	if(bHMAC == false) return;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	if(m_bHMAC == false)
 
     | 
  
  
     | 
    
       		FillHMACList(m_pHMACs, m_pAlgorithms);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	while(1)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		if(m_pAlgorithms[i] == NULL) break;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		RH_ASSERT(m_pHMACs[i] != NULL);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		m_pHMACs[i]->SetKey(pKey, uKeySize);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		i++;
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	m_bHMAC = bHMAC;
 
     | 
  
  
     | 
    
       	rhstrcpy(m_szHMACKey, (const char *)pKey, RH_MAX_STD_BUFFER);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void CHashManager::SetOption(INTPREF nOption, bool bFlag)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	RH_ASSERT((nOption > HM_NULL) && (nOption < HM_LAST));
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	if(nOption == HM_RECURSIVE) m_bRecursiveScanning = bFlag;
 
     | 
  
  
     | 
    
       	if(nOption == HM_SHORTNAMES) m_bShortNames = bFlag;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void CHashManager::PrepareHashing()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	m_output.InitOutput(this);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void CHashManager::EndHashing()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	m_output.CloseOutput();
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       bool CHashManager::HashPath(const char *pszPath, const char *pszMask)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	RH_TRACE2("Hashing path: %s, mask: %s", pszPath, pszMask);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       #if (RH_TARGET_SYSTEM == RH_TARGET_SYSTEM_WINDOWS)
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	HANDLE hFind;
 
     | 
  
  
     | 
    
       	WIN32_FIND_DATA fd;
 
     | 
  
  
     | 
    
       	char szBasePath[RH_MAX_PATH];
 
     | 
  
  
     | 
    
       	char szFileDesc[RH_MAX_PATH];
 
     | 
  
  
     | 
    
       	bool bFileFound = true;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	// Construct the full path
 
     | 
  
  
     | 
    
       	rhfullpathex(pszPath, szBasePath);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	ZeroMemory(&fd, sizeof(WIN32_FIND_DATA));
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	rhstrcpy(szFileDesc, szBasePath, RH_MAX_PATH);
 
     | 
  
  
     | 
    
       	catdirsep(szFileDesc);
 
     | 
  
  
     | 
    
       	rhstrcat(szFileDesc, "*", RH_MAX_PATH);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	RH_TRACE1("FindFile: %s", szFileDesc);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	hFind = FindFirstFile(szFileDesc, &fd);
 
     | 
  
  
     | 
    
       	if(hFind == INVALID_HANDLE_VALUE) return true; // Nothing to do
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	bFileFound = true;
 
     | 
  
  
     | 
    
       	while(1)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		if(bFileFound == false) break;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		rhstrcpy(szFileDesc, fd.cFileName, RH_MAX_PATH);
 
     | 
  
  
     | 
    
       		fileonly(szFileDesc);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if(ispathnav(szFileDesc) == false)
 
     | 
  
  
     | 
    
       		{
 
     | 
  
  
     | 
    
       			if((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
 
     | 
  
  
     | 
    
       			{
 
     | 
  
  
     | 
    
       				if(fpattern_match(pszMask, szFileDesc) == true)
 
     | 
  
  
     | 
    
       				{
 
     | 
  
  
     | 
    
       					rhstrcpy(szFileDesc, szBasePath, RH_MAX_PATH);
 
     | 
  
  
     | 
    
       					catdirsep(szFileDesc);
 
     | 
  
  
     | 
    
       					rhstrcat(szFileDesc, fd.cFileName, RH_MAX_PATH);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       					HashFile(szFileDesc);
 
     | 
  
  
     | 
    
       				}
 
     | 
  
  
     | 
    
       			}
 
     | 
  
  
     | 
    
       			else // It's a directory
 
     | 
  
  
     | 
    
       			{
 
     | 
  
  
     | 
    
       				if(m_bRecursiveScanning == true)
 
     | 
  
  
     | 
    
       				{
 
     | 
  
  
     | 
    
       					rhstrcpy(szFileDesc, szBasePath, RH_MAX_PATH);
 
     | 
  
  
     | 
    
       					catdirsep(szFileDesc);
 
     | 
  
  
     | 
    
       					rhstrcat(szFileDesc, fd.cFileName, RH_MAX_PATH);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       					HashPath(szFileDesc, pszMask);
 
     | 
  
  
     | 
    
       				}
 
     | 
  
  
     | 
    
       			}
 
     | 
  
  
     | 
    
       		}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if(FindNextFile(hFind, &fd) == FALSE) bFileFound = false;
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	FindClose(hFind);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	return true;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	//////////////////////////////////////////////////////////////////////////
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       #else // RH_TARGET_SYSTEM != RH_TARGET_SYSTEM_WINDOWS
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	RH_TRACE1("New scan called with pszPath = %s", pszPath);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	if(chdir(pszPath) != 0) return RH_FIND_DENIED; // Permission denied?
 
     | 
  
  
     | 
    
       	DIR *pDir = opendir("."); // Find all files in that path
 
     | 
  
  
     | 
    
       	if(pDir == NULL) return true; // No access
 
     | 
  
  
     | 
    
       	struct dirent *pEntry;
 
     | 
  
  
     | 
    
       	struct stat fileStats;
 
     | 
  
  
     | 
    
       	char szPath[RH_MAX_PATH];
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	while((pEntry = readdir(pDir)))
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		if(lstat(pEntry->d_name, &fileStats) == 0)
 
     | 
  
  
     | 
    
       		{
 
     | 
  
  
     | 
    
       			rhfullpathex(pEntry->d_name, szPath);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			RH_TRACE2("Entry: %s, fullpath: %s", pEntry->d_name, szPath);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			if(ispathnav(pEntry->d_name) == false)
 
     | 
  
  
     | 
    
       			{
 
     | 
  
  
     | 
    
       				if(S_ISDIR(fileStats.st_mode))
 
     | 
  
  
     | 
    
       				{
 
     | 
  
  
     | 
    
       					if(m_bRecursiveScanning == true)
 
     | 
  
  
     | 
    
       					{
 
     | 
  
  
     | 
    
       						RH_TRACE1("New path hashing: %s", szPath);
 
     | 
  
  
     | 
    
       						catdirsep(szPath);
 
     | 
  
  
     | 
    
       						if(HashPath(szPath, pszMask) != RH_FIND_DENIED)
 
     | 
  
  
     | 
    
       							chdir("..");
 
     | 
  
  
     | 
    
       					}
 
     | 
  
  
     | 
    
       				}
 
     | 
  
  
     | 
    
       				else
 
     | 
  
  
     | 
    
       				{
 
     | 
  
  
     | 
    
       					if(fpattern_match(pszMask, pEntry->d_name) == true)
 
     | 
  
  
     | 
    
       						HashFile(szPath);
 
     | 
  
  
     | 
    
       				}
 
     | 
  
  
     | 
    
       			}
 
     | 
  
  
     | 
    
       			else
 
     | 
  
  
     | 
    
       			{
 
     | 
  
  
     | 
    
       				RH_TRACE0("Entry skipped");
 
     | 
  
  
     | 
    
       			}
 
     | 
  
  
     | 
    
       		}
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	closedir(pDir);
 
     | 
  
  
     | 
    
       	return true;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       #endif
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       INTPREF CHashManager::HashFile(const char *pszFile)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	FILE *fp;
 
     | 
  
  
     | 
    
       	UINTPREF uFileSize, uRead;
 
     | 
  
  
     | 
    
       	UWORD8 pBuf[HM_BUFFER_SIZE];
 
     | 
  
  
     | 
    
       	INTPREF nAlgorithm;
 
     | 
  
  
     | 
    
       	RH_DATA_INFO rhDataInfo;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	RH_ASSERT(HM_BUFFER_SIZE >= RH_MAX_PATH);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	RH_ASSERT(pszFile != NULL);
 
     | 
  
  
     | 
    
       	if(pszFile == NULL) return RH_NULLPOINTER;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	RH_TRACE1("Hashing file: %s", pszFile);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	fp = fopen(pszFile, "rb");
 
     | 
  
  
     | 
    
       	if(fp == NULL) return RH_FILE_NOT_FOUND;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	fseek(fp, 0, SEEK_END);
 
     | 
  
  
     | 
    
       	uFileSize = ftell(fp);
 
     | 
  
  
     | 
    
       	fseek(fp, 0, SEEK_SET);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	rhDataInfo.pszFileName = pszFile;
 
     | 
  
  
     | 
    
       	rhDataInfo.uDataLen = uFileSize;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	nAlgorithm = 0;
 
     | 
  
  
     | 
    
       	while(1)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		if(m_pAlgorithms[nAlgorithm] == NULL) break;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if(m_bUseAlgorithm[nAlgorithm] == true)
 
     | 
  
  
     | 
    
       		{
 
     | 
  
  
     | 
    
       			if(m_bHMAC == false)
 
     | 
  
  
     | 
    
       				m_pAlgorithms[nAlgorithm]->Init(&rhDataInfo);
 
     | 
  
  
     | 
    
       			else
 
     | 
  
  
     | 
    
       				m_pHMACs[nAlgorithm]->Init(&rhDataInfo);
 
     | 
  
  
     | 
    
       		}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		nAlgorithm++;
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	while(1)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		uRead = fread(pBuf, 1, HM_BUFFER_SIZE, fp);
 
     | 
  
  
     | 
    
       		if(uRead == 0) break;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		nAlgorithm = 0;
 
     | 
  
  
     | 
    
       		while(1)
 
     | 
  
  
     | 
    
       		{
 
     | 
  
  
     | 
    
       			if(m_pAlgorithms[nAlgorithm] == NULL) break;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			if(m_bUseAlgorithm[nAlgorithm] == true)
 
     | 
  
  
     | 
    
       			{
 
     | 
  
  
     | 
    
       				if(m_bHMAC == false)
 
     | 
  
  
     | 
    
       					m_pAlgorithms[nAlgorithm]->Update(pBuf, uRead);
 
     | 
  
  
     | 
    
       				else
 
     | 
  
  
     | 
    
       					m_pHMACs[nAlgorithm]->Update(pBuf, uRead);
 
     | 
  
  
     | 
    
       			}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			nAlgorithm++;
 
     | 
  
  
     | 
    
       		}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if(uRead < HM_BUFFER_SIZE) break;
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	fclose(fp);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	if(m_bShortNames == true)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		rhstrcpy((char *)pBuf, pszFile, HM_BUFFER_SIZE);
 
     | 
  
  
     | 
    
       		fileonly((char *)pBuf);
 
     | 
  
  
     | 
    
       		m_output.NewDataSource((char *)pBuf, m_bHMAC, m_szHMACKey);
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       	else
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		m_output.NewDataSource(pszFile, m_bHMAC, m_szHMACKey);
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	CHashAlgorithm *pAlgo;
 
     | 
  
  
     | 
    
       	CHMAC *pHMAC;
 
     | 
  
  
     | 
    
       	nAlgorithm = 0;
 
     | 
  
  
     | 
    
       	while(1)
 
     | 
  
  
     | 
    
       	{
 
     | 
  
  
     | 
    
       		if(m_pAlgorithms[nAlgorithm] == NULL) break;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if(m_bUseAlgorithm[nAlgorithm] == true)
 
     | 
  
  
     | 
    
       		{
 
     | 
  
  
     | 
    
       			pAlgo = m_pAlgorithms[nAlgorithm]; // Select algorithm
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			if(m_bHMAC == false)
 
     | 
  
  
     | 
    
       			{
 
     | 
  
  
     | 
    
       				pAlgo->Final();
 
     | 
  
  
     | 
    
       				pAlgo->GetHash(pBuf); // Reuse the file buffer
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       				m_output.Output(pAlgo->GetName(), pBuf, pAlgo->GetLength());
 
     | 
  
  
     | 
    
       			}
 
     | 
  
  
     | 
    
       			else
 
     | 
  
  
     | 
    
       			{
 
     | 
  
  
     | 
    
       				pHMAC = m_pHMACs[nAlgorithm]; // Select HMAC
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       				pHMAC->Final();
 
     | 
  
  
     | 
    
       				pHMAC->GetHash(pBuf); // Reuse the file buffer
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       				m_output.Output(pAlgo->GetName(), pBuf, pAlgo->GetLength());
 
     | 
  
  
     | 
    
       			}
 
     | 
  
  
     | 
    
       		}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		nAlgorithm++;
 
     | 
  
  
     | 
    
       	}
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	m_output.CloseDataSource();
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	return RH_SUCCESS;
 
     | 
  
  
     | 
    
       }
 
     |