From 5994743c73616afbb9219cfc9d3b8b81dc5ee843 Mon Sep 17 00:00:00 2001
From: Heavy Bob <ferrettclay@gmail.com>
Date: Thu, 10 Apr 2025 02:46:35 +1000
Subject: [PATCH] Added checks for streamlink response for web handler

I've also put in a check to make sure if we are going to accept a response from the api that it it's valid.
---
 AutoTrackR2/WebHandler.cs | 54 ++++++++++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/AutoTrackR2/WebHandler.cs b/AutoTrackR2/WebHandler.cs
index c18d440..b05a1a8 100644
--- a/AutoTrackR2/WebHandler.cs
+++ b/AutoTrackR2/WebHandler.cs
@@ -175,23 +175,47 @@ public static class WebHandler
             var responseContent = await response.Content.ReadAsStringAsync();
             Console.WriteLine($"Response: {responseContent}");
 
-            // Check if the response contains a streamer field
-            try
+            // Only process streamer data if streamlink is enabled
+            if (ConfigManager.StreamlinkEnabled == 1)
             {
-                var responseData = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(responseContent);
-                if (responseData != null && responseData.TryGetValue("streamer", out JsonElement streamerElement))
-                {
-                    string streamerHandle = streamerElement.GetString() ?? string.Empty;
-                    if (!string.IsNullOrEmpty(streamerHandle))
-                    {
-                        TrackREventDispatcher.OnStreamlinkRecordEvent(streamerHandle);
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                Console.WriteLine($"Error parsing streamer from response: {ex.Message}");
+                ProcessStreamerResponse(responseContent);
             }
         }
     }
+
+    private static void ProcessStreamerResponse(string responseContent)
+    {
+        try
+        {
+            var responseData = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(responseContent);
+            if (responseData != null && responseData.TryGetValue("streamer", out JsonElement streamerElement))
+            {
+                string streamerHandle = streamerElement.GetString() ?? string.Empty;
+                if (!string.IsNullOrEmpty(streamerHandle))
+                {
+                    // Sanitize the streamer handle before using it, this is to prevent any malicious instructions. 
+                    string sanitizedHandle = SanitizeStreamerHandle(streamerHandle);
+                    if (!string.IsNullOrEmpty(sanitizedHandle))
+                    {
+                        TrackREventDispatcher.OnStreamlinkRecordEvent(sanitizedHandle);
+                    }
+                }
+            }
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"Error parsing streamer from response: {ex.Message}");
+        }
+    }
+
+    private static string SanitizeStreamerHandle(string handle)
+    {
+        // Twitch usernames 4-25 characters, letters, numbers and underscores.
+        if (Regex.IsMatch(handle, @"^[a-zA-Z0-9_]{4,25}$"))
+        {
+            return handle.ToLower(); // Api won't return anything other than lowercase but just in case. 
+        }
+
+        return string.Empty; // Reject invalid handles
+    }
 }
\ No newline at end of file