diff --git a/MusicToSoundpad.vcxproj b/MusicToSoundpad.vcxproj
index 7c38f32..52233de 100644
--- a/MusicToSoundpad.vcxproj
+++ b/MusicToSoundpad.vcxproj
@@ -20,6 +20,10 @@
+
+
+
+
17.0
diff --git a/MusicToSoundpad.vcxproj.filters b/MusicToSoundpad.vcxproj.filters
index 0b7f47e..672ec92 100644
--- a/MusicToSoundpad.vcxproj.filters
+++ b/MusicToSoundpad.vcxproj.filters
@@ -18,5 +18,13 @@
Source Files
+
+ Source Files
+
+
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index 1e402ae..6767adb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3,6 +3,7 @@
#include
#include
#include
+#include "md5.h"
#pragma comment(lib, "urlmon.lib")
@@ -30,7 +31,6 @@ BOOL DownloadFile(const wchar_t* url, const wchar_t* filePath) {
}
}
-// TODO: Compare the sums of the existing and latest binary to check for updates
BOOL CheckAndDownloadYTDLP(const wchar_t* utilsFolderPath) {
const wchar_t* ytDlpFileName = L"yt-dlp.exe";
const wchar_t* ytDlpUrl = L"https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe";
@@ -44,7 +44,12 @@ BOOL CheckAndDownloadYTDLP(const wchar_t* utilsFolderPath) {
wprintf(L"Downloading yt-dlp.exe...\n");
return DownloadFile(ytDlpUrl, ytDlpFilePath);
} else {
- wprintf(L"yt-dlp.exe already exists in the utils folder.\n");
+ wprintf(L"yt-dlp.exe already exists in the utils folder. Checking for updates...\n");
+ if (UpdateYTDLP() == 2)
+ {
+ wprintf(L"Updating yt-dlp.exe...\n");
+ return DownloadFile(ytDlpUrl, ytDlpFilePath);
+ }
return TRUE;
}
}
diff --git a/src/md5.c b/src/md5.c
new file mode 100644
index 0000000..bc89185
--- /dev/null
+++ b/src/md5.c
@@ -0,0 +1,147 @@
+#include
+#include
+#include
+#include
+#include
+
+#pragma comment(lib, "wininet.lib")
+#pragma comment(lib, "crypt32.lib")
+
+#define BUFSIZE 1024
+#define MD5_HASH_SIZE 16
+
+bool _DownloadFile(const char* url, const char* localFilePath) {
+ HINTERNET hInternet = InternetOpenA("MD5Check", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
+ if (hInternet == NULL) {
+ fprintf(stderr, "Error opening internet connection.\n");
+ return false;
+ }
+
+ HINTERNET hURL = InternetOpenUrlA(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD, 0);
+ if (hURL == NULL) {
+ fprintf(stderr, "Error opening URL: %s\n", url);
+ InternetCloseHandle(hInternet);
+ return false;
+ }
+
+ FILE* outputFile;
+ if (fopen_s(&outputFile, localFilePath, "wb") != 0 || outputFile == NULL) {
+ fprintf(stderr, "Error creating local file: %s\n", localFilePath);
+ InternetCloseHandle(hURL);
+ InternetCloseHandle(hInternet);
+ return false;
+ }
+
+ BYTE buffer[BUFSIZE];
+ DWORD bytesRead;
+ while (InternetReadFile(hURL, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
+ fwrite(buffer, 1, bytesRead, outputFile);
+ }
+
+ fclose(outputFile);
+ InternetCloseHandle(hURL);
+ InternetCloseHandle(hInternet);
+
+ return true;
+}
+
+bool CalculateMD5HashOfFile(const char* filename, BYTE* md5hash) {
+ HCRYPTPROV hProv = 0;
+ HCRYPTHASH hHash = 0;
+ HANDLE hFile = NULL;
+ BYTE rgbFile[BUFSIZE];
+ DWORD cbRead = 0;
+
+ if (!CryptAcquireContextA(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ return false;
+ }
+
+ if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
+ CryptReleaseContext(hProv, 0);
+ return false;
+ }
+
+ hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ CryptDestroyHash(hHash);
+ CryptReleaseContext(hProv, 0);
+ return false;
+ }
+
+ while (ReadFile(hFile, rgbFile, BUFSIZE, &cbRead, NULL) && cbRead > 0) {
+ if (!CryptHashData(hHash, rgbFile, cbRead, 0)) {
+ CloseHandle(hFile);
+ CryptDestroyHash(hHash);
+ CryptReleaseContext(hProv, 0);
+ return false;
+ }
+ }
+
+ DWORD cbHash = MD5_HASH_SIZE;
+ if (!CryptGetHashParam(hHash, HP_HASHVAL, md5hash, &cbHash, 0)) {
+ CloseHandle(hFile);
+ CryptDestroyHash(hHash);
+ CryptReleaseContext(hProv, 0);
+ return false;
+ }
+
+ CloseHandle(hFile);
+ CryptDestroyHash(hHash);
+ CryptReleaseContext(hProv, 0);
+ return true;
+}
+
+int UpdateYTDLP() {
+ char* localFile = "utils\\yt-dlp.exe";
+ char* remoteURL = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe";
+ BYTE localMD5[MD5_HASH_SIZE];
+ BYTE remoteMD5[MD5_HASH_SIZE];
+
+ char tempFilePath[MAX_PATH];
+ if (GetTempPathA(sizeof(tempFilePath), tempFilePath) == 0) {
+ fprintf(stderr, "Error getting temporary file path.\n");
+ return 1;
+ }
+
+ strcat_s(tempFilePath, sizeof(tempFilePath), "tempfile.dat");
+
+ if (!_DownloadFile(remoteURL, tempFilePath)) {
+ fprintf(stderr, "Error downloading remote file.\n");
+ return 1;
+ }
+
+ if (!CalculateMD5HashOfFile(localFile, localMD5)) {
+ fprintf(stderr, "Error calculating MD5 hash of local file.\n");
+ return 1;
+ }
+
+ if (!CalculateMD5HashOfFile(tempFilePath, remoteMD5)) {
+ fprintf(stderr, "Error calculating MD5 hash of remote file.\n");
+ return 1;
+ }
+
+ printf("Local MD5: ");
+ for (int i = 0; i < MD5_HASH_SIZE; i++) {
+ printf("%02x", localMD5[i]);
+ }
+ printf("\n");
+
+ printf("Remote MD5: ");
+ for (int i = 0; i < MD5_HASH_SIZE; i++) {
+ printf("%02x", remoteMD5[i]);
+ }
+ printf("\n");
+
+ if (memcmp(localMD5, remoteMD5, sizeof(localMD5)) == 0) {
+ printf("MD5 checksums match.\n");
+ } else {
+ printf("MD5 checksums do not match.\n");
+ return 2;
+ }
+
+ if (remove(tempFilePath) != 0) {
+ fprintf(stderr, "Error deleting temporary file.\n");
+ }
+
+ return 0;
+}
diff --git a/src/md5.h b/src/md5.h
new file mode 100644
index 0000000..931d3f8
--- /dev/null
+++ b/src/md5.h
@@ -0,0 +1,2 @@
+#pragma once
+int UpdateYTDLP();