<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using TextAdventures.Utility.JSInterop;
using WebInterfaces;

namespace WebPlayer
{
    public partial class Play : System.Web.UI.Page
    {
        private PlayerHandler m_player;
        private OutputBuffer m_buffer;
        private string m_gameId;

        protected void Page_Load(object sender, EventArgs e)
        {
            // We store the game in the Session, but use a dictionary keyed by GUIDs which
            // are stored in the ViewState. This allows the same user in the same browser
            // to open multiple games in different browser tabs.

            if (Games == null)
            {
                Games = new Dictionary<string, PlayerHandler>();
            }

            if (OutputBuffers == null)
            {
                OutputBuffers = new Dictionary<string, OutputBuffer>();
            }

            if (Resources == null)
            {
                Resources = new SessionResources();
            }

            m_gameId = (string)ViewState["GameId"];
            if (m_gameId == null)
            {
                m_gameId = Guid.NewGuid().ToString();
                ViewState["GameId"] = m_gameId;
            }

            if (Page.IsPostBack)
            {
                if (Games.ContainsKey(m_gameId))
                {
                    m_player = Games[m_gameId];
                }

                if (!OutputBuffers.ContainsKey(m_gameId))
                {
                    // TO DO: Think this only ever happens while debugging?
                    return;
                }
                m_buffer = OutputBuffers[m_gameId];
            }
            else
            {
                m_buffer = new OutputBuffer();
                OutputBuffers.Add(m_gameId, m_buffer);

                bool saveVisible = IsLoggedIn && (!string.IsNullOrEmpty(Request["id"]) || !string.IsNullOrEmpty(Request["load"]));
                m_buffer.AddJavaScriptToBuffer("showSaveButton", new BooleanParameter(saveVisible));
            }
        }

        protected void InitTimerTick(object sender, EventArgs e)
        {
            if (m_buffer == null) return;
            m_buffer.InitStage++;

            switch (m_buffer.InitStage)
            {
                case 1:
                    string initialText = LoadGameForRequest();
                    if (m_player == null)
                    {
                        tmrInit.Enabled = false;
                    }
                    else
                    {
                        RegisterExternalScripts();
                        RegisterExternalStylesheets();
                    }

                    OutputTextNow(initialText);
                    break;
                case 2:
                    tmrInit.Enabled = false;

                    m_player.BeginGame();
                    OutputTextNow(m_player.ClearBuffer());
                    break;
            }
        }

        private string LoadGameForRequest()
        {
            string folder = null;
            string gameFile = Request["file"];
            string id = Request["id"];
            string loadId = Request["load"];
            if (string.IsNullOrEmpty(gameFile))
            {
                if (!string.IsNullOrEmpty(id))
                {
                    IFileManager fileManager = FileManagerLoader.GetFileManager();
                    if (fileManager != null)
                    {
                        gameFile = fileManager.GetFileForID(id);
                    }
                }
                else if (!string.IsNullOrEmpty(loadId))
                {
                    IFileManager fileManager = FileManagerLoader.GetFileManager();
                    if (fileManager != null)
                    {
                        gameFile = fileManager.GetSaveFileForID(SessionManagerLoader.GetSessionManager().GetUser(), loadId, out id);
                        folder = ConfigurationManager.AppSettings["GameSaveFolder"];
                    }
                }
            }
            return LoadGame(gameFile, id, folder);
        }

        private string LoadGame(string gameFile, string id, string folder)
        {
            if (string.IsNullOrEmpty(gameFile))
            {
                return "No game specified";
            }

            string rootPath = folder ?? ConfigurationManager.AppSettings["GameFolder"];
            string libPath = ConfigurationManager.AppSettings["LibraryFolder"];
            var filename = GetGameFilename(gameFile, rootPath);
            if (filename == null)
            {
                return "Invalid filename";
            }
            List<string> errors;

            try
            {
                m_player = new PlayerHandler(filename, m_buffer, id, SessionManagerLoader.GetSessionManager().GetUser());
                m_player.GameId = m_gameId;
                m_player.LibraryFolder = libPath;
                Games[m_gameId] = m_player;
                m_player.BeginWait += m_player_BeginWait;
                m_player.BeginPause += m_player_BeginPause;
                m_player.ShowMenuDelegate = m_player_ShowMenu;
                m_player.ShowQuestionDelegate = m_player_ShowQuestion;
                m_player.AddResource += AddResource;
                m_player.PlayAudio += m_player_PlayAudio;
                m_player.StopAudio += m_player_StopAudio;
                
                if (m_player.Initialise(out errors))
                {
                    Resources.AddGame(m_player.Game);

                    // Successful game start
                    return m_player.ClearBuffer();
                }
            }
            catch (Exception ex)
            {
                return "<b>Error loading game:</b><br/>" + ex.Message;
            }

            string output = string.Empty;

            foreach (string error in errors)
            {
                output += error + "<br/>";
            }

            return output;
        }

        public static string GetGameFilename(string gameFile, string rootPath)
        {
            string filename;
            if (rootPath == null)
            {
                filename = gameFile;
            }
            else
            {
                filename = Path.Combine(rootPath, gameFile);

                var directory = new DirectoryInfo(Path.GetDirectoryName(filename));

                // Block attempts to access files outside the GameFolder
                if (!directory.FullName.StartsWith(rootPath))
                {
                    return null;
                }
            }<commit_msg>Fix bug with updated WebPath folder logic<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using TextAdventures.Utility.JSInterop;
using WebInterfaces;

namespace WebPlayer
{
    public partial class Play : System.Web.UI.Page
    {
        private PlayerHandler m_player;
        private OutputBuffer m_buffer;
        private string m_gameId;

        protected void Page_Load(object sender, EventArgs e)
        {
            // We store the game in the Session, but use a dictionary keyed by GUIDs which
            // are stored in the ViewState. This allows the same user in the same browser
            // to open multiple games in different browser tabs.

            if (Games == null)
            {
                Games = new Dictionary<string, PlayerHandler>();
            }

            if (OutputBuffers == null)
            {
                OutputBuffers = new Dictionary<string, OutputBuffer>();
            }

            if (Resources == null)
            {
                Resources = new SessionResources();
            }

            m_gameId = (string)ViewState["GameId"];
            if (m_gameId == null)
            {
                m_gameId = Guid.NewGuid().ToString();
                ViewState["GameId"] = m_gameId;
            }

            if (Page.IsPostBack)
            {
                if (Games.ContainsKey(m_gameId))
                {
                    m_player = Games[m_gameId];
                }

                if (!OutputBuffers.ContainsKey(m_gameId))
                {
                    // TO DO: Think this only ever happens while debugging?
                    return;
                }
                m_buffer = OutputBuffers[m_gameId];
            }
            else
            {
                m_buffer = new OutputBuffer();
                OutputBuffers.Add(m_gameId, m_buffer);

                bool saveVisible = IsLoggedIn && (!string.IsNullOrEmpty(Request["id"]) || !string.IsNullOrEmpty(Request["load"]));
                m_buffer.AddJavaScriptToBuffer("showSaveButton", new BooleanParameter(saveVisible));
            }
        }

        protected void InitTimerTick(object sender, EventArgs e)
        {
            if (m_buffer == null) return;
            m_buffer.InitStage++;

            switch (m_buffer.InitStage)
            {
                case 1:
                    string initialText = LoadGameForRequest();
                    if (m_player == null)
                    {
                        tmrInit.Enabled = false;
                    }
                    else
                    {
                        RegisterExternalScripts();
                        RegisterExternalStylesheets();
                    }

                    OutputTextNow(initialText);
                    break;
                case 2:
                    tmrInit.Enabled = false;

                    m_player.BeginGame();
                    OutputTextNow(m_player.ClearBuffer());
                    break;
            }
        }

        private string LoadGameForRequest()
        {
            string folder = null;
            string gameFile = Request["file"];
            string id = Request["id"];
            string loadId = Request["load"];
            if (string.IsNullOrEmpty(gameFile))
            {
                if (!string.IsNullOrEmpty(id))
                {
                    IFileManager fileManager = FileManagerLoader.GetFileManager();
                    if (fileManager != null)
                    {
                        gameFile = fileManager.GetFileForID(id);
                    }
                }
                else if (!string.IsNullOrEmpty(loadId))
                {
                    IFileManager fileManager = FileManagerLoader.GetFileManager();
                    if (fileManager != null)
                    {
                        gameFile = fileManager.GetSaveFileForID(SessionManagerLoader.GetSessionManager().GetUser(), loadId, out id);
                        folder = ConfigurationManager.AppSettings["GameSaveFolder"];
                    }
                }
            }
            return LoadGame(gameFile, id, folder);
        }

        private string LoadGame(string gameFile, string id, string folder)
        {
            if (string.IsNullOrEmpty(gameFile))
            {
                return "No game specified";
            }

            string rootPath = folder ?? ConfigurationManager.AppSettings["GameFolder"];
            string libPath = ConfigurationManager.AppSettings["LibraryFolder"];
            var filename = GetGameFilename(gameFile, rootPath);
            if (filename == null)
            {
                return "Invalid filename";
            }
            List<string> errors;

            try
            {
                m_player = new PlayerHandler(filename, m_buffer, id, SessionManagerLoader.GetSessionManager().GetUser());
                m_player.GameId = m_gameId;
                m_player.LibraryFolder = libPath;
                Games[m_gameId] = m_player;
                m_player.BeginWait += m_player_BeginWait;
                m_player.BeginPause += m_player_BeginPause;
                m_player.ShowMenuDelegate = m_player_ShowMenu;
                m_player.ShowQuestionDelegate = m_player_ShowQuestion;
                m_player.AddResource += AddResource;
                m_player.PlayAudio += m_player_PlayAudio;
                m_player.StopAudio += m_player_StopAudio;
                
                if (m_player.Initialise(out errors))
                {
                    Resources.AddGame(m_player.Game);

                    // Successful game start
                    return m_player.ClearBuffer();
                }
            }
            catch (Exception ex)
            {
                return "<b>Error loading game:</b><br/>" + ex.Message;
            }

            string output = string.Empty;

            foreach (string error in errors)
            {
                output += error + "<br/>";
            }

            return output;
        }

        public static string GetGameFilename(string gameFile, string rootPath)
        {
            string filename;
            if (rootPath == null)
            {
                filename = gameFile;
            }
            else
            {
                filename = Path.Combine(rootPath, gameFile);

                var directory = new DirectoryInfo(Path.GetDirectoryName(filename));

                var directoryName = directory.FullName;
                if (rootPath.EndsWith(@"\") && !directoryName.EndsWith(@"\"))
                {
                    directoryName += @"\";
                }

                // Block attempts to access files outside the GameFolder
                if (!directoryName.StartsWith(rootPath))
                {
                    return null;
                }
            }
{'fraction_non_alphanumeric': 0.08087542575548953, 'fraction_numerical': 0.000289876077976665, 'mean_word_length': 1.2719789265722752, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5733859', 'n_tokens_mistral': 3352, 'n_tokens_neox': 3141, 'n_words': 709}