// Fill out your copyright notice in the Description page of Project Settings. #include "Widget/SDTFluxRaceResultWidget.h" #include "DTFluxRaceResultModule.h" #include "HttpModule.h" #include "IWebBrowserCookieManager.h" #include "IWebBrowserWindow.h" #include "SlateOptMacros.h" #include "WebBrowserModule.h" #include "Interfaces/IHttpRequest.h" #include "Interfaces/IHttpResponse.h" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SDTFluxRaceResultWidget::Construct(const FArguments& InArgs) { FWebBrowserInitSettings browserInitSettings = FWebBrowserInitSettings(); IWebBrowserModule::Get().CustomInitialize(browserInitSettings); WindowSettings.InitialURL = TEXT("about:blank"); WindowSettings.BrowserFrameRate = 25; if (IWebBrowserModule::IsAvailable() && IWebBrowserModule::Get().IsWebModuleAvailable()) { IWebBrowserSingleton* WebBrowserSingleton = IWebBrowserModule::Get().GetSingleton(); Browser = WebBrowserSingleton->CreateBrowserWindow(WindowSettings); // Browser->OnLoadUrl().BindRaw(this, &SDTFluxRaceResultWidget::OnLoadOverride); } ChildSlot [ SNew(SBox) .Padding(5.0f) [ SNew(SBorder) .BorderImage(FCoreStyle::Get().GetBrush("ToolPanel.GroupBorder")) [ SNew(SVerticalBox) + SVerticalBox::Slot() [ SAssignNew(WebBrowser, SWebBrowser, Browser) .ShowControls(true) .SupportsTransparency(true) .OnUrlChanged(this, &SDTFluxRaceResultWidget::OnUrlChanged) .OnBeforeNavigation(this, &SDTFluxRaceResultWidget::OnBeforeNavigation) .OnLoadCompleted(FSimpleDelegate::CreateRaw(this, &SDTFluxRaceResultWidget::OnLoadCompleted)) .OnLoadError(FSimpleDelegate::CreateRaw(this, &SDTFluxRaceResultWidget::OnLoadError)) .OnLoadStarted(FSimpleDelegate::CreateRaw(this, &SDTFluxRaceResultWidget::OnLoadStarted)) .ShowErrorMessage(true) .ShowAddressBar(true) ] ] ] ]; } void SDTFluxRaceResultWidget::OnCookieSet(bool bSuccess) { } void SDTFluxRaceResultWidget::LoadContentViaHTTP() { UE_LOG(logDTFluxRaceResult, Log, TEXT("Loading initial content via HTTP: %s"), *RaceResultUrl); LoadSpecificURL(RaceResultUrl); } void SDTFluxRaceResultWidget::LoadSpecificURL(const FString& Url) { UE_LOG(logDTFluxRaceResult, Log, TEXT("Loading via HTTP: %s"), *Url); // Créer la requête HTTP TSharedRef Request = FHttpModule::Get().CreateRequest(); // Ajouter l'authentification Basic pour TOUTES les requêtes FString Credentials = Username + TEXT(":") + Password; FString EncodedCredentials = FBase64::Encode(Credentials); Request->SetURL(Url); Request->SetVerb("GET"); Request->SetHeader("Authorization", "Basic " + EncodedCredentials); Request->SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"); Request->SetHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); Request->SetHeader("Accept-Language", "en-US,en;q=0.5"); Request->SetHeader("Accept-Encoding", "gzip, deflate"); Request->SetHeader("Connection", "keep-alive"); Request->OnProcessRequestComplete().BindRaw(this, &SDTFluxRaceResultWidget::OnHTTPContentLoaded); Request->ProcessRequest(); UE_LOG(logDTFluxRaceResult, Log, TEXT("HTTP request sent with Basic Auth")); } void SDTFluxRaceResultWidget::OnHTTPContentLoaded(TSharedPtr Request, TSharedPtr HttpResponse, bool bWasSuccessful) { if (bWasSuccessful && HttpResponse.IsValid()) { int32 ResponseCode = HttpResponse->GetResponseCode(); UE_LOG(logDTFluxRaceResult, Log, TEXT("HTTP Response Code: %d"), ResponseCode); if (ResponseCode == 200) { FString Content = HttpResponse->GetContentAsString(); UE_LOG(logDTFluxRaceResult, Log, TEXT("Content loaded successfully, size: %d characters"), Content.Len()); // Traiter le contenu HTML FString ProcessedContent = ProcessHTMLContent(Content, Request->GetURL()); // Charger le contenu dans le browser via LoadString if (Browser.IsValid()) { Browser->LoadString(ProcessedContent, Request->GetURL()); UE_LOG(logDTFluxRaceResult, Log, TEXT("Content loaded into browser")); } } else if (ResponseCode == 401) { UE_LOG(logDTFluxRaceResult, Error, TEXT("Authentication failed - 401 Unauthorized. Check your credentials.")); } else if (ResponseCode == 403) { UE_LOG(logDTFluxRaceResult, Error, TEXT("Access forbidden - 403 Forbidden")); } else if (ResponseCode == 404) { UE_LOG(logDTFluxRaceResult, Error, TEXT("Page not found - 404 Not Found")); } else { UE_LOG(logDTFluxRaceResult, Error, TEXT("HTTP request failed with code: %d"), ResponseCode); } } else { UE_LOG(logDTFluxRaceResult, Error, TEXT("HTTP request failed completely")); } } void SDTFluxRaceResultWidget::OnLoadOverride() { } void SDTFluxRaceResultWidget::OnUrlChanged(const FText& NewUrl) { UE_LOG(logDTFluxRaceResult, Log, TEXT("URL changed to: %s"), *NewUrl.ToString()); } FString SDTFluxRaceResultWidget::ProcessHTMLContent(const FString& Content, const FString& BaseUrl) { FString ProcessedContent = Content; // Extraire le domaine de base FString BaseDomain = ExtractDomain(BaseUrl); UE_LOG(logDTFluxRaceResult, Log, TEXT("Processing HTML content, base domain: %s"), *BaseDomain); // Convertir tous les liens relatifs en liens absolus ProcessedContent = ProcessedContent.Replace(TEXT("src=\"/"), *FString::Printf(TEXT("src=\"%s/"), *BaseDomain)); ProcessedContent = ProcessedContent.Replace(TEXT("href=\"/"), *FString::Printf(TEXT("href=\"%s/"), *BaseDomain)); ProcessedContent = ProcessedContent.Replace(TEXT("src='/"), *FString::Printf(TEXT("src='%s/"), *BaseDomain)); ProcessedContent = ProcessedContent.Replace(TEXT("href='/"), *FString::Printf(TEXT("href='%s/"), *BaseDomain)); // Gérer les liens relatifs avec ./ ProcessedContent = ProcessedContent.Replace(TEXT("src=\"./"), *FString::Printf(TEXT("src=\"%s/"), *BaseDomain)); ProcessedContent = ProcessedContent.Replace(TEXT("href=\"./"), *FString::Printf(TEXT("href=\"%s/"), *BaseDomain)); // Ajouter une balise base pour aider avec les liens relatifs restants FString BaseTag = FString::Printf(TEXT(""), *BaseDomain); if (ProcessedContent.Contains(TEXT(""))) { FString HeadReplacement = TEXT("") + BaseTag; ProcessedContent = ProcessedContent.Replace(TEXT(""), *HeadReplacement); } else if (ProcessedContent.Contains(TEXT(""))) { FString HeadReplacement = TEXT("") + BaseTag; ProcessedContent = ProcessedContent.Replace(TEXT(""), *HeadReplacement); } UE_LOG(logDTFluxRaceResult, Log, TEXT("HTML content processed")); return ProcessedContent; } FString SDTFluxRaceResultWidget::ExtractDomain(const FString& Url) { FString Domain = Url; // Enlever le protocole if (Url.StartsWith(TEXT("https://"))) { Domain = Url.Mid(8); } else if (Url.StartsWith(TEXT("http://"))) { Domain = Url.Mid(7); } // Trouver le premier slash (début du path) int32 SlashIndex; if (Domain.FindChar(TEXT('/'), SlashIndex)) { Domain = Url.Left(Url.Len() - (Domain.Len() - SlashIndex)); } // Enlever le port si présent FString DomainPart = Domain; if (Domain.StartsWith(TEXT("https://"))) { DomainPart = Domain.Mid(8); } else if (Domain.StartsWith(TEXT("http://"))) { DomainPart = Domain.Mid(7); } int32 ColonIndex; if (DomainPart.FindChar(TEXT(':'), ColonIndex)) { Domain = Domain.Left(Domain.Len() - (DomainPart.Len() - ColonIndex)); } return Domain; } bool SDTFluxRaceResultWidget::OnBeforeNavigation(const FString& Url, const FWebNavigationRequest& Request) { UE_LOG(logDTFluxRaceResult, Log, TEXT("Loading via HTTP: %s"), *Url); TSharedRef HTTPRequest = FHttpModule::Get().CreateRequest(); // Authentification pour toutes les requêtes FString Credentials = Username + TEXT(":") + Password; FString EncodedCredentials = FBase64::Encode(Credentials); HTTPRequest->SetURL(RaceResultUrl); HTTPRequest->SetVerb("GET"); HTTPRequest->SetHeader("Authorization", "Basic " + EncodedCredentials); HTTPRequest->SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"); HTTPRequest->SetHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); HTTPRequest->OnProcessRequestComplete().BindRaw(this, &SDTFluxRaceResultWidget::OnHTTPContentLoaded); HTTPRequest->ProcessRequest(); return true; } void SDTFluxRaceResultWidget::OnLoadCompleted() { UE_LOG(logDTFluxRaceResult, Log, TEXT("Load Completed")); } void SDTFluxRaceResultWidget::OnLoadStarted() { UE_LOG(logDTFluxRaceResult, Log, TEXT("Load Started")); } void SDTFluxRaceResultWidget::OnLoadError() { UE_LOG(logDTFluxRaceResult, Log, TEXT("Load Error")); } void SDTFluxRaceResultWidget::OnBeforeResourceLoad(FString Url, FString ResourceType, FContextRequestHeaders& AdditionalHeaders, const bool AllowUserCredentials) { } void SDTFluxRaceResultWidget::SetupBasicAuth() { } END_SLATE_FUNCTION_BUILD_OPTIMIZATION