public static bool SendThumbnailsAsZipFile(FileBrowseRequest request, ThumbnailSizes thumbSize, ref BrowserSender bSender)
        {
            // We'll need a shell helper
            FatAttitude.ShellHelper sh = new FatAttitude.ShellHelper();

            // Set up temp directory
            string tempFolderName = Path.GetRandomFileName();
            string tempPath = Path.Combine (Functions.ZipTempFolder, tempFolderName);
            Directory.CreateDirectory(tempPath);

            // Go through the thumbnails (filter already applied, so these are pic files)
            FileBrowseResult fbResult = FileBrowseExporter.BrowsePath(request.FullPath, request.Filters);
            // Any files?
            if (fbResult.Files.Count < 1) return false;

            int SkipCounter = 0;
            int OutputCounter = 0;
            List<string> outputFiles = new List<string>();
            foreach (BrowseItem bItem in fbResult.Files)
            {
                // Skip items before batch
                if (request.ThumbnailsLimitToBatch)
                    if (request.ThumbnailsBatch > 0)
                        if (SkipCounter++ < (request.ThumbnailsBatchSize * request.ThumbnailsBatch))
                            continue;

                string strFullPath = Path.Combine(fbResult.BaseDirectory, bItem.Name);
                string strLog = ""; // ignore log
                Bitmap bmp = sh.ThumbnailForFile(strFullPath, thumbSize, ref strLog);

                string fnSansExtension = Path.GetFileNameWithoutExtension(bItem.Name);
                string strOutputFileFullPath = Path.Combine(tempPath,  (fnSansExtension + "_thumb.jpg" ) );
                bmp.Save(strOutputFileFullPath, ImageFormat.Jpeg);

                outputFiles.Add(strOutputFileFullPath);

                // End of batch?
                if (request.ThumbnailsLimitToBatch)
                    if (OutputCounter++ >= request.ThumbnailsBatchSize)
                        break;
            }

            // Now zip up the files
            string strOutputZipFile = Path.Combine(Functions.ZipTempFolder, (  Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".zip") );
            bool result = ZipHelper.CreateZipFileFromFiles(outputFiles, strOutputZipFile);

            // And send the zip file to the browser
            result &= (bSender.SendFileToBrowser(strOutputZipFile));
            File.Delete(strOutputZipFile);
            Directory.Delete(tempPath, true);

            return result;
        }
Exemple #2
0
        public static bool SendFolderFilesAsZipFile(FileBrowseResult fbResult, ref BrowserSender bSender)
        {
            // We'll need a shell helper
            CreateShellHelperIfNull();

            // Set up temp directory
            string tempFolderName = Path.GetRandomFileName();
            string tempPath       = Path.Combine(Functions.ZipTempFolder, tempFolderName);

            Directory.CreateDirectory(tempPath);

            // Any files?
            if (fbResult.Files.Count < 1)
            {
                return(false);
            }

            List <string> outputFiles = new List <string>();

            foreach (BrowseItem bItem in fbResult.Files)
            {
                string strFullPath = Path.Combine(fbResult.BaseDirectory, bItem.Name);
                outputFiles.Add(strFullPath);
            }

            // Now zip up the files
            string strOutputZipFile = Path.Combine(Functions.ZipTempFolder, (Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".zip"));
            bool   result           = ZipHelper.CreateZipFileFromFiles(outputFiles, strOutputZipFile);

            // And send the zip file to the browser
            result &= (bSender.SendFileToBrowser(strOutputZipFile, false, false, true));
            File.Delete(strOutputZipFile);
            Directory.Delete(tempPath, true);

            return(result);
        }
        private bool SendRemoteControlCommand(ref BrowserSender bs)
        {
            if (Themes.UsingMobileTheme)
            {
                return SendRemoteControlCommandMobile(ref bs);
            }
            else
            {
                SendRemoteControlCommandDesktop(ref bs);
                return true;

            }
        }
        private void SendFileThumbnail(string fileName, FatAttitude.ThumbnailSizes thumbSize, ref BrowserSender browserSender)
        {
            // Find file or folder?
            if (
                (! File.Exists(fileName)) && (! Directory.Exists(fileName))
                )
            {
                bool foo = browserSender.Send404Page();
                return;
            }

            FatAttitude.ShellHelper sh = new FatAttitude.ShellHelper();
            string strLog = ""; // ignore
            Bitmap thumb = sh.ThumbnailForFile(fileName, thumbSize, ref strLog);
            if (thumb == null)
            {
                browserSender.SendFileToBrowser("thumbnail_default.png", true, false);
                return;
            }

            byte[] outputdata =  ImageResizer.ImageToByteArray(thumb, ImageFormat.Jpeg);

            // Send to browser
            bool foo2 = browserSender.SendDataToBrowser("image/jpeg", outputdata);
        }
        public void Run()
        {
            #if !DEBUG
            try
            {
            #endif
            // To store headers and styles
            List<string> AdditionalStyles = new List<string>();

            // Set HTTP response version to 1.1 (experimental)
            //  Context.Response.ProtocolVersion = new Version("1.1");

            BrowserSender browserSender = new BrowserSender(Context);
            currentClientIP = Request.RemoteEndPoint.Address.ToString();
            qsParams = Request.QueryString;

            if (Settings.Default.DebugServer) spoolMessage("Client Connected (" + Request.RemoteEndPoint.Address.ToString() + ")");

            if ((Settings.Default.DebugAdvanced) && (Settings.Default.DebugServer))
            {
                spoolMessage("Headers from client:");
                for (int i = 0; i < Request.Headers.Count; ++i)
                    spoolMessage(string.Format("{0}: {1}", Request.Headers.Keys[i], Request.Headers[i]));
            }

            // Split request into lines
            string txtPostObjects = "";
            if (Request.HttpMethod.Equals("POST"))
            {
                StreamReader sr = new StreamReader(Request.InputStream);
                txtPostObjects = sr.ReadToEnd();
            }

            // User agent - detect mobile
            processUserAgentStringFromRequestHeaders();

            // Get action string from Url
            string txtAction = GetActionFromBrowserRequest();

            if (Settings.Default.DebugServer)
            {
                Functions.WriteLineToLogFile("From Client: " + txtAction);
            }

            // Build response
            txtResponse = "";
            txtPageTitle = Settings.Default.MainMenuTitle;
            bool foo;

            // R.I.P. Open server  (keep this for legacy compatibility)
            if (txtAction.StartsWith("open"))
                txtAction = txtAction.Substring(5);

            // Special cases / conversions
            if (txtAction.ToLowerInvariant().Equals("apple-touch-icon.png"))
                txtAction = "static/images/apple-touch-icon.png";

            // Querystring authentication is one possible method that overrides all others if true: check for token (and renew)
            if (txtAction.StartsWith("xml/checktoken")) // Special open method - check a token
            {
                bool ignore = CheckForTokenAuthentication();
                string checkForTokenResult = AuthenticatedByToken ? "GOOD" : "BAD";
                string xCheckResponse = "<?xml version=\"1.0\"?><checktokenresponse result=\"" + checkForTokenResult +  "\" />";
                browserSender.SendXMLToBrowser(xCheckResponse);
                return;
            }
            else if (!CheckForTokenAuthentication())
            {
                // invalid token
                browserSender.SendGenericStatusCodePage("403", "Incorrect authentication");
                spoolMessage("API: failed authentication via token.");
                return;
            }

            // XML METHODS - no HTTP authentication required (uses token-based auth)
            if (txtAction.StartsWith("xml"))
            {
                XMLresponse = "";
                WebServiceProcess(txtAction, ref browserSender, ref txtPostObjects);
                return;
            }

            // Any other non-authenticated methods
            switch (txtAction)
            {
                // SPECIAL FILE NAME SHORTCUTS - NO AUTH REQUIRED **************
                case "robots.txt":
                    if (!browserSender.SendFileToBrowser("static\\robots.txt"))
                        Functions.WriteLineToLogFile("Could not send robots.txt to browser");
                    return;
                case "clientaccesspolicy.xml":
                    if (!browserSender.SendFileToBrowser("static\\clientaccesspolicy.xml"))
                        Functions.WriteLineToLogFile("Could not send clientaccesspolicy.xml to browser (presumably to Silverlight)");
                    return;
                case "silverlightsource":
                    if (!browserSender.SendFileToBrowser("static\\silverlight\\SilverPotato.xap"))
                        Functions.WriteLineToLogFile("Could not send SilverPotato XAP to browser");
                    return;

                //Ping is allowed
                case "ping":
                    Version v = Functions.ServerVersion;
                    string xResponse = "<?xml version=\"1.0\"?><pingresponse result=\"PING_RESULT\" serverversion=\"SERVER_VERSION\" serverrevision=\"SERVER_REVISION\" serverosversionstring=\"SERVER_OS_VERSION_STRING\" serverosversion=\"SERVER_OS_VERSION\" servercapabilities=\"CAP_FLAGS\" />";
                    xResponse = xResponse.Replace("PING_RESULT", Settings.Default.RequirePassword ? "NEED_PASSWORD" : "OK");
                    xResponse = xResponse.Replace("SERVER_VERSION", v.Major.ToString() + "." +
                    v.Minor.ToString() );  // This is culture invariant
                    xResponse = xResponse.Replace("SERVER_OS_VERSION_STRING", Environment.OSVersion.VersionString);
                    xResponse = xResponse.Replace("SERVER_OS_VERSION", Environment.OSVersion.Version.ToString(2) );
                    xResponse = xResponse.Replace("SERVER_REVISION", v.Build.ToString());
                    xResponse = xResponse.Replace("CAP_FLAGS", Functions.ServerCapabilities);
                    browserSender.SendXMLToBrowser(xResponse);
                    return;

                // Fav Icon is allowed
                case "favicon.ico":
                    browserSender.SendFileToBrowser(HttpUtility.UrlDecode("static\\images\\remotepotatoicon.ico"));
                    return;

                default:
                    break;
            }

            // Channel logos are allowed
            if ((txtAction.StartsWith("logo")))
            {
                int hashlocation = txtAction.LastIndexOf("/");
                if (hashlocation < 1)
                {
                    bool fooa = browserSender.Send404Page();
                }
                else
                {
                    txtAction = txtAction.Replace("logo/", "");
                    string logoSvcID = HttpUtility.UrlDecode(txtAction);

                    // Send logo to browser
                    browserSender.SendLogoToBrowser(logoSvcID);
                }
                return;
            }

            // Special case 'static' files that aren't => legacy support for streaming
            if (txtAction.StartsWith("httplivestream"))
            {
                ProcessHTTPLSURL(txtAction, ref browserSender);
                return;
            }

            // Static Files
            if ( (txtAction.StartsWith("static")) )
            {
                int hashlocation = txtAction.LastIndexOf("/");
                if (hashlocation < 1)
                {
                    bool fooa = browserSender.Send404Page();
                }
                else
                {
                    // Send file
                    browserSender.SendFileToBrowser(HttpUtility.UrlDecode(txtAction));
                }
                return;
            }

            // Skin files
            if ( (txtAction.StartsWith("skin")))
            {
                int hashlocation = txtAction.LastIndexOf("/");
                if (hashlocation < 1)
                {
                    bool fooa = browserSender.Send404Page();
                }
                else
                {
                    // Send file
                    browserSender.SendFileToBrowser(HttpUtility.UrlDecode(txtAction), true, false);
                }
                return;
            }

            // Thumbnails are allowed
            if (txtAction == "rectvthumbnail64")
            {
                GetRecTVThumbnail(ref browserSender, true);
                return;
            }
            else if (txtAction == "rectvthumbnail")
            {
                GetRecTVThumbnail(ref browserSender, false);
                return;
            }

            if (txtAction.StartsWith("getfilethumbnail64"))
            {
                GetFileThumbnailUsingQueryString(ref browserSender, true);
                return;
            }
            else if (txtAction.StartsWith("getfilethumbnail"))
            {
                GetFileThumbnailUsingQueryString(ref browserSender, false);
                return;
            }

            if (txtAction.StartsWith("filethumbnail"))
            {
                string txtSize = txtAction.Replace("filethumbnail/","");
                FatAttitude.ThumbnailSizes size = (FatAttitude.ThumbnailSizes) Enum.Parse( (new FatAttitude.ThumbnailSizes().GetType() ), txtSize, true);

                SendFileThumbnail(txtPostObjects, size, ref browserSender);
                return;
            }
            if (txtAction.StartsWith("musicalbumthumbnail"))
            {
                GetAlbumThumbnail(ref browserSender, txtAction.Contains("musicalbumthumbnail64") );
                return;
            }
            if (txtAction.StartsWith("musicsongthumbnail"))
            {
                GetSongThumbnail(ref browserSender, txtAction.Contains("musicsongthumbnail64"));
                return;
            }

            // Silverlight is allowed (no longer contains password info)
            bool showSilverlight = (txtAction.StartsWith("silverlight"));
            if (Settings.Default.SilverlightIsDefault)
                showSilverlight = showSilverlight | (txtAction.Trim().Equals(""));

            if (showSilverlight)
            {
                string silverTemplate = FileCache.ReadTextFile("static\\silverlight\\default_template.htm");
                browserSender.SendNormalHTMLPageToBrowser(silverTemplate);
                return;
            }

            // MORE OPEN METHODS...
            if (txtAction.StartsWith("streamsong"))
            {

                bool isBase64Encoded = (txtAction.StartsWith("streamsong64"));

                if (!SendSongToBrowser(ref browserSender, isBase64Encoded,  true, false))
                    browserSender.Send404Page();
                return;
            }

            // MORE OPEN METHODS...
            if (txtAction.StartsWith("downloadsong"))
            {

                bool isBase64Encoded = (txtAction.StartsWith("downloadsong64"));

                if (!SendSongToBrowser(ref browserSender, isBase64Encoded, true, true))
                    browserSender.Send404Page();
                return;
            }

            // ********************************************************************************************
            // Cookie Authentication Required for all Methods below here **********************************
            // ********************************************************************************************

            bool processMoreActions = false;
            if (canProceedAuthenticatedByHTTPCookie())
            {
                processMoreActions = true;
            }
            else
            {
                spoolMessage("Webserver: requesting login.");

                bool LoginSuccess = false;
                string destURL = "";
                string destQueryString = "";
                ViewLoginPage(txtPostObjects, ref LoginSuccess, ref destURL, ref destQueryString);

                // Successful login
                if (LoginSuccess)
                {
                    processMoreActions = true;
                    txtPageTitle = "";
                    // Assign new (old) action and querystring for further processing
                    txtAction = destURL;
                    qsParams = HttpUtility.ParseQueryString(destQueryString);

                    // We've missed the silverlight check (it's up above), so check again
                    if (Settings.Default.SilverlightIsDefault)
                    {
                        string silverTemplate = FileCache.ReadTextFile("static\\silverlight\\default_template.htm");
                        browserSender.SendNormalHTMLPageToBrowser(silverTemplate);
                        return;
                    }

                }

            }

            bool sentWholePage = false;
            if (processMoreActions)
            {
                switch (txtAction)
                {
                    // Legacy Streamsong  (secured)
                    case "streamsong.mp3":
                        if (!SendSongToBrowser(ref browserSender, false, true, false))
                            browserSender.Send404Page();
                        return;
                    case "streamsong":
                        if (!SendSongToBrowser(ref browserSender, false, true, false))
                            browserSender.Send404Page();
                        return;

                    // MANUAL RECORDING ======================================================
                    case "recordmanual":
                        foo = TryManualRecording();
                        break;

                        // Remote Control
                    case "remotecontrol":
                        foo = ViewRemoteControl();
                        break;

                    // Remote Control
                    case "rc":
                        bool haveSentHTMLPage = SendRemoteControlCommand(ref browserSender);
                        if (haveSentHTMLPage) return;  // Don't continue; this method sends a blank page
                        break;

                    // RECORD A SERIES
                    case "recordshow_series":
                        foo = RecordSeries();
                        break;

                    // RECORD (FROM RecordingRequest): MULTIPURPOSE
                    case "recordfromqueue":
                        foo = RecordFromQueue();
                        break;

                        // PICS
                    case "browsepics":
                        ViewPicturesLibrary();
                        break;

                    case "viewpic":
                        foo = ViewPicture(ref browserSender, ref sentWholePage);
                        if (sentWholePage) return; // no more processing required
                        break;

                    case "picfolderaszip":
                        foo = GetPicturesFolderAsZip(ref browserSender);
                        return; // Don't continue, no Reponse left to output

                    // VIDEOS
                    case "browsevideos":
                        ViewVideoLibrary();
                        break;

                    case "streamvideo":
                        foo = StreamVideo();
                        break;

                    // MUSIC
                    case "musicroot":
                        ViewMusic();
                        break;

                    case "musicartists":
                        ViewMusicArtists(false);
                        break;

                    case "musicartist":
                        ViewMusicArtist();
                        break;

                    case "musicalbumartists":
                        ViewMusicArtists(true);
                        break;

                    case "musicalbums":
                        ViewMusicAlbums();
                        break;

                    case "musicalbum":
                        ViewMusicAlbum();
                        break;

                    case "musicgenres":
                        ViewMusicGenres();
                        break;

                    case "musicgenre":
                        ViewMusicGenre();
                        break;

                    case "musicsong":
                        ViewMusicSong();
                        break;

                    // LIST RECORDINGS
                    case "scheduledrecordings":
                        foo = ViewScheduledRecordings();
                        break;

                    case "log-out":
                        DoLogOut();
                        break;

                    // LIST RECORDINGS
                    case "recordedtv":
                        foo = ViewRecordedTVList();
                        AdditionalStyles.Add("rectv");
                        break;

                    // VIEW A SPECIFIC SERIES
                    case "viewseriesrequest":
                        foo = ViewSeriesRequest();
                        AdditionalStyles.Add("showdetails");
                        break;

                    // MANAGE ALL SERIES
                    case "viewseriesrequests":
                        foo = ViewSeriesRequests();
                        break;

                    // VIEW AN EPG PAGE
                    case "viewepglist":
                        foo = ViewEPGList();
                        AdditionalStyles.Add("epg-list");
                        break;

                    // VIEW AN EPG PAGE - GRID
                    case "viewepggrid":
                        Functions.WriteLineToLogFile("RP: (VEPG)");
                        foo = ViewEPGGrid();
                        AdditionalStyles.Add("epg-grid");
                        break;

                    // Shift EPG Grid Up
                    case "epgnavup":
                        foo = EPGGridChannelRetreat();
                        AdditionalStyles.Add("epg-grid");
                        break;

                    // Shift EPG Grid Down
                    case "epgnavdown":
                        foo = EPGGridChannelAdvance();
                        AdditionalStyles.Add("epg-grid");
                        break;

                    // Shift EPG Grid Right
                    case "epgnavright":
                        foo = EPGGridTimeWindowShiftByMinutes(EPGManager.TimespanMinutes);
                        AdditionalStyles.Add("epg-grid");
                        break;

                    // Shift EPG Grid Left
                    case "epgnavleft":
                        foo = EPGGridTimeWindowShiftByMinutes(0 - EPGManager.TimespanMinutes);
                        AdditionalStyles.Add("epg-grid");
                        break;

                    // Shift EPG Grid Left
                    case "epgnavtop":
                        foo = EPGGridChannelSetAbsolute(true, false);
                        AdditionalStyles.Add("epg-grid");
                        break;

                    // Shift EPG Grid Left
                    case "epgnavbottom":
                        foo = EPGGridChannelSetAbsolute(false, true);
                        AdditionalStyles.Add("epg-grid");
                        break;

                    // Shift EPG To Page
                    case "epgjumptopage":
                        foo = EPGGridChannelJump();
                        AdditionalStyles.Add("epg-grid");
                        break;

                    // VIEW AN EPG SHOW
                    case "viewepgprogramme":
                        foo = ViewEPGProgramme();
                        AdditionalStyles.Add("showdetails");
                        break;

                    // STREAM A SHOW
                    case "streamprogramme":
                        foo = StreamRecordedProgramme();
                        AdditionalStyles.Add("showdetails");
                        break;

                    // SEARCH BY TITLE
                    case "searchbytitle":
                        foo = SearchShowsByText();
                        break;

                    // DELETE A RECORDING
                    case "deletefile":
                        foo = DeleteFileFromFilePath(false);
                        break;

                    case "deletefile64":
                        foo = DeleteFileFromFilePath(true);
                        break;

                    // CANCEL A RECORDING
                    case "cancelseriesrequest":
                        foo = CancelRequest();
                        break;

                    // CANCEL A RECORDING
                    case "cancelrecording":
                        foo = CancelRecording();
                        break;

                    // VIEW MOVIES
                    case "movies":
                        foo = ViewMovies();
                        AdditionalStyles.Add("movies");
                        break;

                    // VIEW MOVIES
                    case "viewmovie":
                        foo = ViewMovie();
                        AdditionalStyles.Add("showdetails");
                        AdditionalStyles.Add("movies");
                        break;

                    case "info":
                        txtResponse += "This is the Remote Potato Server v" + Functions.VersionText + " running on " + Environment.OSVersion.VersionString + ".";
                        txtResponse += "<br/><br/>For help and support please visit the <a href='http://forums.fatattitude.com'>FatAttitude Forums</a>.";
                        break;

                    case "mainmenu":
                        ShowMainMenu();
                        break;

                    default:
                        ShowMainMenu();
                        break;

                }
            }

            // Finalise response: convert to master page
            string txtOutputPage = FileCache.ReadSkinTextFile("masterpage.htm");

            // Commit response
            txtOutputPage = txtOutputPage.Replace("**PAGECONTENT**", txtResponse);
            txtResponse = "";

            // Style inclusion?  (this line must be before the Skin section, as the returned string includes **SKINFOLDER** to be replaced
            txtOutputPage = txtOutputPage.Replace("**PAGEADDITIONALSTYLES**", AdditionalStyleLinks(AdditionalStyles));
            // Orientation
            txtOutputPage = txtOutputPage.Replace("**PAGEORIENTATION**", txtOutputPage.Contains("PAGEORIENTATION=LANDSCAPE") ? "landscape" : "portrait");

            // Skin
            txtOutputPage = txtOutputPage.Replace("**SKINFOLDER**", "/static/skins/" + Themes.ActiveThemeName);
            txtOutputPage = txtOutputPage.Replace("**HEADER**", "Remote Potato");
            // Default Page Title
            txtOutputPage = txtOutputPage.Replace("**PAGETITLE**", txtPageTitle);

            // Copyright / Timestamp
            txtOutputPage = txtOutputPage.Replace("**TIMEANDVERSIONSTRING**", DateTime.Now.ToLongTimeString() + ", v" + Functions.VersionText);

            if (!browserSender.SendNormalHTMLPageToBrowser(txtOutputPage))
            {
                spoolMessage("Webserver failed to send data.");
            }

            #if !DEBUG
            }

            catch (Exception e)
            {
                Functions.WriteExceptionToLogFile(e);
                spoolMessage("EXCEPTION OCCURRED: " + e.Message);

                BrowserSender exceptionBrowserSender = new BrowserSender(Context);
                exceptionBrowserSender.SendNormalHTMLPageToBrowser("<h1>Remote Potato Error</h1>An error occurred and remote potato was unable to serve this web page.<br /><br />Check the debug logs for more information.");
            }
            #endif
        }
        private void ProcessHTTPLSURL(string txtAction, ref BrowserSender browserSender)
        {
            // GET STREAMER ID
            int ID;
            if (txtAction.StartsWith("httplivestream/"))
            {
                txtAction = txtAction.Replace("httplivestream/","");

                int nextSlash = txtAction.IndexOf("/");
                if (nextSlash == -1)
                {
                    browserSender.Send404Page();
                    return;
                }

                string strMediaStreamerID = txtAction.Substring(0, nextSlash);

                if (! int.TryParse(strMediaStreamerID, out ID))
                {
                    browserSender.Send404Page();
                    return;
                }

                // Make txtAction the final portion
                txtAction = txtAction.Replace(ID.ToString() + "/","");
            }
            else
            {
                browserSender.Send404Page();
                return;
            }

            if (txtAction.EndsWith("m3u8"))
            {
                string indexFile = StreamingManager.Default.IndexFileForStreamer(ID);
                browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
                return;
            }

            if (txtAction.StartsWith("seg"))
            {
                txtAction = txtAction.Replace(".ts", ""); // remove extension

                // Get segment number
                string strSegNumber;
                List<string> parts = txtAction.Split('-').ToList();
                if (parts.Count > 1)
                    strSegNumber = parts[1];
                else
                {
                    browserSender.Send404Page();
                    return;
                }

                int iSegNumber = 0;
                if (!int.TryParse(strSegNumber, out iSegNumber))
                {
                    browserSender.Send404Page();
                    return;
                }

                byte[] TSdata = new byte[]{};
                string txtError = "";
                if (StreamingManager.Default.SegmentFromStreamer(ID, iSegNumber, ref TSdata, ref txtError))
                {
                    browserSender.SendDataToBrowser("video/mp2t", TSdata);
                    return;
                }
                else
                {
                    Functions.WriteLineToLogFileIfSetting(Settings.Default.DebugStreaming, "Could not get streaming segment number " + strSegNumber + ":" + txtError);
                    browserSender.Send404Page();
                }
            }
        }
        public static bool SendFolderFilesAsZipFile(FileBrowseResult fbResult, ref BrowserSender bSender)
        {
            // We'll need a shell helper
            CreateShellHelperIfNull();

            // Set up temp directory
            string tempFolderName = Path.GetRandomFileName();
            string tempPath = Path.Combine(Functions.ZipTempFolder, tempFolderName);
            Directory.CreateDirectory(tempPath);

            // Any files?
            if (fbResult.Files.Count < 1) return false;

            List<string> outputFiles = new List<string>();
            foreach (BrowseItem bItem in fbResult.Files)
            {
                string strFullPath = Path.Combine(fbResult.BaseDirectory, bItem.Name);
                outputFiles.Add(strFullPath);
            }

            // Now zip up the files
            string strOutputZipFile = Path.Combine(Functions.ZipTempFolder, (Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".zip"));
            bool result = ZipHelper.CreateZipFileFromFiles(outputFiles, strOutputZipFile);

            // And send the zip file to the browser
            result &= (bSender.SendFileToBrowser(strOutputZipFile, false, false, true));
            File.Delete(strOutputZipFile);
            Directory.Delete(tempPath, true);

            return result;
        }
        private void WebServiceProcess(string action, ref BrowserSender browserSender, ref string PostObjects)
        {
            if (Settings.Default.DebugFullAPI)
            {
                Functions.WriteLineToLogFile("\r\n\r\nAPI: Incoming API Call: " + action);
                if (PostObjects.Length > 0)
                    Functions.WriteLineToLogFile("API: Post Object String: [" + PostObjects + "]");
                else
                    Functions.WriteLineToLogFile("API: Post Object String: Blank.");
            }

            try
            {

                // Pre-process, e.g. to correct '%2B replaced by + sign' bug
                action = preProcessActionString(action);

                // LOGIN - GET TOKEN
                if (action.StartsWith("xml/login"))
                {
                    if (
                        (!qsParams.HasParameter("un")) &&
                        (!qsParams.HasParameter("hashedpw") || (!qsParams.HasParameter("pw")))
                        )
                    {
                        // not enough params
                        XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"NOT_ENOUGH_PARAMETERS\" />";
                        browserSender.SendXMLToBrowser(XMLresponse);
                        return;
                    }

                    string UN = "", PW = "", HPW = "", client = "";
                    bool passwordIsHashed = qsParams.HasParameter("hashedpw");

                    // Client (optional)
                    if (qsParams.HasParameter("client"))
                    {
                        client = qsParams["client"].Trim();
                        client = HttpUtility.UrlDecode(client);
                    }

                    UN = qsParams["un"].Trim();
                    UN = HttpUtility.UrlDecode(UN);
                    if (passwordIsHashed)
                    {
                        HPW = qsParams["hashedpw"].Trim();
                        HPW = HttpUtility.UrlDecode(HPW);
                    }
                    else
                    {
                        PW = qsParams["pw"].Trim();
                        PW = HttpUtility.UrlDecode(PW);
                    }

                    if (action.StartsWith("xml/login64"))
                    {
                        UN = Functions.DecodeFromBase64(UN);
                        if (passwordIsHashed)
                            HPW = Functions.DecodeFromBase64(PW);
                        else
                            PW = Functions.DecodeFromBase64(PW);

                        client = Functions.DecodeFromBase64(client);
                    }

                    if ((!UN.Equals(Settings.Default.UserName)) ||
                        (!Functions.StringHashesToPasswordHash(PW, passwordIsHashed))
                        )
                    {
                        // incorrect credentials - always log
                        Functions.WriteLineToLogFile("API: Failed login attempt from client " + client + " with username " + UN);

                        XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"INCORRECT_CREDENTIALS\" />";
                        browserSender.SendXMLToBrowser(XMLresponse);
                        return;
                    }

                    // Success!
                    if (Settings.Default.DebugBasic)
                        Functions.WriteLineToLogFile("API: User " + UN + " logged in OK using client " + client);

                    string token = AuthSessionHelper.Default.AddClient(currentClientIP);  // Store session, get token
                    XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"OK\" token=\"" + token + "\" />";
                    browserSender.SendXMLToBrowser(XMLresponse);
                    return;
                }

                // ************ REMAINING METHODS MAY REQUIRE AUTHENTICATION
                if (!AuthenticatedByToken)
                {
                    Functions.logAPIoutputString("ASending 403 Incorrect Authentication");
                    browserSender.SendGenericStatusCodePage("403", "Incorrect authentication");
                    spoolMessage("API: Must provide a valid authentication token.  Use /xml/login first.");
                    return;
                }

                // Should we zip up afterwards
                bool zipContent = false;
                if (action.EndsWith("/zip"))
                {
                    zipContent = true;
                    action = action.Replace("/zip", "");
                }
                if (txtActionOriginalCase.EndsWith("/zip"))
                {
                    txtActionOriginalCase = txtActionOriginalCase.Replace("/zip", "");
                }

                if (action.StartsWith("xml/channels/setasfavorite/"))
                {
                    string chanID = action.Replace("xml/channels/setasfavorite/", "");

                    string strResponse = (EPGManager.MakeChannelFavorite(chanID)) ? "OK" : "ERROR";
                    XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse);
                    if (Settings.Default.DebugChannels) Functions.WriteLineToLogFile("API: Set channel " + chanID + " as favorite OK.");
                }
                else if (action.StartsWith("xml/channels/unsetasfavorite/"))
                {
                    string chanID = action.Replace("xml/channels/unsetasfavorite/", "");

                    string strResponse = (EPGManager.MakeChannelNotFavorite(chanID)) ? "OK" : "ERROR";
                    XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse);
                    if (Settings.Default.DebugChannels) Functions.WriteLineToLogFile("API: Unset channel " + chanID + " as not favorite OK.");
                }
                else if (action == "xml/channels/all")
                {
                    // New 2011:  Update channels first from media center (MediaCenter can randomly change internal IDs)
                    EPGManager.UpdateTVChannels();

                    XMLresponse = EPGExporter.AllChannelsAsXML();
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all channels via XML web request...");
                }
                else if (action.StartsWith("xml/programmes"))
                {
                    string subAction = action.Replace("xml/programmes/", "");

                    // No description?  (turbo mode)
                    bool omitDescriptions = (subAction.StartsWith("nodescription"));
                    if (omitDescriptions)
                    {
                        subAction = subAction.Replace("nodescription/", "");
                    }

                    // If a programme type is specified, restrict to this type, otherwise use all
                    TVProgrammeType restrictProgrammesToType = (qsParams.HasParameter("programmetype")) ?
                        (TVProgrammeType)Enum.Parse(new TVProgrammeType().GetType(), qsParams["programmetype"], true) :
                        TVProgrammeType.All;

                    // 2. CHANNELS
                    List<string> TVServiceIDs = new List<string>();
                    if (subAction.StartsWith("limitchannels/"))
                    {
                        subAction = subAction.Replace("limitchannels/", "");
                        TVServiceIDs = Functions.StringListFromXML(PostObjects);
                    }
                    else if (subAction.StartsWith("favoritechannels/"))
                    {
                        subAction = subAction.Replace("favoritechannels/", "");
                        TVServiceIDs = EPGManager.EPGDisplayedTVChannelsServiceIDs;
                    }
                    else if (subAction.StartsWith("byepgrequest"))
                    {

                        List<EPGRequest> EPGRequests = EPGRequest.ArrayFromXML(PostObjects);

                        try
                        {
                            XMLresponse = EPGExporter.EPGwithEPGRequests(EPGRequests, omitDescriptions, restrictProgrammesToType);
                            if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes (using " + EPGRequests.Count.ToString() + " epg requests) via XML web request...");
                        }
                        catch (Exception ex)
                        {
                            Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse array of EPG requests.  Date passed was " + PostObjects);
                            Functions.WriteExceptionToLogFile(ex);
                        }
                    }

                    // 3. DATE / DAYRANGE
                    if (subAction.StartsWith("date/"))
                    {
                        string strDate = subAction.Replace("date/", "");
                        DateTime localDate = new DateTime();
                        if (DateTime.TryParse(strDate, out localDate))
                        {

                            XMLresponse = EPGExporter.EPGForLocalDate(localDate, TVServiceIDs, omitDescriptions, restrictProgrammesToType);
                            if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for date " + strDate + " via XML web request...");
                        }
                        else
                        {
                            Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse local date to export shows.  Date passed was " + strDate + ".");
                        }
                    }
                    else if (subAction.StartsWith("daterange/"))
                    {
                        string strDate = subAction.Replace("daterange/", "");
                        string[] dateRanges = strDate.Split(new string[] { "/" }, StringSplitOptions.None);
                        if (dateRanges.Count() > 1)
                        {
                            DateTime startDateTime, endDateTime;
                            if (DateTime.TryParse(dateRanges[0], out startDateTime) &&
                                DateTime.TryParse(dateRanges[1], out endDateTime)
                                )
                            {
                                if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for date range " + strDate + " via XML web request...");
                                XMLresponse = EPGExporter.EPGForDateRange(startDateTime, endDateTime, TVServiceIDs, omitDescriptions, restrictProgrammesToType);
                            }
                            else
                            {
                                Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse day ranges.");
                            }
                        }
                    }
                    else if (subAction.StartsWith("dayrange/"))
                    {
                        string strDate = subAction.Replace("dayrange/", "");

                        string[] dayRanges = strDate.Split(new string[] { "/" }, StringSplitOptions.None);
                        if (dayRanges.Count() > 1)
                        {
                            int startDaysAhead, numberOfDays;
                            if (int.TryParse(dayRanges[0], out startDaysAhead) &&
                                int.TryParse(dayRanges[1], out numberOfDays)
                                )
                            {
                                if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for day range " + strDate + " via XML web request...");
                                XMLresponse = EPGExporter.EPGForDaysRange(startDaysAhead, numberOfDays, TVServiceIDs, omitDescriptions, restrictProgrammesToType);
                            }
                            else
                            {
                                Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse day ranges.");
                            }
                        }
                    }
                    else if (subAction.StartsWith("search"))
                    {
                        EPGSearch theSearch = EPGSearch.FromXML(PostObjects);
                        if (theSearch != null)
                        {
                            XMLresponse = EPGExporter.TVProgrammesMatchingSearch(theSearch);

                            if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all programmes matching search.");
                        }
                        else
                        {
                            Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse search request XML");
                        }
                    }
                }
                else if (action.StartsWith("xml/programme/getinfo/"))
                {
                    string strUID = action.Replace("xml/programme/getinfo/", "");
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting programme info blob for prog ID " + strUID + " via XML web request...");
                    XMLresponse = EPGExporter.TVProgrammeInfoBlobForProgID(strUID);
                }
                else if (action.StartsWith("xml/filebrowse/dir"))
                {
                    FileBrowseRequest fbrequest = FileBrowseRequest.FromXML(PostObjects);
                    if (fbrequest != null)
                    {
                        XMLresponse = FileBrowseExporter.FileBrowseUsingRequestAsXML(fbrequest);

                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting list of files matching request (path " + fbrequest.FullPath + ")");
                    }
                    else
                    {
                        Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse file browse request XML");
                    }
                }
                else if (action.StartsWith("xml/recordings"))
                {
                    // FOR NOW.. ..refresh each time, although strictly may not be necessary
                    if (Settings.Default.RecordingsRetrieveAsParanoid) EPGManager.ReloadAllRecordings();

                    XMLresponse = EPGExporter.RecordingsBlobAsXML();
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all recordings via XML web request...");
                }
                else if (action.StartsWith("xml/settings"))
                {
                    XMLresponse = EPGExporter.AllSettingsAsXML();
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all settings via XML web request...");
                }
                else if (action.StartsWith("xml/record/byrecordingrequest"))
                {
                    RecordingRequest tReq = RecordingRequest.FromXML(PostObjects);

                    XMLresponse = EPGManager.ScheduleRecording(RecordingRequest.FromXML(PostObjects)).ToXML();
                }
                else if (action.StartsWith("xml/recordedtv"))
                {
                    /*if (action.Contains("refreshnow"))
                        RecTV.Default.RefreshCache(); */

                    XMLresponse = EPGExporter.AllRecordedTVAsXML();
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all recorded TV via XML web request...");
                }
                else if (action.StartsWith("xml/cancelrequest/"))
                {
                    string txtID = action.Replace("xml/cancelrequest/", "");
                    XMLresponse = WebSvcCancelRequest(txtID);
                }
                else if (action.StartsWith("xml/sendremotekey/"))
                {
                    string txtCmd = action.Replace("xml/sendremotekey/", "");

                    string strResponse = IRCommunicator.Default.SendIRCommand(txtCmd); // Returns OK or HELPER_NOT_RUNNING.  Doesn't return socket errors (it's ASync)
                    XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse);
                }
                else if (action.StartsWith("xml/showlog"))
                {
                    XMLresponse = "<?xml version=\"1.0\"?><log ";
                    if (Settings.Default.AllowRemoteLogRetrieval)
                    {
                        XMLresponse += "result=\"OK\" contents=\"" + FileCache.ReadTextFileFromDisk(Functions.DebugLogFileFN) + "\">";
                    }
                    else
                    {
                        XMLresponse += "result=\"Error\" contents=\"RemoteLoggingDisabled\">";
                    }

                    XMLresponse += "</log>";
                }
                else if (action.StartsWith("xml/cancelrecording/"))
                {
                    string txtID = action.Replace("xml/cancelrecording/", "");
                    XMLresponse = WebSvcCancelRecording(txtID);
                }
                else if (action.StartsWith("xml/deletefile64"))
                {
                    string filePath = "";
                    if (PostObjects.Trim().Length > 0)
                    {
                        filePath = HttpUtility.UrlDecode(PostObjects);
                        filePath = Functions.DecodeFromBase64(filePath, Encoding.UTF8);
                    }

                    XMLresponse = WebSvcDeleteFileByFilePath(filePath);
                }
                else if (action.StartsWith("xml/deletefile"))
                {
                    string filePath = "";
                    if (PostObjects.Trim().Length > 0)
                        filePath = HttpUtility.UrlDecode(PostObjects);
                    else
                    {
                        // LEGACY - use URL path
                        filePath = action.Replace("xml/deletefile/", "");
                    }

                    XMLresponse = WebSvcDeleteFileByFilePath(filePath);
                }
                else if (action.StartsWith("xml/mediastream/start/bymediastreamingrequest"))
                {
                    MediaStreamingResult streamResult;
                    MediaStreamingRequest streamRq = XMLHelper.Deserialize<MediaStreamingRequest>(PostObjects);

                    if (streamRq != null)
                        streamResult = StreamingManager.Default.StartStreamer(streamRq, Request.UserHostName);
                    else
                        streamResult = new MediaStreamingResult(MediaStreamingResultCodes.NamedError, "Error in streaming request.");

                    XMLresponse = XMLHelper.Serialize<MediaStreamingResult>(streamResult);
                }
                else if (action.StartsWith("xml/mediastream/probe/byfilename"))
                {
                    string strFileName = HttpUtility.UrlDecode(PostObjects);
                    strFileName = strFileName.Trim();

                    if (action.StartsWith("xml/mediastream/probe/byfilename64"))
                        strFileName = Functions.DecodeFromBase64(strFileName);

                    List<AVStream> result;
                    if (strFileName.Length > 0)
                        result = StreamingManager.Default.ProbeFile(strFileName);
                    else
                        result = new List<AVStream>();

                    if (Settings.Default.DebugStreaming)
                        Functions.WriteLineToLogFile("Probed file " + strFileName + ": sending back details of " + result.Count.ToString() + " AV streams.");

                    XMLresponse = XMLHelper.Serialize<List<AVStream>>(result);
                }
                else if (action.StartsWith("xml/mediastream/keepalive/"))
                {
                    string strStreamerID = action.Replace("xml/mediastream/keepalive/", "");
                    int streamerID;
                    string strmStatus;
                    if (int.TryParse(strStreamerID, out streamerID))
                    {
                        strmStatus = StreamingManager.Default.KeepStreamerAliveAndReturnStatus(streamerID);
                    }
                    else
                    {
                        Functions.WriteLineToLogFile("Warning: Could not parse streamer ID " + strStreamerID);
                        strmStatus = "invalid_id";
                    }

                    //XMLresponse = XMLHelper.XMLReponseWithOutputString(strmStatus);
                    XMLresponse = strmStatus;
                    if (Settings.Default.DebugAdvanced)
                        Functions.WriteLineToLogFile("MediaStreaming: GetStatus  (" + strStreamerID + "): " + strmStatus);
                }
                else if (action.StartsWith("xml/mediastream/stop/"))
                {
                    string strStreamerID = action.Replace("xml/mediastream/stop/", "");
                    int streamerID;
                    try
                    {
                        if (int.TryParse(strStreamerID, out streamerID))
                        {
                            if (!StreamingManager.Default.StopStreamer(streamerID))
                                Functions.WriteLineToLogFile("Warning: Could not stop streamer ID " + strStreamerID);
                        }
                        else
                        {
                            Functions.WriteLineToLogFile("Warning: Could not parse streamer ID " + strStreamerID);
                        }
                    }
                    catch (Exception ex)
                    {
                        Functions.WriteExceptionToLogFileIfAdvanced(ex);
                    }

                    XMLresponse = XMLHelper.XMLReponseWithOutputString("No Data");
                }
                else if (action.StartsWith("xml/stream/start"))
                {
                    WTVStreamingVideoResult streamResult;
                    WTVStreamingVideoRequest streamRq = XMLHelper.Deserialize<WTVStreamingVideoRequest>(PostObjects);
                    if (streamRq == null)
                    {
                        streamResult = new WTVStreamingVideoResult(DSStreamResultCodes.ErrorInStreamRequest);
                    }
                    else
                    {
                        try
                        {
                            streamResult = DSStreamingManager.Default.StartStreamer(streamRq);
                        }
                        catch (Exception e)
                        {
                            Functions.WriteLineToLogFile("Exception setting up streaming object:");
                            Functions.WriteExceptionToLogFile(e);
                            streamResult = new WTVStreamingVideoResult(DSStreamResultCodes.ErrorExceptionOccurred, e.Message);
                        }
                    }

                    XMLresponse = XMLHelper.Serialize<WTVStreamingVideoResult>(streamResult);
                }
                else if (action.StartsWith("xml/stream/stop"))
                {
                    XMLresponse = XMLHelper.XMLReponseWithOutputString("ERROR (DEPRECATED)");
                }
                else if (action.StartsWith("xml/picture/thumbnailzip/"))
                {
                    FileBrowseRequest fbrequest = FileBrowseRequest.FromXML(PostObjects);
                    if (fbrequest != null)
                    {
                        if (PictureExporter.SendThumbnailsAsZipFile(fbrequest, FatAttitude.ThumbnailSizes.Small, ref browserSender))
                            return;
                        else
                        {
                            if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Could not export zip of thumbnails.");
                            browserSender.Send404Page();
                        }
                    }
                    else
                    {
                        Functions.WriteLineToLogFile("ThumbnailZip: Error in requestprocessor- could not parse file browse request XML");
                    }
                }
                else if (action.StartsWith("xml/picture/get"))  // matches /xml/picture/getrequest too
                {
                    string strSubAction = txtActionOriginalCase.Replace("xml/picture/", "");

                    // URL DECODE
                    strSubAction = HttpUtility.UrlDecode(strSubAction);

                    string strParams;
                    string strFileName = "";
                    bool fileNameAtEndOfUri = false;
                    bool fileNameAtEndOfUriIsBase64Encoded = false;
                    if (strSubAction.StartsWith("getwithfilename"))  // GET FILENAME FROM URL
                    {
                        fileNameAtEndOfUri = true;

                        fileNameAtEndOfUriIsBase64Encoded = strSubAction.StartsWith("getwithfilename64");

                        if (fileNameAtEndOfUriIsBase64Encoded)
                            strParams = strSubAction.Replace("getwithfilename64/", "");
                        else
                            strParams = strSubAction.Replace("getwithfilename/", "");
                    }
                    else
                    // GET FILENAME FROM POST STRING
                    {
                        fileNameAtEndOfUri = false;
                        strFileName = PostObjects;
                        strParams = strSubAction.Replace("get/", "");
                    }

                    string[] Params = strParams.Split(new string[] { "/" }, StringSplitOptions.None);

                    bool haveFrameSizes = false;
                    int frameWidth = 0;
                    int frameHeight = 0;
                    if (Params.Count() > 1)
                    {
                        if ((int.TryParse(Params[0], out frameWidth) &&
                                 int.TryParse(Params[1], out frameHeight)
                                ))
                            haveFrameSizes = ((frameWidth > 0) && (frameHeight > 0));
                        else
                            haveFrameSizes = false;
                    }
                    else
                        // Send full picture
                        haveFrameSizes = false;

                    if (!haveFrameSizes) Functions.WriteLineToLogFile("Xml/Picture: invalid frame size (or none supplied): using full picture");

                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting picture " + strFileName + " resized to frame " + frameWidth.ToString() + "x" + frameHeight.ToString());

                    // Get Filename if not got already
                    // File name from Uri ?
                    if (fileNameAtEndOfUri)
                    {
                        if (fileNameAtEndOfUriIsBase64Encoded)
                        {
                            // Take final component and un-encode to produce filename
                            strFileName = Params[Params.Count() - 1];
                            strFileName = HttpUtility.UrlDecode(strFileName);
                            strFileName = Functions.DecodeFromBase64(strFileName);
                        }
                        else
                        {
                            // Reconstruct filename by putting /slashed/ components back together
                            for (int pCount = 2; pCount < Params.Count(); pCount++)
                            {
                                strFileName = strFileName + Params[pCount];
                                if (pCount < (Params.Count() - 1))
                                    strFileName = strFileName + "/";

                                strFileName = HttpUtility.UrlDecode(strFileName);
                            }
                        }

                    }

                    if (string.IsNullOrEmpty(strFileName))
                    {
                        Functions.WriteLineToLogFile("Xml/Picture : No filename specified in POST request, sending 404");
                        browserSender.Send404Page();
                        return;
                    }

                    // Send
                    if (haveFrameSizes)
                    {

                        byte[] resizedPictureData = new byte[] { };
                        if (ImageResizer.ResizePicture(strFileName, new Size(frameWidth, frameHeight), out resizedPictureData, ImageFormat.Jpeg, false))
                        {
                            browserSender.SendDataToBrowser(Functions.MimeTypeForFileName(strFileName), resizedPictureData);
                            return;
                        }
                        else
                        {
                            Functions.WriteLineToLogFile("Xml/Picture: Could not resize picture.");
                            browserSender.Send404Page();
                            return;
                        }
                    }
                    else  // No frame sizes, send full image
                    {
                        browserSender.SendFileToBrowser(strFileName);
                        return;
                    }

                }
                else if (action.StartsWith("xml/music/framework"))
                {
                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.MusicFrameworkAsXML();
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting music framework blob via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/artist"))
                {
                    bool isBase64Encoded = (action.Contains("artist64/"));
                    action = action.Replace("artist64", "artist");
                    txtActionOriginalCase = txtActionOriginalCase.Replace("artist64", "artist");

                    string strArtistID = txtActionOriginalCase.Replace("xml/music/songs/artist/", "");
                    strArtistID = HttpUtility.UrlDecode(strArtistID);

                    if (isBase64Encoded)
                        strArtistID = Functions.DecodeFromBase64(strArtistID);

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.GetSongsForArtistAsXML(strArtistID);
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting songs for artist " + strArtistID + " via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/album"))
                {
                    bool isBase64Encoded = (action.Contains("album64/"));
                    action = action.Replace("album64", "album");
                    txtActionOriginalCase = txtActionOriginalCase.Replace("album64", "album");

                    // USE case sensitive action string for match
                    string strAlbumID = txtActionOriginalCase.Replace("xml/music/songs/album/", "");
                    strAlbumID = HttpUtility.UrlDecode(strAlbumID);

                    if (isBase64Encoded)
                        strAlbumID = Functions.DecodeFromBase64(strAlbumID);

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.GetSongsForAlbumAsXML(strAlbumID);
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting songs for album " + strAlbumID + " via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/genre"))
                {
                    bool isBase64Encoded = (action.Contains("genre64/"));
                    action = action.Replace("genre64", "genre");
                    txtActionOriginalCase = txtActionOriginalCase.Replace("genre64", "genre");

                    // USE case sensitive action string for match
                    string strGenreID = txtActionOriginalCase.Replace("xml/music/songs/genre/", "");
                    strGenreID = HttpUtility.UrlDecode(strGenreID);

                    if (isBase64Encoded)
                        strGenreID = Functions.DecodeFromBase64(strGenreID);

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.GetSongsForGenreAsXML(strGenreID);
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting songs for genre " + strGenreID + " via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/all"))
                {

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.GetAllSongsAsXML();
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all songs in library via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/checkexists"))
                {
                    bool isBase64Encoded = (action.Contains("checkexists64/"));
                    action = action.Replace("checkexists64", "checkexists");
                    txtActionOriginalCase = txtActionOriginalCase.Replace("checkexists64", "checkexists");

                    // USE case sensitive action string for match
                    string strSongID = txtActionOriginalCase.Replace("xml/music/songs/checkexists/", "");
                    strSongID = HttpUtility.UrlDecode(strSongID);

                    if (isBase64Encoded)
                        strSongID = Functions.DecodeFromBase64(strSongID);

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.WMPItemFileExistsAsXML(strSongID);
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting whether song exists... " + XMLresponse);
                    }
                }
                else
                {

                    Functions.WriteLineToLogFile("XML: Unknown request");
                    XMLresponse = "";
                }

                if (String.IsNullOrEmpty(XMLresponse))
                {
                    Functions.WriteLineToLogFile("NULL xmlresponse - nothing to send out to Silverlight client.  Sending error string.");
                    browserSender.SendStringToBrowser(XMLHelper.XMLReponseWithOutputString("No Data"));
                    return;
                }

                // Strip out any UTF-16 encoding
                XMLresponse = Functions.StripIllegalXmlCharacters(XMLresponse);

                // Zip up ?
                if (zipContent)
                {
                    Functions.logAPIoutputString(XMLresponse);
                    XMLresponse = ZipHelper.ZipString(XMLresponse);

                    if (Settings.Default.DebugServer)
                        Functions.WriteLineToLogFile("Zipped String to base64 string.  Length:" + XMLresponse.Length.ToString() + " characters. ");

                    browserSender.SendZipStringToBrowser(XMLresponse);
                }
                else
                    browserSender.SendXMLToBrowser(XMLresponse);
            }
            catch (Exception e)
            {
                string errorResponse = XMLHelper.XMLReponseWithOutputString("An error occurred - " + e.Message + " - check the debug log on the server.");

                Functions.WriteLineToLogFile("Exception while processing XML request:");
                Functions.WriteExceptionToLogFile(e);

                browserSender.SendXMLToBrowser(errorResponse);
            }
        }
        private bool SendSongToBrowser(ref BrowserSender browserSender, bool isBase64Encoded, bool sendChunked, bool isDownload)
        {
            if (! (qsParams.HasParameter("id"))) return false;

            string songID = HttpUtility.UrlDecode(qsParams["id"]);

            if (isBase64Encoded)
                songID = Functions.DecodeFromBase64(songID);

            string FN;
            using (WMPManager manager = new WMPManager())
            {
                FN = manager.FileNameForWMPItem(songID);
                if (string.IsNullOrEmpty(FN)) return false;
            }

            // Send CHUNKED  (not implemented)
            browserSender.SendFileToBrowser(FN, false, sendChunked, isDownload);
            return true;
        }
        private void GetFileThumbnailUsingQueryString(ref BrowserSender browserSender, bool isBase64Encoded)
        {
            // Any parameters?
            bool validated = true;
            validated &= qsParams.HasParameter("filename");
            validated &= qsParams.HasParameter("size");

            if (!validated)
            {
                bool foo = browserSender.Send404Page();
                return;
            }

            string size = qsParams["size"];

            string qsFN = qsParams["filename"];
            string fileName = HttpUtility.UrlDecode( qsFN );
            if (isBase64Encoded)
                fileName = Functions.DecodeFromBase64(fileName, Encoding.UTF8);  // http uses UTF8 encoding

            FatAttitude.ThumbnailSizes tSize = (FatAttitude.ThumbnailSizes)Enum.Parse(typeof(FatAttitude.ThumbnailSizes), size, true);

            SendFileThumbnail(fileName, tSize, ref browserSender);
        }
        private void WebServiceProcess(string action, ref BrowserSender browserSender, ref string PostObjects)
        {
            if (Settings.Default.DebugFullAPI)
            {
                Functions.WriteLineToLogFile("\r\n\r\nAPI: Incoming API Call: " + action);
                if (PostObjects.Length > 0)
                    Functions.WriteLineToLogFile("API: Post Object String: [" + PostObjects + "]");
                else
                    Functions.WriteLineToLogFile("API: Post Object String: Blank.");
            }

            try
            {

                // Pre-process, e.g. to correct '%2B replaced by + sign' bug
                action = preProcessActionString(action);

                // LOGIN - GET TOKEN
                if (action.StartsWith("xml/login"))
                {
                    if (
                        (!qsParams.HasParameter("un")) &&
                        (!qsParams.HasParameter("hashedpw") || (!qsParams.HasParameter("pw")))
                        )
                    {
                        // not enough params
                        XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"NOT_ENOUGH_PARAMETERS\" />";
                        browserSender.SendXMLToBrowser(XMLresponse);
                        return;
                    }

                    string UN = "", PW = "", HPW = "", client = "";
                    bool passwordIsHashed = qsParams.HasParameter("hashedpw");

                    // Client (optional)
                    if (qsParams.HasParameter("client"))
                    {
                        client = qsParams["client"].Trim();
                        client = HttpUtility.UrlDecode(client);
                    }

                    UN = qsParams["un"].Trim();
                    UN = HttpUtility.UrlDecode(UN);
                    if (passwordIsHashed)
                    {
                        HPW = qsParams["hashedpw"].Trim();
                        HPW = HttpUtility.UrlDecode(HPW);
                    }
                    else
                    {
                        PW = qsParams["pw"].Trim();
                        PW = HttpUtility.UrlDecode(PW);
                    }

                    if (action.StartsWith("xml/login64"))
                    {
                        UN = Functions.DecodeFromBase64(UN);
                        if (passwordIsHashed)
                            HPW = Functions.DecodeFromBase64(PW);
                        else
                            PW = Functions.DecodeFromBase64(PW);

                        client = Functions.DecodeFromBase64(client);
                    }

                    if ((!UN.Equals(Settings.Default.UserName)) ||
                        (!Functions.StringHashesToPasswordHash(PW, passwordIsHashed))
                        )
                    {
                        // incorrect credentials - always log
                        Functions.WriteLineToLogFile("API: Failed login attempt from client " + client + " with username " + UN);

                        XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"INCORRECT_CREDENTIALS\" />";
                        browserSender.SendXMLToBrowser(XMLresponse);
                        return;
                    }

                    // Success!
                    if (Settings.Default.DebugBasic)
                        Functions.WriteLineToLogFile("API: User " + UN + " logged in OK using client " + client);

                    string token = AuthSessionHelper.Default.AddClient(currentClientIP);  // Store session, get token
                    XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"OK\" token=\"" + token + "\" />";
                    browserSender.SendXMLToBrowser(XMLresponse);
                    return;
                }

                // ************ REMAINING METHODS MAY REQUIRE AUTHENTICATION
                if (!AuthenticatedByToken)
                {
                    Functions.logAPIoutputString("ASending 403 Incorrect Authentication");
                    browserSender.SendGenericStatusCodePage("403", "Incorrect authentication");
                    spoolMessage("API: Must provide a valid authentication token.  Use /xml/login first.");
                    return;
                }

                // Should we zip up afterwards
                bool zipContent = false;
                if (action.EndsWith("/zip"))
                {
                    zipContent = true;
                    action = action.Replace("/zip", "");
                }
                if (txtActionOriginalCase.EndsWith("/zip"))
                {
                    txtActionOriginalCase = txtActionOriginalCase.Replace("/zip", "");
                }

                if (action.StartsWith("xml/channels/setasfavorite/"))
                {
                    string chanID = action.Replace("xml/channels/setasfavorite/", "");

                    string strResponse = (EPGManager.MakeChannelFavorite(chanID)) ? "OK" : "ERROR";
                    XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse);
                    if (Settings.Default.DebugChannels) Functions.WriteLineToLogFile("API: Set channel " + chanID + " as favorite OK.");
                }
                else if (action.StartsWith("xml/channels/unsetasfavorite/"))
                {
                    string chanID = action.Replace("xml/channels/unsetasfavorite/", "");

                    string strResponse = (EPGManager.MakeChannelNotFavorite(chanID)) ? "OK" : "ERROR";
                    XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse);
                    if (Settings.Default.DebugChannels) Functions.WriteLineToLogFile("API: Unset channel " + chanID + " as not favorite OK.");
                }
                else if (action == "xml/channels/all")
                {
                    // New 2011:  Update channels first from media center (MediaCenter can randomly change internal IDs)
                    EPGManager.UpdateTVChannels();

                    XMLresponse = EPGExporter.AllChannelsAsXML();
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all channels via XML web request...");
                }
                else if (action.StartsWith("xml/programmes"))
                {
                    string subAction = action.Replace("xml/programmes/", "");

                    // No description?  (turbo mode)
                    bool omitDescriptions = (subAction.StartsWith("nodescription"));
                    if (omitDescriptions)
                    {
                        subAction = subAction.Replace("nodescription/", "");
                    }

                    // If a programme type is specified, restrict to this type, otherwise use all
                    TVProgrammeType restrictProgrammesToType = (qsParams.HasParameter("programmetype")) ?
                        (TVProgrammeType)Enum.Parse(new TVProgrammeType().GetType(), qsParams["programmetype"], true) :
                        TVProgrammeType.All;

                    // 2. CHANNELS
                    List<string> TVServiceIDs = new List<string>();
                    if (subAction.StartsWith("limitchannels/"))
                    {
                        subAction = subAction.Replace("limitchannels/", "");
                        TVServiceIDs = Functions.StringListFromXML(PostObjects);
                    }
                    else if (subAction.StartsWith("favoritechannels/"))
                    {
                        subAction = subAction.Replace("favoritechannels/", "");
                        TVServiceIDs = EPGManager.EPGDisplayedTVChannelsServiceIDs;
                    }
                    else if (subAction.StartsWith("byepgrequest"))
                    {

                        List<EPGRequest> EPGRequests = EPGRequest.ArrayFromXML(PostObjects);

                        try
                        {
                            XMLresponse = EPGExporter.EPGwithEPGRequests(EPGRequests, omitDescriptions, restrictProgrammesToType);
                            if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes (using " + EPGRequests.Count.ToString() + " epg requests) via XML web request...");
                        }
                        catch (Exception ex)
                        {
                            Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse array of EPG requests.  Date passed was " + PostObjects);
                            Functions.WriteExceptionToLogFile(ex);
                        }
                    }

                    // 3. DATE / DAYRANGE
                    if (subAction.StartsWith("date/"))
                    {
                        string strDate = subAction.Replace("date/", "");
                        DateTime localDate = new DateTime();
                        if (DateTime.TryParse(strDate, out localDate))
                        {

                            XMLresponse = EPGExporter.EPGForLocalDate(localDate, TVServiceIDs, omitDescriptions, restrictProgrammesToType);
                            if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for date " + strDate + " via XML web request...");
                        }
                        else
                        {
                            Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse local date to export shows.  Date passed was " + strDate + ".");
                        }
                    }
                    else if (subAction.StartsWith("daterange/"))
                    {
                        string strDate = subAction.Replace("daterange/", "");
                        string[] dateRanges = strDate.Split(new string[] { "/" }, StringSplitOptions.None);
                        if (dateRanges.Count() > 1)
                        {
                            DateTime startDateTime, endDateTime;
                            if (DateTime.TryParse(dateRanges[0], out startDateTime) &&
                                DateTime.TryParse(dateRanges[1], out endDateTime)
                                )
                            {
                                if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for date range " + strDate + " via XML web request...");
                                XMLresponse = EPGExporter.EPGForDateRange(startDateTime, endDateTime, TVServiceIDs, omitDescriptions, restrictProgrammesToType);
                            }
                            else
                            {
                                Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse day ranges.");
                            }
                        }
                    }
                    else if (subAction.StartsWith("dayrange/"))
                    {
                        string strDate = subAction.Replace("dayrange/", "");

                        string[] dayRanges = strDate.Split(new string[] { "/" }, StringSplitOptions.None);
                        if (dayRanges.Count() > 1)
                        {
                            int startDaysAhead, numberOfDays;
                            if (int.TryParse(dayRanges[0], out startDaysAhead) &&
                                int.TryParse(dayRanges[1], out numberOfDays)
                                )
                            {
                                if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for day range " + strDate + " via XML web request...");
                                XMLresponse = EPGExporter.EPGForDaysRange(startDaysAhead, numberOfDays, TVServiceIDs, omitDescriptions, restrictProgrammesToType);
                            }
                            else
                            {
                                Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse day ranges.");
                            }
                        }
                    }
                    else if (subAction.StartsWith("search"))
                    {
                        EPGSearch theSearch = EPGSearch.FromXML(PostObjects);
                        if (theSearch != null)
                        {
                            XMLresponse = EPGExporter.TVProgrammesMatchingSearch(theSearch);

                            if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all programmes matching search.");
                        }
                        else
                        {
                            Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse search request XML");
                        }
                    }
                }
                else if (action.StartsWith("xml/programme/getinfo/"))
                {
                    string strUID = action.Replace("xml/programme/getinfo/", "");
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting programme info blob for prog ID " + strUID + " via XML web request...");
                    XMLresponse = EPGExporter.TVProgrammeInfoBlobForProgID(strUID);
                }
                else if (action.StartsWith("xml/filebrowse/dir"))
                {
                    FileBrowseRequest fbrequest = FileBrowseRequest.FromXML(PostObjects);
                    if (fbrequest != null)
                    {
                        XMLresponse = FileBrowseExporter.FileBrowseUsingRequestAsXML(fbrequest);

                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting list of files matching request (path " + fbrequest.FullPath + ")");
                    }
                    else
                    {
                        Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse file browse request XML");
                    }
                }
                else if (action.StartsWith("xml/recordings"))
                {
                    // FOR NOW.. ..refresh each time, although strictly may not be necessary
                    if (Settings.Default.RecordingsRetrieveAsParanoid) EPGManager.ReloadAllRecordings();

                    XMLresponse = EPGExporter.RecordingsBlobAsXML();
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all recordings via XML web request...");
                }
                else if (action.StartsWith("xml/settings"))
                {
                    XMLresponse = EPGExporter.AllSettingsAsXML();
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all settings via XML web request...");
                }
                else if (action.StartsWith("xml/record/byrecordingrequest"))
                {
                    RecordingRequest tReq = RecordingRequest.FromXML(PostObjects);

                    XMLresponse = EPGManager.ScheduleRecording(RecordingRequest.FromXML(PostObjects)).ToXML();
                }
                else if (action.StartsWith("xml/recordedtv"))
                {
                    /*if (action.Contains("refreshnow"))
                        RecTV.Default.RefreshCache(); */

                    XMLresponse = EPGExporter.AllRecordedTVAsXML();
                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all recorded TV via XML web request...");
                }
                else if (action.StartsWith("xml/cancelrequest/"))
                {
                    string txtID = action.Replace("xml/cancelrequest/", "");
                    XMLresponse = WebSvcCancelRequest(txtID);
                }
                else if (action.StartsWith("xml/sendremotekey/"))
                {
                    string txtCmd = action.Replace("xml/sendremotekey/", "");

                    string strResponse = IRCommunicator.Default.SendIRCommand(txtCmd); // Returns OK or HELPER_NOT_RUNNING.  Doesn't return socket errors (it's ASync)
                    XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse);
                }
                else if (action.StartsWith("xml/showlog"))
                {
                    XMLresponse = "<?xml version=\"1.0\"?><log ";
                    if (Settings.Default.AllowRemoteLogRetrieval)
                    {
                        XMLresponse += "result=\"OK\" contents=\"" + FileCache.ReadTextFileFromDisk(Functions.DebugLogFileFN) + "\">";
                    }
                    else
                    {
                        XMLresponse += "result=\"Error\" contents=\"RemoteLoggingDisabled\">";
                    }

                    XMLresponse += "</log>";
                }
                else if (action.StartsWith("xml/cancelrecording/"))
                {
                    string txtID = action.Replace("xml/cancelrecording/", "");
                    XMLresponse = WebSvcCancelRecording(txtID);
                }
                else if (action.StartsWith("xml/realcancelrecording64/"))
                {
                    string filePath = "";
                    if (PostObjects.Trim().Length > 0)
                    {
                        filePath = HttpUtility.UrlDecode(PostObjects);
                        filePath = Functions.DecodeFromBase64(filePath, Encoding.UTF8);
                    }

                    XMLresponse = WebSvcRealCancelRecording64(filePath);
                }
                else if (action.StartsWith("xml/deletefile64"))
                {
                    string filePath = "";
                    if (PostObjects.Trim().Length > 0)
                    {
                        filePath = HttpUtility.UrlDecode(PostObjects);
                        filePath = Functions.DecodeFromBase64(filePath, Encoding.UTF8);
                    }

                    XMLresponse = WebSvcDeleteFileByFilePath(filePath);
                }
                else if (action.StartsWith("xml/deletefile"))
                {
                    string filePath = "";
                    if (PostObjects.Trim().Length > 0)
                        filePath = HttpUtility.UrlDecode(PostObjects);
                    else
                    {
                        // LEGACY - use URL path
                        filePath = action.Replace("xml/deletefile/", "");
                    }

                    XMLresponse = WebSvcDeleteFileByFilePath(filePath);
                }
                else if (action.StartsWith("xml/deletebackgroundtranscoded"))
                {
                    StreamingManager.Default.DeleteAllBackgroundTranscodedStreamingFiles();
                }
                else if (action.StartsWith("xml/mediastream/start/bymediastreamingrequestgetid"))
                {
                    MediaStreamingResult streamResult2 = new MediaStreamingResult();
                    MediaStreamingRequest streamRq = XMLHelper.Deserialize<MediaStreamingRequest>(PostObjects);

                    if (streamRq != null)
                    {
                        streamResult2.StreamerID = StreamingManager.Default.newUniqueID(streamRq, true);
                        streamResult2.LiveStreamingIndexPath = "/httplivestream/" + streamResult2.StreamerID + "/index.m3u8";
                        streamResult2.Success = true;
                    }
                    else
                    {
                        streamResult2.StreamerID = 0;
                        streamResult2.Success = false;
                    }

                    XMLresponse = XMLHelper.Serialize<MediaStreamingResult>(streamResult2);
                }
                else if (action.StartsWith("xml/mediastream/start/bymediastreamingrequest"))
                {
                    MediaStreamingResult streamResult;
                    MediaStreamingRequest streamRq = XMLHelper.Deserialize<MediaStreamingRequest>(PostObjects);

                    if (streamRq != null)
                        streamResult = StreamingManager.Default.StartStreamer(streamRq, Request.UserHostName);
                    else
                        streamResult = new MediaStreamingResult(MediaStreamingResultCodes.NamedError, "Error in streaming request.");

                    XMLresponse = XMLHelper.Serialize<MediaStreamingResult>(streamResult);
                }
                else if (action.StartsWith("xml/restartrp"))
                {
                    //88888
                    if (RestartRP != null)
                    {
                        RestartRP(this, e);
                        XMLresponse = XMLHelper.Serialize<String>("success");
                    }
                    else
                    {
                        XMLresponse = XMLHelper.Serialize<String>("failed");
                    }
                }
                else if (action.StartsWith("xml/killffmpeglatest"))
                {
                    Process[] workers = Process.GetProcessesByName("ffmpeglatest");
                    foreach (Process worker in workers)
                    {
                        worker.Kill();
                        worker.WaitForExit();
                        worker.Dispose();
                    }
                }
                else if (action.StartsWith("xml/livetvstop"))
                {
                    //foreach (string recTVFolder in Settings.Default.RecordedTVFolders)
                    //{
                    //    DirectoryInfo di = new DirectoryInfo(recTVFolder);
                    //    FileInfo[] files = null;
                    //    try
                    //    {
                    //        files = di.GetFiles("RMCLiveTV*.wtv");
                    //    }
                    //    catch (Exception e)
                    //    {
                    //        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("You probably have a path defined in Recorded TV (RP settings) that does not exist. Exception " + e.ToString());
                    //    }
                    //    if (files != null)
                    //    {
                    //        for (int index = 0; index < files.Length; index++)
                    //        {
                    //            try
                    //            {
                    //                files[index].Delete();
                    //            }
                    //            catch (Exception)
                    //            {
                    //                //file was currently being read or something, just ignore
                    //            }
                    //        }
                    //    }
                    //}

                    Int32 ID;
                    action = action.Replace("xml/livetvstop/", "");

                    action = action.Replace("streamerid=", "");

                    Int32.TryParse(action, out ID);

                    bool stopped;
                    if (ID == 0)
                    {
                        stopped = false;
                    }
                    else
                    {
                        stopped = StreamingManager.Default.StopStreamer(ID, 4);
                    }

                    XMLresponse = XMLHelper.Serialize<string>("LiveTV does not always really stop, but stream " + ID + " is stopped=" + stopped);
                }
                else if (action.StartsWith("xml/getshowschedule"))
                //else if (action.StartsWith("livetv/getshowschedule"))        //suggestion as new syntax
                {
                    action = action.Replace("xml/getshowschedule/", "");
                    //action = action.Replace("livetv/getshowschedule/", "");

                    action = action.Replace("serviceid=", "");
                    string serviceID = action.Substring(0, action.IndexOf("starttime="));
                    action = action.Replace(serviceID, "");
                    action = action.Replace("starttime=", "");
                    long startTime = 0;
                    long.TryParse(action.Substring(0, action.IndexOf("duration=")), out startTime);

                    action = action.Replace("" + startTime, "");
                    action = action.Replace("duration=", "");
                    long duration = 0;
                    long.TryParse(action, out duration);

                    //ShowDebuggingInformationShowProgress:
                    EPGRequest request = new EPGRequest(serviceID, startTime, (startTime + duration));
                    List<EPGRequest> requests = new List<EPGRequest>();
                    requests.Add(request);

                    //TVService ds = new TVService();
                    //List<TVService> dss = new List<TVService>();
                    ////List<string> ServiceIDs = new List<string>();
                    ////List<string> _channels = new List<string>();
                    //TVProgramme progtvchannel = new TVProgramme();
                    //List<TVProgramme> progtvchannelz = new List<TVProgramme>();
                    //progtvchannelz.Add(progtvchannel);

                    var tvProgs = EPGManager.mcData.GetTVProgrammes(requests, false, TVProgrammeType.All);
                    List<string> scheduledshows = new List<string>();
                    string showinfo = "";
                    int firstshow = 0;
                    foreach (var tvProg in tvProgs)
                    {
                        TimeZone localzone = TimeZone.CurrentTimeZone;
                        var startingTime = localzone.ToLocalTime(new DateTime(tvProg.StartTime));
                        var endingTime = localzone.ToLocalTime(new DateTime(tvProg.StopTime));

                        if (firstshow == 0)
                        {
                            DateTime now = DateTime.Now;
                            TimeSpan currShowTime = now.Subtract(startingTime);
                            TimeSpan durationLeft = endingTime.Subtract(now);

                            showinfo = "Show Title: " + tvProg.Title + " Start time: " + String.Format("{0:MMM dd yyyy hh:mm:ss tt}", startingTime) + ". Ends at: " + String.Format("{0:MMM dd yyyy hh:mm:ss tt}", endingTime) + ". Current time: " + String.Format("{0:g}", currShowTime) + ". Time left: " + String.Format("{0:c}", durationLeft) + ". Timezone " + localzone.StandardName;
                            Functions.WriteLineToLogFile(showinfo);
                            firstshow++;
                            scheduledshows.Add(showinfo);
                        }
                        else
                        {
                            showinfo = "Show Title: " + tvProg.Title + ". Start time: " + String.Format("{0:MMM dd yyyy hh:mm:ss tt}", startingTime) + ". Ends at: " + String.Format("{0:MMM dd yyyy hh:mm:ss tt}", endingTime);
                            Functions.WriteLineToLogFile(showinfo);
                            scheduledshows.Add(showinfo);
                        }
                    }
                    XMLresponse = XMLHelper.Serialize<List<string>>(scheduledshows);

                }

                else if (action.StartsWith("xml/checkexists"))
                {
                    Int32 ID;
                    action = action.Replace("xml/checkexists/", "");

                    bool CheckInBackgroundTranscodedDirectory = action.Contains("streamtranscodedinbackground=");

                    if (CheckInBackgroundTranscodedDirectory)
                    {
                        int pos = action.IndexOf("streamtranscodedinbackground=", 0);
                        string action2 = action.Replace(action.Substring(0, "streamtranscodedinbackground=".Length), "");
                        action2 = action2.Replace("/index.m3u8", "");
                        action2 = action2.Replace("/index2.m3u8", "");

                        Int32.TryParse(action2, out ID);
                        action = "segment-0.ts";
                    }
                    else
                    {
                        action = action.Replace("streamid=", "");

                        int pos = action.IndexOf("/segment=", 0);
                        string action2 = action.Replace(action.Substring(pos, action.Length - pos), "");

                        Int32.TryParse(action2, out ID);

                        action = action.Replace(ID + "/segment=", "");
                    }
                    string dir = Functions.AppDataFolder;
                    string streamPath;
                    if (CheckInBackgroundTranscodedDirectory)
                    {
                        streamPath = Path.Combine(dir, "static\\BackgroundTranscodedMediastreams\\");
                    }
                    else
                    {
                        streamPath = Path.Combine(dir, "static\\mediastreams\\");
                    }

                    DirectoryInfo di = new DirectoryInfo(streamPath + ID);
                    FileInfo[] files = null;
                    try
                    {
                        files = di.GetFiles(action);
                    }
                    catch (Exception e)
                    {
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile(e.ToString());
                        XMLresponse = XMLHelper.Serialize<string>("failure");
                    }
                    try
                    {
                        if (files != null && files[0].Exists)
                        {
                            XMLresponse = XMLHelper.Serialize<string>("success");
                        }
                        else
                        {
                            XMLresponse = XMLHelper.Serialize<string>("failure");
                        }
                    }
                    catch (Exception e)
                    {
                        XMLresponse = XMLHelper.Serialize<string>("failure");
                    }
                }
                else if (action.StartsWith("xml/setrprecstreamid/"))
                {
                    //ToDo: Have to define an API that conforms to the rest of the API!
                    //

                    // GET rprec ID and streamID
                    action = action.Replace("xml/setrprecstreamid/", "");

                    long rprecId = 0;
                    long.TryParse((action.Substring(0, action.IndexOf("streamid="))), out rprecId);

                    action = action.Replace("" + rprecId, "");
                    action = action.Replace("streamid=", "");

                    long streamId = 0;
                    long.TryParse(action, out streamId);

                    EPGManager.setStreamID(rprecId, streamId);
                    if (Settings.Default.DebugAdvanced)
                        Functions.WriteLineToLogFile("Setting recording " + rprecId + " to streamID " + streamId);
                }
                //else if (action.StartWith("xml/startlivetv"))     //suggestion
                else if (action.StartsWith("xml/livetv"))
                {
                    //ToDo: Have to define an API that conforms to the rest of the API!
                    //

                    XMLresponse = "";
                    RecordingRequest newRR = null;
                    bool failedValidation = false;
                    string failedValidationReason = "";

                    string filenameId = "RMCLiveTV";

                    // GET SERVICE ID (Channel) and length
                    action = action.Replace("xml/livetv/", "");

                    string serviceId = action.Substring(0, action.IndexOf("uniqueandroid="));

                    action = action.Replace(serviceId, "");
                    action = action.Replace("uniqueandroid=", "");

                    string uniqueAndroidId = action.Substring(0, action.IndexOf("length="));

                    // DURATION
                    Int32 tryDuration;
                    Int32.TryParse(action.Substring(action.IndexOf("length=") + 7), out tryDuration);
                    DateTime tryStartTime = DateTime.Now;

                    //  Schedule manual recording
                    // DATE TIME

                    if ((tryDuration == 0) | (tryDuration > 720))
                    {
                        failedValidation = true;
                        failedValidationReason += "Invalid duration, must be between 1 and 720 minutes.<br>";
                    }

                    // In the unliklely event a file already exist with a certain random nr, try again:
                    bool randomFileAlreadyExists = false;
                    do
                    {
                        Random r = new Random();
                        filenameId = filenameId + uniqueAndroidId + r.Next(0, int.MaxValue);
                        string[] filePaths = null;
                        foreach (string recTVFolder in Settings.Default.RecordedTVFolders)
                        {
                            try
                            {
                                filePaths = Directory.GetFiles(recTVFolder, filenameId + "*.wtv");
                            }
                            catch (Exception e)
                            {
                                if (Settings.Default.DebugAdvanced)
                                    Functions.WriteLineToLogFile(
                                        "You probably have a path defined in Recorded TV (RP settings) that does not exist. Exception " +
                                        e.ToString());
                            }
                            if (filePaths.Length > 0)
                            {
                                randomFileAlreadyExists = true;
                                break;
                            }
                        }
                    } while (randomFileAlreadyExists);

                    // Create a new recording request
                    newRR = new RecordingRequest(tryStartTime.ToUniversalTime(), long.Parse(serviceId), tryDuration,
                                                 filenameId);

                    // Passed validation?
                    if (failedValidation)
                    {
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("FailedValidation");
                        txtResponse += "<p class='recorderror'>Error in recording request: " + failedValidationReason +
                                       "</p>";
                        XMLresponse = XMLHelper.Serialize<string>(txtResponse);
                    }
                    else
                    {
                        if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Did not fail Validation");

                        qsParams.Add("queueid", RecordingQueue.AddToQueue(newRR));
                        string txtRecSummary2;
                        if (RecordFromQueue(out txtRecSummary2))
                        {
                            bool found = false;
                            if (txtRecSummary2.Contains("The scheduling was successful"))
                            {
                                if (RecordFromQueueResult != null)
                                {
                                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile(RecordFromQueueResult);
                                    if (!RecordFromQueueResult.StartsWith("Recording not scheduled"))
                                    {
                                        if (Settings.Default.DebugAdvanced)
                                            Functions.WriteLineToLogFile("RecordFromQueue=True");
                                        int waittimeforfiletoappear = 20; // seconds
                                        //int waittimeforfiletoappear = 200; // seconds, testing whether setting needs high value for certain tv card like Ceton
                                        DateTime begin = DateTime.Now;
                                        string[] filepaths = null;
                                        int i = 0;
                                        do
                                        {
                                            foreach (string rectvfolder in Settings.Default.RecordedTVFolders)
                                            {
                                                if ((i % 1000 == 0) && (Settings.Default.DebugAdvanced))
                                                    Functions.WriteLineToLogFile("Checking " + rectvfolder + " for " +
                                                                                 filenameId + "*.wtv");
                                                i++;
                                                try
                                                {
                                                    filepaths = Directory.GetFiles(rectvfolder, filenameId + "*.wtv");
                                                }
                                                catch (Exception e)
                                                {
                                                    if (Settings.Default.DebugAdvanced)
                                                        Functions.WriteLineToLogFile(
                                                            "You probably have a path defined in Recorded TV (RP settings) that does not exist. Exception " +
                                                            e.ToString());
                                                }
                                                if (filepaths != null && filepaths.Length > 0)
                                                {
                                                    if (Settings.Default.DebugAdvanced)
                                                        Functions.WriteLineToLogFile("Found recording tv folder..." +
                                                                                     filepaths[0]);
                                                    break;
                                                }
                                            }

                                            if (filepaths != null && filepaths.Length > 0)
                                            {
                                                XMLresponse = XMLHelper.Serialize<string>(filepaths[0]);
                                                found = true;
                                                break;
                                            }

                                            if (DateTime.Compare(begin.AddSeconds(waittimeforfiletoappear), DateTime.Now) <
                                                0) //not found after 20 seconds
                                            {
                                                if (Settings.Default.DebugAdvanced)
                                                {
                                                    foreach (string rectvfolder in Settings.Default.RecordedTVFolders)
                                                    {
                                                        string[] filepaths2 = Directory.GetFiles(rectvfolder, "*.*");
                                                        foreach (string fp in filepaths2)
                                                        {
                                                            Functions.WriteLineToLogFile("However, this does exist :" + fp);
                                                        }
                                                    }
                                                }
                                                break;
                                            }
                                        } while (true);
                                    }
                                }
                                else
                                {
                                    if (Settings.Default.DebugAdvanced)
                                        Functions.WriteLineToLogFile("strange: RecordFromQueueResult is null");
                                }
                            }
                            if (!found)
                            {
                                List<string> errors = new List<string>();
                                if (Settings.Default.DebugAdvanced)
                                    Functions.WriteLineToLogFile("All tuners are busy somewhere in between now and " +
                                                                 tryDuration + " minutes from now");
                                errors.Add("All tuners are busy somewhere in between now and " + tryDuration +
                                           " minutes from now");
                                DateRange dateRange = new DateRange(DateTime.UtcNow,
                                                                    DateTime.UtcNow.AddMinutes(tryDuration));
                                if (Settings.Default.DebugAdvanced)
                                    Functions.WriteLineToLogFile("Going to find conflicting recordings");
                                List<RPRecording> recsToday = EPGManager.AllRecordingsRunningInTimeFrame(dateRange);
                                //List<RPRecording> oldLiveTVrecs = EPGManager.AllRecordingsContainsTitle("RMCLiveTV");
                                foreach (RPRecording rec in recsToday)
                                {
                                    if (Settings.Default.DebugAdvanced)
                                        Functions.WriteLineToLogFile("Recording: not found!, conflicting: " + rec.Title +
                                                                     " Are your recording folders in Remote Potato RP server (the general tab click on \"recorded TV\") and Media Center (tasks/setings/TV/Recorder) the same?");
                                    //if (rec.TVProgramme().StartTime <= (tryStartTime.Ticks + tryDuration * TimeSpan.TicksPerMinute))
                                    {
                                        errors.Add(rec.Id.ToString());
                                        errors.Add(rec.Title);
                                        errors.Add(rec.TVProgramme().TVService().Callsign);
                                        errors.Add(rec.TVProgramme().StartTime.ToString());
                                        errors.Add(rec.TVProgramme().StopTime.ToString());
                                        //errors.Add(rec.TVProgramme().Filename);
                                    }
                                }
                                if (Settings.Default.DebugAdvanced && errors.Count == 0)
                                    Functions.WriteLineToLogFile(
                                        "mmm, this is strange: no recordings in recording folder beginning with RMCLiveTV");
                                XMLresponse = XMLHelper.Serialize<List<string>>(errors);
                            }
                            //Could wait for event (for file to appear) instead...
                            //WTVfse = new FileSystemEventHandler(OnChanged);
                            //foreach (string location in Settings.Default.RecordedTVFolders)
                            //{
                            //    FileSystemWatcher w = new FileSystemWatcher();
                            //    w.Path = location;
                            //    /* Watch for changes in LastAccess and LastWrite times, and
                            //       the renaming of files or directories. */
                            //    w.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                            //       | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                            //    // Only watch filter.
                            //    w.Filter = filenameID + "*.wtv";

                            //    w.Created += WTVfse;
                            //    WTVwatcher.Add(w);
                            //}
                            //// Begin watching.
                            //foreach (FileSystemWatcher w in WTVwatcher)
                            //{
                            //    w.EnableRaisingEvents = true;
                            //}
                            //do { } while (!LiveTVScheduled);
                            //XMLresponse = XMLHelper.Serialize<string>(LiveTVFilename);
                        }
                        else
                        {
                            if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("RecordFromQueue=False");
                        }
                    }

                }
                else if (action.StartsWith("xml/mediastream/probe/byfilename"))
                {
                    string strFileName = HttpUtility.UrlDecode(PostObjects);
                    strFileName = strFileName.Trim();

                    if (action.StartsWith("xml/mediastream/probe/byfilename64"))
                        strFileName = Functions.DecodeFromBase64(strFileName);

                    List<AVStream> result;
                    if (strFileName.Length > 0)
                        result = StreamingManager.Default.ProbeFile(strFileName);
                    else
                        result = new List<AVStream>();

                    if (Settings.Default.DebugStreaming)
                        Functions.WriteLineToLogFile("Probed file " + strFileName + ": sending back details of " +
                                                     result.Count.ToString() + " AV streams.");

                    XMLresponse = XMLHelper.Serialize<List<AVStream>>(result);
                }
                else if (action.StartsWith("xml/mediastream/keepalive/"))
                {
                    string strStreamerID = action.Replace("xml/mediastream/keepalive/", "");
                    int streamerID;
                    string strmStatus;
                    if (int.TryParse(strStreamerID, out streamerID))
                    {
                        strmStatus = StreamingManager.Default.KeepStreamerAliveAndReturnStatus(streamerID);
                    }
                    else
                    {
                        Functions.WriteLineToLogFile("Warning: Could not parse streamer ID " + strStreamerID);
                        strmStatus = "invalid_id";
                    }

                    //XMLresponse = XMLHelper.XMLReponseWithOutputString(strmStatus);
                    XMLresponse = strmStatus;
                    if (Settings.Default.DebugAdvanced)
                        Functions.WriteLineToLogFile("MediaStreaming: GetStatus  (" + strStreamerID + "): " + strmStatus);
                }
                else if (action.StartsWith("xml/mediastream/stop/"))
                {
                    string strStreamerID = action.Replace("xml/mediastream/stop/", "");
                    int streamerID;
                    try
                    {
                        if (int.TryParse(strStreamerID, out streamerID))
                        {
                            if (!StreamingManager.Default.StopStreamer(streamerID, 5))
                                Functions.WriteLineToLogFile("Warning in stopping mediastream: Could not stop streamer ID " + strStreamerID);
                        }
                        else
                        {
                            Functions.WriteLineToLogFile("Warningin stopping mediastream2: Could not parse streamer ID " + strStreamerID);
                        }
                    }
                    catch (Exception ex)
                    {
                        Functions.WriteExceptionToLogFileIfAdvanced(ex);
                    }

                    XMLresponse = XMLHelper.XMLReponseWithOutputString("No Data");
                }
                else if (action.StartsWith("xml/stream/start"))
                {
                    WTVStreamingVideoResult streamResult;
                    WTVStreamingVideoRequest streamRq = XMLHelper.Deserialize<WTVStreamingVideoRequest>(PostObjects);
                    if (streamRq == null)
                    {
                        streamResult = new WTVStreamingVideoResult(DSStreamResultCodes.ErrorInStreamRequest);
                    }
                    else
                    {
                        try
                        {
                            streamResult = DSStreamingManager.Default.StartStreamer(streamRq);
                        }
                        catch (Exception e)
                        {
                            Functions.WriteLineToLogFile("Exception setting up streaming object:");
                            Functions.WriteExceptionToLogFile(e);
                            streamResult = new WTVStreamingVideoResult(DSStreamResultCodes.ErrorExceptionOccurred,
                                                                       e.Message);
                        }
                    }

                    XMLresponse = XMLHelper.Serialize<WTVStreamingVideoResult>(streamResult);
                }
                else if (action.StartsWith("xml/stream/stop"))
                {
                    XMLresponse = XMLHelper.XMLReponseWithOutputString("ERROR (DEPRECATED)");
                }
                else if (action.StartsWith("xml/picture/thumbnailzip/"))
                {
                    FileBrowseRequest fbrequest = FileBrowseRequest.FromXML(PostObjects);
                    if (fbrequest != null)
                    {
                        if (PictureExporter.SendThumbnailsAsZipFile(fbrequest, FatAttitude.ThumbnailSizes.Small,
                                                                    ref browserSender))
                            return;
                        else
                        {
                            if (Settings.Default.DebugAdvanced)
                                Functions.WriteLineToLogFile("Could not export zip of thumbnails.");
                            browserSender.Send404Page();
                        }
                    }
                    else
                    {
                        Functions.WriteLineToLogFile(
                            "ThumbnailZip: Error in requestprocessor- could not parse file browse request XML");
                    }
                }
                else if (action.StartsWith("xml/picture/get")) // matches /xml/picture/getrequest too
                {
                    string strSubAction = txtActionOriginalCase.Replace("xml/picture/", "");

                    // URL DECODE
                    strSubAction = HttpUtility.UrlDecode(strSubAction);

                    string strParams;
                    string strFileName = "";
                    bool fileNameAtEndOfUri = false;
                    bool fileNameAtEndOfUriIsBase64Encoded = false;
                    if (strSubAction.StartsWith("getwithfilename")) // GET FILENAME FROM URL
                    {
                        fileNameAtEndOfUri = true;

                        fileNameAtEndOfUriIsBase64Encoded = strSubAction.StartsWith("getwithfilename64");

                        if (fileNameAtEndOfUriIsBase64Encoded)
                            strParams = strSubAction.Replace("getwithfilename64/", "");
                        else
                            strParams = strSubAction.Replace("getwithfilename/", "");
                    }
                    else
                    // GET FILENAME FROM POST STRING
                    {
                        fileNameAtEndOfUri = false;
                        strFileName = PostObjects;
                        strParams = strSubAction.Replace("get/", "");
                    }

                    string[] Params = strParams.Split(new string[] { "/" }, StringSplitOptions.None);

                    bool haveFrameSizes = false;
                    int frameWidth = 0;
                    int frameHeight = 0;
                    if (Params.Count() > 1)
                    {
                        if ((int.TryParse(Params[0], out frameWidth) &&
                             int.TryParse(Params[1], out frameHeight)
                            ))
                            haveFrameSizes = ((frameWidth > 0) && (frameHeight > 0));
                        else
                            haveFrameSizes = false;
                    }
                    else
                        // Send full picture
                        haveFrameSizes = false;

                    if (!haveFrameSizes)
                        Functions.WriteLineToLogFile(
                            "Xml/Picture: invalid frame size (or none supplied): using full picture");

                    if (Settings.Default.DebugAdvanced)
                        Functions.WriteLineToLogFile("Exporting picture " + strFileName + " resized to frame " +
                                                     frameWidth.ToString() + "x" + frameHeight.ToString());

                    // Get Filename if not got already
                    // File name from Uri ?
                    if (fileNameAtEndOfUri)
                    {
                        if (fileNameAtEndOfUriIsBase64Encoded)
                        {
                            // Take final component and un-encode to produce filename
                            strFileName = Params[Params.Count() - 1];
                            strFileName = HttpUtility.UrlDecode(strFileName);
                            strFileName = Functions.DecodeFromBase64(strFileName);
                        }
                        else
                        {
                            // Reconstruct filename by putting /slashed/ components back together
                            for (int pCount = 2; pCount < Params.Count(); pCount++)
                            {
                                strFileName = strFileName + Params[pCount];
                                if (pCount < (Params.Count() - 1))
                                    strFileName = strFileName + "/";

                                strFileName = HttpUtility.UrlDecode(strFileName);
                            }
                        }

                    }

                    if (string.IsNullOrEmpty(strFileName))
                    {
                        Functions.WriteLineToLogFile("Xml/Picture : No filename specified in POST request, sending 404");
                        browserSender.Send404Page();
                        return;
                    }

                    // Send
                    if (haveFrameSizes)
                    {

                        byte[] resizedPictureData = new byte[] { };
                        if (ImageResizer.ResizePicture(strFileName, new Size(frameWidth, frameHeight),
                                                       out resizedPictureData, ImageFormat.Jpeg, false))
                        {
                            browserSender.SendDataToBrowser(Functions.MimeTypeForFileName(strFileName),
                                                            resizedPictureData);
                            return;
                        }
                        else
                        {
                            Functions.WriteLineToLogFile("Xml/Picture: Could not resize picture.");
                            browserSender.Send404Page();
                            return;
                        }
                    }
                    else // No frame sizes, send full image
                    {
                        browserSender.SendFileToBrowser(strFileName);
                        return;
                    }

                }
                else if (action.StartsWith("xml/music/framework"))
                {
                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.MusicFrameworkAsXML();
                        if (Settings.Default.DebugAdvanced)
                            Functions.WriteLineToLogFile("Exporting music framework blob via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/artist"))
                {
                    bool isBase64Encoded = (action.Contains("artist64/"));
                    action = action.Replace("artist64", "artist");
                    txtActionOriginalCase = txtActionOriginalCase.Replace("artist64", "artist");

                    string strArtistID = txtActionOriginalCase.Replace("xml/music/songs/artist/", "");
                    strArtistID = HttpUtility.UrlDecode(strArtistID);

                    if (isBase64Encoded)
                        strArtistID = Functions.DecodeFromBase64(strArtistID);

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.GetSongsForArtistAsXML(strArtistID);
                        if (Settings.Default.DebugAdvanced)
                            Functions.WriteLineToLogFile("Exporting songs for artist " + strArtistID +
                                                         " via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/album"))
                {
                    bool isBase64Encoded = (action.Contains("album64/"));
                    action = action.Replace("album64", "album");
                    txtActionOriginalCase = txtActionOriginalCase.Replace("album64", "album");

                    // USE case sensitive action string for match
                    string strAlbumID = txtActionOriginalCase.Replace("xml/music/songs/album/", "");
                    strAlbumID = HttpUtility.UrlDecode(strAlbumID);

                    if (isBase64Encoded)
                        strAlbumID = Functions.DecodeFromBase64(strAlbumID);

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.GetSongsForAlbumAsXML(strAlbumID);
                        if (Settings.Default.DebugAdvanced)
                            Functions.WriteLineToLogFile("Exporting songs for album " + strAlbumID +
                                                         " via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/genre"))
                {
                    bool isBase64Encoded = (action.Contains("genre64/"));
                    action = action.Replace("genre64", "genre");
                    txtActionOriginalCase = txtActionOriginalCase.Replace("genre64", "genre");

                    // USE case sensitive action string for match
                    string strGenreID = txtActionOriginalCase.Replace("xml/music/songs/genre/", "");
                    strGenreID = HttpUtility.UrlDecode(strGenreID);

                    if (isBase64Encoded)
                        strGenreID = Functions.DecodeFromBase64(strGenreID);

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.GetSongsForGenreAsXML(strGenreID);
                        if (Settings.Default.DebugAdvanced)
                            Functions.WriteLineToLogFile("Exporting songs for genre " + strGenreID +
                                                         " via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/all"))
                {

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.GetAllSongsAsXML();
                        if (Settings.Default.DebugAdvanced)
                            Functions.WriteLineToLogFile("Exporting all songs in library via XML web request...");
                    }
                }
                else if (action.StartsWith("xml/music/songs/checkexists"))
                {
                    bool isBase64Encoded = (action.Contains("checkexists64/"));
                    action = action.Replace("checkexists64", "checkexists");
                    txtActionOriginalCase = txtActionOriginalCase.Replace("checkexists64", "checkexists");

                    // USE case sensitive action string for match
                    string strSongID = txtActionOriginalCase.Replace("xml/music/songs/checkexists/", "");
                    strSongID = HttpUtility.UrlDecode(strSongID);

                    if (isBase64Encoded)
                        strSongID = Functions.DecodeFromBase64(strSongID);

                    using (WMPManager manager = new WMPManager())
                    {
                        XMLresponse = manager.WMPItemFileExistsAsXML(strSongID);
                        if (Settings.Default.DebugAdvanced)
                            Functions.WriteLineToLogFile("Exporting whether song exists... " + XMLresponse);
                    }
                }
                else
                {

                    Functions.WriteLineToLogFile("XML: Unknown request");
                    XMLresponse = "";
                }

                if (String.IsNullOrEmpty(XMLresponse))
                {
                    Functions.WriteLineToLogFile("NULL xmlresponse - nothing to send out to Silverlight client.  Sending error string.");
                    browserSender.SendStringToBrowser(XMLHelper.XMLReponseWithOutputString("No Data"));
                    return;
                }

                // Strip out any UTF-16 encoding
                XMLresponse = Functions.StripIllegalXmlCharacters(XMLresponse);

                // Zip up ?
                if (zipContent)
                {
                    Functions.logAPIoutputString(XMLresponse);
                    XMLresponse = ZipHelper.ZipString(XMLresponse);

                    if (Settings.Default.DebugServer)
                        Functions.WriteLineToLogFile("Zipped String to base64 string.  Length:" + XMLresponse.Length.ToString() + " characters. ");

                    browserSender.SendZipStringToBrowser(XMLresponse);
                }
                else
                    browserSender.SendXMLToBrowser(XMLresponse);
            }
            catch (Exception e)
            {
                string errorResponse = XMLHelper.XMLReponseWithOutputString("An error occurred - " + e.Message + " - check the debug log on the server.");

                Functions.WriteLineToLogFile("Exception while processing XML request:");
                Functions.WriteExceptionToLogFile(e);

                browserSender.SendXMLToBrowser(errorResponse);

            }
        }
        private void SendSegmentData(string txtAction, ref BrowserSender browserSender, int ID, bool sendToBrowser, bool doTranscode)
        {
            bool LatestFFmpeg = false;
            if (txtAction.StartsWith("seg!")) //first wait screen segment for NewLiveTV
            {
                txtAction = "seg-99999.ts";
            }
            else if (txtAction.StartsWith("seg$")) //first wait screen segment for latest FFMPEG
            {
                LatestFFmpeg = true;
                txtAction = "seg-99999.ts";
            }
            bool IsNewLiveTV = txtAction.StartsWith("liveseg");

            txtAction = txtAction.Replace(".ts", ""); // remove extension

            // Get segment number
            string strSegNumber;
            List<string> parts = txtAction.Split('-').ToList();
            if (parts.Count > 1)
                strSegNumber = parts[1];
            else
            {
                if (!sendToBrowser) return;
                browserSender.Send404Page();
                return;
            }

            int iSegNumber = 0;
            if (!int.TryParse(strSegNumber, out iSegNumber))
            {
                if (!sendToBrowser) return;
                browserSender.Send404Page();
                return;
            }

            int iIndexNumber = 0;
            //if (IsNewLiveTV)
            //{
            //    iIndexNumber = SegmentTabel.getIndex(""+ID, iSegNumber);
            //    iSegNumber = SegmentTabel.getSegment(iIndexNumber, iSegNumber);
            //}

            byte[] TSdata = new byte[] { };
            string txtError = "";
            if (LatestFFmpeg && strSegNumber.Equals("99999"))
            {
                StreamingManager.Default.SegmentFromStreamer(iIndexNumber, ID, iSegNumber, ref TSdata, ref txtError, doTranscode); //start up the runners
                Functions.WriteLineToLogFileIfSetting(Settings.Default.DebugStreaming, "Sending please wait screen");
                Segment s = new Segment();

                string FN = Functions.ToolkitFolder + "\\pleasewait.ts";

                if (!sendToBrowser) return;
                s.Data = FileToByteArray(FN);

                browserSender.SendDataToBrowser("video/mp2t", s.Data);
            }
            else
            {
                if (IsNewLiveTV && strSegNumber.Equals("99999"))
                {
                    Functions.WriteLineToLogFileIfSetting(Settings.Default.DebugStreaming,
                                                          "Could not get streaming segment number " + strSegNumber +
                                                          "but live tv, so continuing");
                    if (!sendToBrowser) return;
            //                    browserSender.Send404Page();
                    Functions.WriteLineToLogFileIfSetting(Settings.Default.DebugStreaming, "Sending please wait screen");
                    Segment s = new Segment();

                    string FN = Functions.ToolkitFolder + "\\pleasewait.ts";

                    s.Data = FileToByteArray(FN);

                    browserSender.SendDataToBrowser("video/mp2t", s.Data);
                }
                else
                    if (StreamingManager.Default.SegmentFromStreamer(iIndexNumber, ID, iSegNumber, ref TSdata, ref txtError, doTranscode))
                    {
                        {
                            if (!sendToBrowser) return;
                            browserSender.SendDataToBrowser("video/mp2t", TSdata);
                        }

                        return;
                    }
                    else
                    {
                        Functions.WriteLineToLogFileIfSetting(Settings.Default.DebugStreaming, "Could not get streaming segment number " + strSegNumber + ":" + txtError);
                        if (!sendToBrowser) return;
                        browserSender.Send404Page();
                    }
            }
        }
        private void ProcessHTTPLSURL(string txtAction, ref BrowserSender browserSender)
        {
            Functions.WriteLineToLogFileIfSetting(Settings.Default.DebugStreaming, "ProcesssHTTP: " + txtAction);
            // GET STREAMER ID
            int ID;
            if (txtAction.StartsWith("httplivestream/"))
            {
                txtAction = txtAction.Replace("httplivestream/", "");

                int nextSlash = txtAction.IndexOf("/");
                if (nextSlash == -1)
                {
                    browserSender.Send404Page();
                    return;
                }

                string strMediaStreamerID = txtAction.Substring(0, nextSlash);

                if (!int.TryParse(strMediaStreamerID, out ID))
                {
                    browserSender.Send404Page();
                    return;
                }

                // Make txtAction the final portion
                txtAction = txtAction.Replace(ID.ToString() + "/", "");
            }
            else
            {
                browserSender.Send404Page();
                return;
            }

            //if (txtAction.EndsWith("index2.m3u8"))
            //{
            //    string workingFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "RemotePotato");
            //    workingFolderPath = Path.Combine(workingFolderPath + "\\static\\mediastreams\\", ID.ToString());
            //    if (!Directory.Exists(workingFolderPath)) Directory.CreateDirectory(workingFolderPath);
            //    string filePath2 = workingFolderPath + "\\index2.m3u8";
            //    string indexFile = "#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-MEDIA-SEQUENCE:0\n#EXT-X-ALLOW-CACHE:YES\n#EXT-X-TARGETDURATION:5\n#EXTINF:4,\nsegment-0.ts";
            //    if (File.Exists(filePath2))
            //    {
            //        StreamReader streamReader = new StreamReader(new FileStream(filePath2, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
            //        indexFile = streamReader.ReadToEnd();
            //        streamReader.Close();
            //    }

            //        browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");

            //    return;

            //}
            //else
            if (txtAction.EndsWith("livetv.m3u8"))
            {
                string workingFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "RemotePotato");
                workingFolderPath = Path.Combine(workingFolderPath + "\\static\\mediastreams\\", ID.ToString());
                if (!Directory.Exists(workingFolderPath)) Directory.CreateDirectory(workingFolderPath);
                //string filePathNewFFMPeg = workingFolderPath + "\\index2.m3u8";
                string filePathNewLiveTV = workingFolderPath + "\\livetvtemp0.m3u8";
                string indexFile = "";

                {
                    if (File.Exists(filePathNewLiveTV)) // NewLiveTV:  m3u8 indexfile exists
                    {
                        indexFile = StreamingManager.Default.IndexFileForStreamer(ID, false);
                        browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
                        return;

                        //old code:
                        StreamReader streamReader = new StreamReader(new FileStream(filePathNewLiveTV, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
                        indexFile = streamReader.ReadToEnd();
                        streamReader.Close();
                    }
                    else if (txtAction.EndsWith("livetv.m3u8")) // new live TV
                    {
                        // Yeah, you can start me up, start me up, display waiting screen
                        StringBuilder sbindexfile = new StringBuilder(1000);

                        sbindexfile.AppendLine("#EXTM3U");
                        sbindexfile.AppendLine("#EXT-X-TARGETDURATION:" + 1);
                        sbindexfile.AppendLine("#EXT-X-ALLOWCACHE:1"); // allow client to cache files
                        //                        sbindexfile.AppendLine("#EXTINF:10,");
                        //                        sbindexfile.AppendLine("seg-0.ts"); //seg-0 does not exist this actually kicks off the ffmpeg runner, does not work
                        sbindexfile.AppendLine("#EXTINF:" + 1 + ",");
                        sbindexfile.AppendLine("seg!-99999.ts");
                        //                        sbindexfile.AppendLine("#EXTINF:1,");
                        //                        sbindexfile.AppendLine("seg-2.ts");
                        //                    sbindexfile.AppendLine("#ext-x-endlist");

                        indexFile = sbindexfile.ToString();

                    }

                    browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");

                    if (false)
                    {
                        //livetv.m3u8 might be written to and for a moment not exist so better is:
                        //http://stackoverflow.com/questions/4238345/asynchronously-wait-for-taskt-to-complete-with-timeout
                        // Your scheduler
                        TaskScheduler scheduler = TaskScheduler.Default;

                        BrowserSender browserSender2 = browserSender;

                        Task nonblockingTask = new Task(() =>
                        {
                            CancellationTokenSource source = new CancellationTokenSource();

                            Task t1 = new Task(() =>
                            {
                                while (true)
                                {
                                    // Do something
                                    if (File.Exists(filePathNewLiveTV))
                                    {
                                        File.Delete(filePathNewLiveTV + "b");
                                        File.Copy(filePathNewLiveTV, filePathNewLiveTV + "b");
                                        StreamReader streamReader2 = new StreamReader(filePathNewLiveTV + "b");
                                        indexFile = streamReader2.ReadToEnd();
                                        streamReader2.Close();
                                    }
                                    if (source.IsCancellationRequested)
                                        break;
                                }
                            }, source.Token);

                            t1.Start(scheduler);

                            // Wait for task 1
                            bool firstTimeout = t1.Wait(5000);

                            if (!firstTimeout)
                            {
                                // If it hasn't finished at first timeout display message
                                if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("livetv.m3u8 not generated after 5 seconds");
                                bool secondTimeout = t1.Wait(5000);

                                if (!secondTimeout)
                                {
                                    source.Cancel();
                                    if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("livetv.m3u8 not generated after 10 seconds, Operation stopped!");
                                }
                            }

                            browserSender2.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");

                        });

                        nonblockingTask.Start();
                    }

                }

                return;
            }
            else
                if (txtAction.EndsWith("m3u8"))
                {
                    string indexFile = StreamingManager.Default.IndexFileForStreamer(ID, false);
                    browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
                    return;
                }
                else
                    if (txtAction.EndsWith("playtranscoded"))
                    {
                        string indexFile = StreamingManager.Default.IndexFileForStreamer(ID, true);
                        browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
                        return;
                    }

                    else //for windows 8 app store support (metro)
                        if (txtAction.EndsWith("bat"))
                        {
                            string indexFile = @"c:\ffmpeg\ffplay.exe http://" + Request.RemoteEndPoint.Address.ToString() + ":" + Request.LocalEndPoint.Port + "/httplivestream/" + ID + "/index.m3u8";
                            browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
                            return;
                        }

            if (txtAction.EndsWith("onlytranscode"))
            {
                browserSender.Send404Page();
                string indexFile = StreamingManager.Default.IndexFileForStreamer(ID, true);
                List<string> lines = indexFile.Split(Environment.NewLine.ToCharArray()).ToList();
                MediaStreamer ms = StreamingManager.Default.GetStreamerByID(ID);
                foreach (string line in lines)
                {
                    if (line.StartsWith("seg"))
                    {
                        SendSegmentData(line, ref browserSender, ID, false, true);
                        ms.lastContactAtTime = DateTime.Now; //This counts as contact from the server
                    }
                }
                //now move the data to a safe place, otherwise the janitor will clean up at its convenience
                StreamingManager.Default.MoveSegmentData(ID);
                return;
            }

            if (txtAction.StartsWith("segbackground"))
            {
                txtAction = txtAction.Replace("background", "");
                SendSegmentData(txtAction, ref browserSender, ID, true, false);
                return;
            }
            else if (txtAction.StartsWith("seg") || txtAction.StartsWith("liveseg"))
            {
                SendSegmentData(txtAction, ref browserSender, ID, true, true);
                return;
            }
        }
Exemple #14
0
        public static bool SendThumbnailsAsZipFile(FileBrowseRequest request, ThumbnailSizes thumbSize, ref BrowserSender bSender)
        {
            // We'll need a shell helper
            FatAttitude.ShellHelper sh = new FatAttitude.ShellHelper();

            // Set up temp directory
            string tempFolderName = Path.GetRandomFileName();
            string tempPath       = Path.Combine(Functions.ZipTempFolder, tempFolderName);

            Directory.CreateDirectory(tempPath);

            // Go through the thumbnails (filter already applied, so these are pic files)
            FileBrowseResult fbResult = FileBrowseExporter.BrowsePath(request.FullPath, request.Filters);

            // Any files?
            if (fbResult.Files.Count < 1)
            {
                return(false);
            }

            int           SkipCounter   = 0;
            int           OutputCounter = 0;
            List <string> outputFiles   = new List <string>();

            foreach (BrowseItem bItem in fbResult.Files)
            {
                // Skip items before batch
                if (request.ThumbnailsLimitToBatch)
                {
                    if (request.ThumbnailsBatch > 0)
                    {
                        if (SkipCounter++ < (request.ThumbnailsBatchSize * request.ThumbnailsBatch))
                        {
                            continue;
                        }
                    }
                }

                string strFullPath = Path.Combine(fbResult.BaseDirectory, bItem.Name);
                string strLog      = ""; // ignore log
                Bitmap bmp         = sh.ThumbnailForFile(strFullPath, thumbSize, ref strLog);

                string fnSansExtension       = Path.GetFileNameWithoutExtension(bItem.Name);
                string strOutputFileFullPath = Path.Combine(tempPath, (fnSansExtension + "_thumb.jpg"));
                bmp.Save(strOutputFileFullPath, ImageFormat.Jpeg);

                outputFiles.Add(strOutputFileFullPath);

                // End of batch?
                if (request.ThumbnailsLimitToBatch)
                {
                    if (OutputCounter++ >= request.ThumbnailsBatchSize)
                    {
                        break;
                    }
                }
            }

            // Now zip up the files
            string strOutputZipFile = Path.Combine(Functions.ZipTempFolder, (Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".zip"));
            bool   result           = ZipHelper.CreateZipFileFromFiles(outputFiles, strOutputZipFile);

            // And send the zip file to the browser
            result &= (bSender.SendFileToBrowser(strOutputZipFile));
            File.Delete(strOutputZipFile);
            Directory.Delete(tempPath, true);

            return(result);
        }
        private void SendRemoteControlCommandDesktop(ref BrowserSender bs)
        {
            string txtHTML = FileCache.ReadSkinTextFile("page_remote_command.htm");

            // CHECK PROCESS IS RUNNING AND FOCUSSED?
            bool doCommand = (qsParams.HasParameter("command"));
            string strCommand = "";
            string strResponse = "No Command";

            if (doCommand)
            {
                strCommand = qsParams["command"];
                if (strCommand == "none")
                {
                    strResponse = "Click a button.";
                }
                else
                {
                    string strResult = IRCommunicator.Default.SendIRCommand(strCommand); // No return (Async)
                    if (strResult == "OK")
                        strResponse = "Sent " + strCommand + " OK";
                    else
                    {
                        if (strResult == "HELPER_NOT_RUNNING")
                            strResult = "The IR Helper application is not running on the server - check your settings.";

                        strResponse = "Not OK: " + strResult;
                    }
                }
            }

            // Replace Caption within iFrame with response
            txtHTML = txtHTML.Replace("**REMOTE_RESPONSE**", strResponse);

            // Send entire page to browser.
            bs.SendNormalHTMLPageToBrowser(txtHTML);
        }
        private bool SendRemoteControlCommandMobile(ref BrowserSender bs)
        {
            // CHECK PROCESS IS RUNNING AND FOCUSSED?
            bool doCommand = (qsParams.HasParameter("command"));
            string strCommand = "";
            string strResponse = "No Command";

            if (doCommand)
            {
                strCommand = qsParams["command"];
                if (strCommand == "none") // Default page
                {
                    // First command - always displayed within an iFrame, even on iPhone
                    string txtHTML = FileCache.ReadSkinTextFile("page_remote_command.htm");

                    strResponse = "Click a button.";

                    // Replace Caption within iFrame with response
                    txtHTML = txtHTML.Replace("**REMOTE_RESPONSE**", strResponse);

                    // Send entire page to browser.
                    bs.SendNormalHTMLPageToBrowser(txtHTML);

                    return true;
                }
                else
                {
                    string strResult = IRCommunicator.Default.SendIRCommand(strCommand); // No return (Async)
                    if (strResult == "OK")
                        strResponse = "Sent " + strCommand + " OK";
                    else
                    {
                        if (strResult == "HELPER_NOT_RUNNING")
                            strResult = "The IR Helper application is not running on the server - check your settings.";

                        strResponse = "Not OK: " + strResult;
                    }
                }
            }

            // iPhone workaround - send the whole page again. (opens it in a new window)
            txtResponse += FileCache.ReadSkinTextFile("page_remote.htm");
            txtResponse += "<br />" + strResponse;
            return false;
        }
        bool GetPicturesFolderAsZip(ref BrowserSender bSender)
        {
            string path;
            if (qsParams.HasParameter("PATH"))
            {
                string qsFN = qsParams["PATH"];
                path = HttpUtility.UrlDecode(qsFN);
                path = Functions.DecodeFromBase64(path, Encoding.UTF8);  // http uses UTF8 encoding

                FileBrowseResult fbr = FileBrowseExporter.BrowsePath(path, FileBrowseExporter.MediaFileTypes.Image);
                FileBrowseExporter.SendFolderFilesAsZipFile(fbr, ref bSender);
            }
            else
            {
                bSender.Send404Page();
            }

            return true;
        }
        private bool ViewPicture(ref BrowserSender bSender, ref bool sentCompletePage)
        {
            string txtOutput = FileCache.ReadSkinTextFile("page_viewpicture.htm");

            StringBuilder sbHTML = new StringBuilder(100);

            string FN = "";
            string strSize = "";
            bool shouldDownload = false;
            if (
                (qsParams.HasParameter("FN")) && (qsParams.HasParameter("SIZE"))
                )
            {
                string qsFN = qsParams["FN"];
                FN = HttpUtility.UrlDecode(qsFN);
                FN = Functions.DecodeFromBase64(FN, Encoding.UTF8);  // http uses UTF8 encoding

                txtPageTitle = Path.GetFileNameWithoutExtension(FN);

                strSize = qsParams["SIZE"];

                shouldDownload = (qsParams.HasParameter("DOWNLOAD"));
            }
            else
            {
                bSender.Send404Page();
                sentCompletePage = true;
            }

            // Thumbnail?
            string imgSrc;
            if (!strSize.Equals("full"))
            {
                // Assemble path to file
                imgSrc = "getfilethumbnail64?filename=" + qsParams["FN"] + "&size=" + strSize;

                HTMLImage image = new HTMLImage(imgSrc, "picturelibraryviewedpicture");

                // Link
                string strLinkToFullImage = "viewpic?FN=" + qsParams["FN"] + "&size=full";
                HTMLLink lnk = new HTMLLink(strLinkToFullImage, image.ToString());

                // Commit to form
                sbHTML.Append(lnk.ToString());

                sbHTML.Append("<br /><br />");

                HTMLLink fullLink = new HTMLLink(strLinkToFullImage, "View original size");
                sbHTML.Append(fullLink.ToString());

                sbHTML.Append("&nbsp;&nbsp;|&nbsp;&nbsp;");

                fullLink = new HTMLLink(strLinkToFullImage + "&download=yes", "Download");
                sbHTML.Append(fullLink.ToString());
            }
            else
            {
                sentCompletePage = true;
                bSender.SendFileToBrowser(FN, false, false, shouldDownload);
            }

            txtOutput = txtOutput.Replace("**LIBRARYTABLE**", sbHTML.ToString());

            txtResponse += txtOutput;

            return true;
        }
        private void GetRecTVThumbnail(ref BrowserSender browserSender, bool isBase64Encoded)
        {
            // Any parameters?
            bool validated = true;

            validated &= qsParams.HasParameter("filename");

            if (!validated)
            {
                bool foo = browserSender.Send404Page();
                return;
            }

            // This can fail with non-ASCII
            string qsFN = qsParams["filename"];
            string fileName = HttpUtility.UrlDecode( qsFN );
            if (isBase64Encoded)
                fileName = Functions.DecodeFromBase64(fileName, Encoding.UTF8);  // http uses UTF8 encoding

            // Find file?
            string filePath = "";
            bool foundFilePath = false;
            if (File.Exists(fileName))  // Fully qualified path was passed
            {
                foundFilePath = true;
                filePath = fileName;
            }
            else
            {
                foreach (string recTVFolder in Settings.Default.RecordedTVFolders)
                {
                    filePath = Path.Combine(recTVFolder, fileName);  // If just a filename is provided, then this appends it to the default record path from the registry
                    if (File.Exists(filePath))
                    {
                        foundFilePath = true;
                        break;
                    }
                }
            }

            if (! foundFilePath)
            {
                bool foo = browserSender.Send404Page();
                return;
            }

            SendFileThumbnail(filePath, FatAttitude.ThumbnailSizes.Medium, ref browserSender);
        }
        private void GetSongThumbnail(ref BrowserSender browserSender, bool isBase64Encoded)
        {
            // Any parameters?
            bool validated = true;
            validated &= qsParams.HasParameter("id");
            validated &= qsParams.HasParameter("size");

            if (!validated)
            {
                bool foo = browserSender.Send404Page();
                return;
            }

            string itemID = HttpUtility.UrlDecode(qsParams["id"]);
            if (isBase64Encoded)
                itemID = Functions.DecodeFromBase64(itemID);

            string size = qsParams["size"];
            WMPManager.Thumbnail_Sizes tSize = (WMPManager.Thumbnail_Sizes)Enum.Parse(typeof(WMPManager.Thumbnail_Sizes), size, true);

            using (WMPManager picManager = new WMPManager())
            {
                string MimeType = "";
                byte[] picBytes = picManager.ThumbnailForWMPItemAsByte("TrackingID", itemID, true, tSize, out MimeType);
                if ((picBytes == null) || (picBytes.Length < 1))
                    browserSender.Send404Page();
                else
                    browserSender.SendDataToBrowser(MimeType, picBytes);
            }
        }
Exemple #21
0
        private void ProcessHTTPLSURL(string txtAction, ref BrowserSender browserSender)
        {
            Functions.WriteLineToLogFileIfSetting(Settings.Default.DebugStreaming, "ProcesssHTTP: " + txtAction);
            // GET STREAMER ID
            int ID;
            if (txtAction.StartsWith("httplivestream/"))
            {
                txtAction = txtAction.Replace("httplivestream/", "");

                int nextSlash = txtAction.IndexOf("/");
                if (nextSlash == -1)
                {
                    browserSender.Send404Page();
                    return;
                }

                string strMediaStreamerID = txtAction.Substring(0, nextSlash);

                if (!int.TryParse(strMediaStreamerID, out ID))
                {
                    browserSender.Send404Page();
                    return;
                }

                // Make txtAction the final portion
                txtAction = txtAction.Replace(ID.ToString() + "/", "");
            }
            else
            {
                browserSender.Send404Page();
                return;
            }

            //if (txtAction.EndsWith("index2.m3u8"))
            //{
            //    string workingFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "RemotePotato");
            //    workingFolderPath = Path.Combine(workingFolderPath + "\\static\\mediastreams\\", ID.ToString());
            //    if (!Directory.Exists(workingFolderPath)) Directory.CreateDirectory(workingFolderPath);
            //    string filePath2 = workingFolderPath + "\\index2.m3u8";
            //    string indexFile = "#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-MEDIA-SEQUENCE:0\n#EXT-X-ALLOW-CACHE:YES\n#EXT-X-TARGETDURATION:5\n#EXTINF:4,\nsegment-0.ts";
            //    if (File.Exists(filePath2))
            //    {
            //        StreamReader streamReader = new StreamReader(new FileStream(filePath2, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
            //        indexFile = streamReader.ReadToEnd();
            //        streamReader.Close();
            //    }

            //        browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");

            //    return;

            //}
            //else
            if (txtAction.Contains("isshellcmdrunning"))
            {
                MediaStreamer ms = StreamingManager.Default.GetStreamerByID(ID);
                XMLresponse = (!ms.isPaused).ToString();
                browserSender.SendXMLToBrowser(XMLresponse);
                return;
            }
            if (txtAction.EndsWith("livetv.m3u8"))
            {
                string indexFile = StreamingManager.Default.IndexFileForStreamer(ID, false, 0);
                browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
                return;
            }
            else
                if (txtAction.EndsWith("m3u8"))
                {
                    int segmnr = StreamingManager.Default.GetTimeForIndexFile(ID);
                    string indexFile = StreamingManager.Default.IndexFileForStreamer(ID, false, segmnr);
                    browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
                    //browserSender.SendStringToBrowser(indexFile, "application/x-mpegURL");
                    return;
                }
                else
                    if (txtAction.EndsWith("playtranscoded.m3u8"))
                    {
                        int segmnr = StreamingManager.Default.GetTimeForIndexFile(ID);
                        string indexFile = StreamingManager.Default.IndexFileForStreamer(ID, true, segmnr);
                        browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
                        return;
                    }

            //else //for windows 8 app store support (metro)
            //    if (txtAction.EndsWith("streamlive.bat"))
            //    {
            //        string indexFile = @"c:\ffmpeg\ffplay.exe http://" + Request.RemoteEndPoint.Address.ToString() + ":" + Request.LocalEndPoint.Port + "/httplivestream/" + ID + "/livetv.m3u8";
            //        browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
            //        return;
            //    }
            //    else //for windows 8 app store support (metro)
            //        if (txtAction.EndsWith("stream.bat"))
            //        {
            //            string indexFile = @"c:\ffmpeg\ffplay.exe http://" + Request.RemoteEndPoint.Address.ToString() + ":" + Request.LocalEndPoint.Port + "/httplivestream/" + ID + "/index.m3u8";
            //            browserSender.SendStringToBrowser(indexFile, "application/vnd.apple.mpegurl");
            //            return;
            //        }

            if (txtAction.EndsWith("onlytranscode"))
            {
                browserSender.Send404Page();
                StreamingManager.Default.DeleteBackgroundSegmentData(ID);
                string indexFile = StreamingManager.Default.IndexFileForStreamer(ID, true, 0);
                List<string> lines = indexFile.Split(Environment.NewLine.ToCharArray()).ToList();
                MediaStreamer ms = StreamingManager.Default.GetStreamerByID(ID);
                string regel = "";
                foreach (string line in lines)
                {
                    if (line.StartsWith("seg"))//segbackground
                    {
                        regel = line;
                        SendSegmentData(line, ref browserSender, ID, false, true);
                        ms.lastContactAtTime = DateTime.Now; //This counts as contact from the server
                    }
                }

                string streamPath = Functions.AppDataFolder + "\\static\\mediastreams\\" + ID + "\\";
                string segfile = streamPath + regel.Replace("background", "ment");
                waitForCopyToComplete(segfile);
                //sometimes an extra segment is generated 1 more than in  the index.m3u8 file, this has also to be waited for completely copied before to be moved.
                int segmentNr = 0;
                Int32.TryParse(regel.Replace("segbackground-", "").Replace(".ts", ""), out segmentNr);
                string segmenttotest = "segbackground-" + (segmentNr + 1) + ".ts";
                segfile = streamPath + segmenttotest.Replace("background", "ment");
                if (File.Exists(segfile))
                    waitForCopyToComplete(segfile);

                //now move the data to a safe place, otherwise the janitor will clean up at its convenience
                StreamingManager.Default.MoveSegmentData(ID);
                return;
            }

            if (txtAction.StartsWith("segbackground"))
            {
                txtAction = txtAction.Replace("background", "");
                SendSegmentData(txtAction, ref browserSender, ID, true, false);
                return;
            }
            else if (txtAction.StartsWith("seg") || txtAction.StartsWith("liveseg"))
            {
                SendSegmentData(txtAction, ref browserSender, ID, true, true);
                return;
            }
        }