mirror of
https://github.com/veracrypt/VeraCrypt
synced 2024-11-28 05:53:29 +01:00
Windows: Add HTML documentation to Windows installer.
This commit is contained in:
parent
b5abd54c1b
commit
6fe660c249
@ -59,6 +59,7 @@
|
|||||||
#include "Xts.h"
|
#include "Xts.h"
|
||||||
#include "Boot/Windows/BootCommon.h"
|
#include "Boot/Windows/BootCommon.h"
|
||||||
#include "Progress.h"
|
#include "Progress.h"
|
||||||
|
#include "zip.h"
|
||||||
|
|
||||||
#ifdef TCMOUNT
|
#ifdef TCMOUNT
|
||||||
#include "Mount/Mount.h"
|
#include "Mount/Mount.h"
|
||||||
@ -6967,6 +6968,17 @@ void CorrectFileName (wchar_t* fileName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CorrectFileName (std::wstring& fileName)
|
||||||
|
{
|
||||||
|
/* replace '/' by '\' */
|
||||||
|
size_t i, len = fileName.length();
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (fileName [i] == L'/')
|
||||||
|
fileName [i] = L'\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CorrectURL (wchar_t* fileName)
|
void CorrectURL (wchar_t* fileName)
|
||||||
{
|
{
|
||||||
/* replace '\' by '/' */
|
/* replace '\' by '/' */
|
||||||
@ -8578,6 +8590,63 @@ BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile)
|
|||||||
return TCCopyFileBase (src, dst);
|
return TCCopyFileBase (src, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL DecompressZipToDir (const unsigned char *inputBuffer, DWORD inputLength, const wchar_t *destinationDir, ProgressFn progressFnPtr, HWND hwndDlg)
|
||||||
|
{
|
||||||
|
BOOL res = TRUE;
|
||||||
|
zip_error_t zerr;
|
||||||
|
zip_int64_t numFiles, i;
|
||||||
|
zip_stat_t sb;
|
||||||
|
zip_source_t* zsrc = zip_source_buffer_create (inputBuffer, inputLength, 0, &zerr);
|
||||||
|
if (!zsrc)
|
||||||
|
return FALSE;
|
||||||
|
zip_t* z = zip_open_from_source (zsrc, ZIP_CHECKCONS | ZIP_RDONLY, &zerr);
|
||||||
|
if (!z)
|
||||||
|
{
|
||||||
|
zip_source_free (zsrc);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
finally_do_arg (zip_t*, z, { zip_close (finally_arg); });
|
||||||
|
|
||||||
|
numFiles = zip_get_num_entries (z, 0);
|
||||||
|
if (numFiles <= 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; (i < numFiles) && res; i++)
|
||||||
|
{
|
||||||
|
ZeroMemory (&sb, sizeof (sb));
|
||||||
|
if ((0 == zip_stat_index (z, i, 0, &sb)) && (sb.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) && (sb.size > 0))
|
||||||
|
{
|
||||||
|
std::wstring wname = Utf8StringToWide (sb.name);
|
||||||
|
CorrectFileName (wname);
|
||||||
|
|
||||||
|
std::wstring filePath = destinationDir + wname;
|
||||||
|
size_t pos = filePath.find_last_of (L"/\\");
|
||||||
|
// create the parent directory if it doesn't exist
|
||||||
|
if (pos != std::wstring::npos)
|
||||||
|
{
|
||||||
|
SHCreateDirectoryEx (NULL, filePath.substr (0, pos).c_str(), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_file_t *f = zip_fopen_index (z, i, 0);
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
ByteArray buffer((ByteArray::size_type) sb.size);
|
||||||
|
|
||||||
|
zip_fread (f, buffer.data(), sb.size);
|
||||||
|
zip_fclose (f);
|
||||||
|
|
||||||
|
if (progressFnPtr)
|
||||||
|
progressFnPtr (hwndDlg, filePath.c_str());
|
||||||
|
|
||||||
|
res = SaveBufferToFile ((char *) buffer.data(), filePath.c_str(), (DWORD) buffer.size(), FALSE, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file
|
// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file
|
||||||
// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE).
|
// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE).
|
||||||
BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed)
|
BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed)
|
||||||
|
@ -368,6 +368,8 @@ BOOL FileExists (const wchar_t *filePathPtr);
|
|||||||
__int64 FindStringInFile (const wchar_t *filePath, const char *str, int strLen);
|
__int64 FindStringInFile (const wchar_t *filePath, const char *str, int strLen);
|
||||||
BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile);
|
BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile);
|
||||||
BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed);
|
BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed);
|
||||||
|
typedef void (_cdecl *ProgressFn) ( HWND hwndDlg , const wchar_t *txt );
|
||||||
|
BOOL DecompressZipToDir (const unsigned char *inputBuffer, DWORD inputLength, const wchar_t *destinationFile, ProgressFn progressFnPtr, HWND hwndDlg);
|
||||||
BOOL TCFlushFile (FILE *f);
|
BOOL TCFlushFile (FILE *f);
|
||||||
BOOL PrintHardCopyTextUTF16 (wchar_t *text, wchar_t *title, size_t byteLen);
|
BOOL PrintHardCopyTextUTF16 (wchar_t *text, wchar_t *title, size_t byteLen);
|
||||||
void GetSpeedString (unsigned __int64 speed, wchar_t *str, size_t cbStr);
|
void GetSpeedString (unsigned __int64 speed, wchar_t *str, size_t cbStr);
|
||||||
@ -526,6 +528,8 @@ INT_PTR SecureDesktopDialogBoxParam (HINSTANCE, LPCWSTR, HWND, DLGPROC, LPARAM);
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
typedef std::vector<unsigned char> ByteArray;
|
||||||
|
|
||||||
struct HostDevice
|
struct HostDevice
|
||||||
{
|
{
|
||||||
HostDevice ()
|
HostDevice ()
|
||||||
@ -588,6 +592,7 @@ bool HexWideStringToArray (const wchar_t* hexStr, std::vector<byte>& arr);
|
|||||||
std::wstring FindDeviceByVolumeID (const BYTE volumeID [VOLUME_ID_SIZE]);
|
std::wstring FindDeviceByVolumeID (const BYTE volumeID [VOLUME_ID_SIZE]);
|
||||||
void RegisterDriverInf (bool registerFilter, const std::string& filter, const std::string& filterReg, HWND ParentWindow, HKEY regKey);
|
void RegisterDriverInf (bool registerFilter, const std::string& filter, const std::string& filterReg, HWND ParentWindow, HKEY regKey);
|
||||||
std::wstring GetTempPathString ();
|
std::wstring GetTempPathString ();
|
||||||
|
void CorrectFileName (std::wstring& fileName);
|
||||||
inline std::wstring AppendSrcPos (const wchar_t* msg, const char* srcPos)
|
inline std::wstring AppendSrcPos (const wchar_t* msg, const char* srcPos)
|
||||||
{
|
{
|
||||||
return std::wstring (msg? msg : L"") + L"\n\nSource: " + SingleStringToWide (srcPos);
|
return std::wstring (msg? msg : L"") + L"\n\nSource: " + SingleStringToWide (srcPos);
|
||||||
|
@ -557,7 +557,7 @@ void StatusMessage (HWND hwndDlg, char *stringId)
|
|||||||
SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0);
|
SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusMessageParam (HWND hwndDlg, char *stringId, wchar_t *param)
|
void StatusMessageParam (HWND hwndDlg, char *stringId, const wchar_t *param)
|
||||||
{
|
{
|
||||||
wchar_t szTmp[1024];
|
wchar_t szTmp[1024];
|
||||||
|
|
||||||
@ -576,23 +576,23 @@ void ClearLogWindow (HWND hwndDlg)
|
|||||||
SendMessage (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_RESETCONTENT, 0, 0);
|
SendMessage (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_RESETCONTENT, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegMessage (HWND hwndDlg, wchar_t *txt)
|
void RegMessage (HWND hwndDlg, const wchar_t *txt)
|
||||||
{
|
{
|
||||||
StatusMessageParam (hwndDlg, "ADDING_REG", txt);
|
StatusMessageParam (hwndDlg, "ADDING_REG", txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyMessage (HWND hwndDlg, wchar_t *txt)
|
void _cdecl CopyMessage (HWND hwndDlg, const wchar_t *txt)
|
||||||
{
|
{
|
||||||
StatusMessageParam (hwndDlg, "INSTALLING", txt);
|
StatusMessageParam (hwndDlg, "INSTALLING", txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveMessage (HWND hwndDlg, wchar_t *txt)
|
void RemoveMessage (HWND hwndDlg, const wchar_t *txt)
|
||||||
{
|
{
|
||||||
if (!Rollback)
|
if (!Rollback)
|
||||||
StatusMessageParam (hwndDlg, "REMOVING", txt);
|
StatusMessageParam (hwndDlg, "REMOVING", txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconMessage (HWND hwndDlg, wchar_t *txt)
|
void IconMessage (HWND hwndDlg, const wchar_t *txt)
|
||||||
{
|
{
|
||||||
StatusMessageParam (hwndDlg, "ADDING_ICON", txt);
|
StatusMessageParam (hwndDlg, "ADDING_ICON", txt);
|
||||||
}
|
}
|
||||||
@ -672,7 +672,7 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir)
|
|||||||
|
|
||||||
for (i = 0; i < sizeof (szFiles) / sizeof (szFiles[0]); i++)
|
for (i = 0; i < sizeof (szFiles) / sizeof (szFiles[0]); i++)
|
||||||
{
|
{
|
||||||
BOOL bResult, driver64 = FALSE;
|
BOOL bResult, driver64 = FALSE, zipFile = FALSE;
|
||||||
wchar_t szDir[TC_MAX_PATH];
|
wchar_t szDir[TC_MAX_PATH];
|
||||||
|
|
||||||
if (wcsstr (szFiles[i], L"VeraCrypt Setup") != 0)
|
if (wcsstr (szFiles[i], L"VeraCrypt Setup") != 0)
|
||||||
@ -696,7 +696,7 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*szFiles[i] == L'A')
|
if ((*szFiles[i] == L'A') || (*szFiles[i] == L'X'))
|
||||||
StringCbCopyW (szDir, sizeof(szDir), szDestDir);
|
StringCbCopyW (szDir, sizeof(szDir), szDestDir);
|
||||||
else if (*szFiles[i] == L'D')
|
else if (*szFiles[i] == L'D')
|
||||||
{
|
{
|
||||||
@ -717,7 +717,17 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir)
|
|||||||
if (*szFiles[i] == L'I')
|
if (*szFiles[i] == L'I')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (*szFiles[i] == L'X')
|
||||||
|
zipFile = TRUE;
|
||||||
|
|
||||||
StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szDir, szFiles[i] + 1);
|
StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szDir, szFiles[i] + 1);
|
||||||
|
if (zipFile)
|
||||||
|
{
|
||||||
|
// build folder name by removing .zip extension
|
||||||
|
wchar_t* ptr = wcsrchr (szTmp, L'.');
|
||||||
|
if (ptr)
|
||||||
|
*ptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (bUninstall == FALSE)
|
if (bUninstall == FALSE)
|
||||||
CopyMessage (hwndDlg, szTmp);
|
CopyMessage (hwndDlg, szTmp);
|
||||||
@ -805,13 +815,24 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir)
|
|||||||
bResult = FALSE;
|
bResult = FALSE;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
if (zipFile)
|
||||||
|
{
|
||||||
|
bResult = DecompressZipToDir (
|
||||||
|
Decompressed_Files[fileNo].fileContent,
|
||||||
|
Decompressed_Files[fileNo].fileLength,
|
||||||
|
szDir,
|
||||||
|
CopyMessage,
|
||||||
|
hwndDlg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bResult = SaveBufferToFile (
|
bResult = SaveBufferToFile (
|
||||||
(char *) Decompressed_Files[fileNo].fileContent,
|
(char *) Decompressed_Files[fileNo].fileContent,
|
||||||
szTmp,
|
szTmp,
|
||||||
Decompressed_Files[fileNo].fileLength,
|
Decompressed_Files[fileNo].fileLength,
|
||||||
FALSE,
|
FALSE,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
if (driver64)
|
if (driver64)
|
||||||
{
|
{
|
||||||
@ -907,6 +928,9 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir)
|
|||||||
{
|
{
|
||||||
if (driver64)
|
if (driver64)
|
||||||
EnableWow64FsRedirection (FALSE);
|
EnableWow64FsRedirection (FALSE);
|
||||||
|
if (zipFile)
|
||||||
|
bResult = StatRemoveDirectory (szTmp);
|
||||||
|
else
|
||||||
bResult = StatDeleteFile (szTmp, TRUE);
|
bResult = StatDeleteFile (szTmp, TRUE);
|
||||||
if (driver64)
|
if (driver64)
|
||||||
EnableWow64FsRedirection (TRUE);
|
EnableWow64FsRedirection (TRUE);
|
||||||
|
@ -74,7 +74,8 @@ static wchar_t *szFiles[]=
|
|||||||
L"ALanguage.vi.xml",
|
L"ALanguage.vi.xml",
|
||||||
L"ALanguage.zh-cn.xml",
|
L"ALanguage.zh-cn.xml",
|
||||||
L"ALanguage.zh-hk.xml",
|
L"ALanguage.zh-hk.xml",
|
||||||
L"ALanguage.zh-tw.xml"
|
L"ALanguage.zh-tw.xml",
|
||||||
|
L"Xdocs.zip",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specifies what files are included in self-extracting packages (no other files will be packaged or extracted).
|
// Specifies what files are included in self-extracting packages (no other files will be packaged or extracted).
|
||||||
@ -128,7 +129,8 @@ static wchar_t *szCompressedFiles[]=
|
|||||||
L"Language.vi.xml",
|
L"Language.vi.xml",
|
||||||
L"Language.zh-cn.xml",
|
L"Language.zh-cn.xml",
|
||||||
L"Language.zh-hk.xml",
|
L"Language.zh-hk.xml",
|
||||||
L"Language.zh-tw.xml"
|
L"Language.zh-tw.xml",
|
||||||
|
L"docs.zip"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FILENAME_64BIT_DRIVER L"veracrypt-x64.sys"
|
#define FILENAME_64BIT_DRIVER L"veracrypt-x64.sys"
|
||||||
@ -140,13 +142,13 @@ BOOL StatRemoveDirectory ( wchar_t *lpszDir );
|
|||||||
HRESULT CreateLink ( wchar_t *lpszPathObj , wchar_t *lpszArguments , wchar_t *lpszPathLink );
|
HRESULT CreateLink ( wchar_t *lpszPathObj , wchar_t *lpszArguments , wchar_t *lpszPathLink );
|
||||||
void GetProgramPath ( HWND hwndDlg , wchar_t *path );
|
void GetProgramPath ( HWND hwndDlg , wchar_t *path );
|
||||||
void StatusMessage (HWND hwndDlg, char *stringId);
|
void StatusMessage (HWND hwndDlg, char *stringId);
|
||||||
void StatusMessageParam (HWND hwndDlg, char *stringId, wchar_t *param);
|
void StatusMessageParam (HWND hwndDlg, char *stringId, const wchar_t *param);
|
||||||
void ClearLogWindow (HWND hwndDlg);
|
void ClearLogWindow (HWND hwndDlg);
|
||||||
void RegMessage ( HWND hwndDlg , wchar_t *txt );
|
void RegMessage ( HWND hwndDlg , const wchar_t *txt );
|
||||||
void RegRemoveMessage (HWND hwndDlg, wchar_t *txt);
|
void RegRemoveMessage (HWND hwndDlg, const wchar_t *txt);
|
||||||
void CopyMessage ( HWND hwndDlg , wchar_t *txt );
|
void _cdecl CopyMessage ( HWND hwndDlg , const wchar_t *txt );
|
||||||
void RemoveMessage ( HWND hwndDlg , wchar_t *txt );
|
void RemoveMessage ( HWND hwndDlg , const wchar_t *txt );
|
||||||
void IconMessage ( HWND hwndDlg , wchar_t *txt );
|
void IconMessage ( HWND hwndDlg , const wchar_t *txt );
|
||||||
static int CALLBACK BrowseCallbackProc ( HWND hwnd , UINT uMsg , LPARAM lp , LPARAM pData );
|
static int CALLBACK BrowseCallbackProc ( HWND hwnd , UINT uMsg , LPARAM lp , LPARAM pData );
|
||||||
void LoadLicense ( HWND hwndDlg );
|
void LoadLicense ( HWND hwndDlg );
|
||||||
void DetermineUpgradeDowngradeStatus (BOOL bCloseDriverHandle, LONG *driverVersionPtr);
|
void DetermineUpgradeDowngradeStatus (BOOL bCloseDriverHandle, LONG *driverVersionPtr);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
PATH=%PATH%;%WSDK81%\bin\x86
|
PATH=%PATH%;%WSDK81%\bin\x86;C:\Program Files\7-Zip;C:\Program Files (x86)\7-Zip
|
||||||
|
|
||||||
rem sign using SHA-1
|
rem sign using SHA-1
|
||||||
signtool sign /v /a /n IDRIX /i Thawte /ac thawte_Primary_MS_Cross_Cert.cer /fd sha1 /t http://timestamp.verisign.com/scripts/timestamp.dll "..\Release\Setup Files\veracrypt.sys" "..\Release\Setup Files\veracrypt-x64.sys"
|
signtool sign /v /a /n IDRIX /i Thawte /ac thawte_Primary_MS_Cross_Cert.cer /fd sha1 /t http://timestamp.verisign.com/scripts/timestamp.dll "..\Release\Setup Files\veracrypt.sys" "..\Release\Setup Files\veracrypt-x64.sys"
|
||||||
@ -11,11 +11,21 @@ signtool sign /v /a /n "IDRIX SARL" /i GlobalSign /ac GlobalSign_SHA256_EV_CodeS
|
|||||||
|
|
||||||
cd "..\Release\Setup Files\"
|
cd "..\Release\Setup Files\"
|
||||||
|
|
||||||
|
del *.xml
|
||||||
copy /V /Y ..\..\..\Translations\*.xml .
|
copy /V /Y ..\..\..\Translations\*.xml .
|
||||||
|
|
||||||
|
rmdir /S /Q docs
|
||||||
|
mkdir docs\html\en
|
||||||
|
copy /V /Y ..\..\..\doc\html\* docs\html\en\.
|
||||||
|
|
||||||
|
del docs.zip
|
||||||
|
7z a -y docs.zip docs
|
||||||
|
|
||||||
"VeraCrypt Setup.exe" /p
|
"VeraCrypt Setup.exe" /p
|
||||||
|
|
||||||
del *.xml
|
del *.xml
|
||||||
|
del docs.zip
|
||||||
|
rmdir /S /Q docs
|
||||||
|
|
||||||
cd "..\..\Signing"
|
cd "..\..\Signing"
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
PATH=%PATH%;%WSDK81%\bin\x86
|
PATH=%PATH%;%WSDK81%\bin\x86;C:\Program Files\7-Zip;C:\Program Files (x86)\7-Zip
|
||||||
|
|
||||||
set PFXNAME=TestCertificate\idrix_codeSign.pfx
|
set PFXNAME=TestCertificate\idrix_codeSign.pfx
|
||||||
set PFXPASSWORD=idrix
|
set PFXPASSWORD=idrix
|
||||||
@ -15,11 +15,21 @@ signtool sign /v /a /f %SHA256PFXNAME% /p %SHA256PFXPASSWORD% /ac %SHA256PFXCA%
|
|||||||
|
|
||||||
cd "..\Release\Setup Files\"
|
cd "..\Release\Setup Files\"
|
||||||
|
|
||||||
|
del *.xml
|
||||||
copy /V /Y ..\..\..\Translations\*.xml .
|
copy /V /Y ..\..\..\Translations\*.xml .
|
||||||
|
|
||||||
|
rmdir /S /Q docs
|
||||||
|
mkdir docs\html\en
|
||||||
|
copy /V /Y ..\..\..\doc\html\* docs\html\en\.
|
||||||
|
|
||||||
|
del docs.zip
|
||||||
|
7z a -y docs.zip docs
|
||||||
|
|
||||||
"VeraCrypt Setup.exe" /p
|
"VeraCrypt Setup.exe" /p
|
||||||
|
|
||||||
del *.xml
|
del *.xml
|
||||||
|
del docs.zip
|
||||||
|
rmdir /S /Q docs
|
||||||
|
|
||||||
cd "..\..\Signing"
|
cd "..\..\Signing"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user