/// <summary>
        /// Checks to ensure that all the parts of the file path are legal, and then
        /// reassembles them into the physical path to the file on the local disk.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="container"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        public static string GetFilePath(string type, string container, string relativeDirectory, string file)
        {
            if (AutoUpdateManager.IsFilenameOrDirectorySafe(type) == false)
            {
                throw new Exception("Invalid type.");
            }

            if (AutoUpdateManager.IsFilenameOrDirectorySafe(container) == false)
            {
                throw new Exception("Invalid container.");
            }

            // The relative directory can contain \, but it shouldn't contain .. ever!
            if (relativeDirectory.StartsWith("\\") || relativeDirectory.StartsWith("//") || relativeDirectory.Contains(".."))
            {
                throw new Exception("Invalid relative directory.");
            }

            if (AutoUpdateManager.IsFilenameOrDirectorySafe(file) == false)
            {
                throw new Exception("Invalid filename.");
            }

            string containerPath = Path.Combine(type, container);
            string relativePath  = containerPath;

            if (String.IsNullOrEmpty(relativeDirectory) == false)
            {
                relativePath = Path.Combine(containerPath, relativeDirectory);
            }

            string filePath = Path.Combine(relativePath, file);

            return(filePath);
        }
        public static bool TryGetPublicationFiles(int publicationID, out Dictionary <string, UpdateItem> filesInPublication, out List <FileCollision> fileCollisions)
        {
            filesInPublication = new Dictionary <string, UpdateItem>();
            fileCollisions     = new List <FileCollision>();

            foreach (FileInfo packageInfo in AutoUpdateManager.GetPackages())
            {
                if (AutoUpdateManager.IsPackageExcludedFromPublication(publicationID, packageInfo.Name) == false)
                {
                    foreach (UpdateItem fileInfo in AutoUpdateManager.GetFilesInUpdatePackage(packageInfo.Name))
                    {
                        if (fileInfo.IsIncluded == false)
                        {
                            continue;
                        }

                        string relativeFilePath = Path.Combine(fileInfo.RelativeDirectory, fileInfo.Name);

                        if (filesInPublication.ContainsKey(relativeFilePath) == true)
                        {
                            FileCollision fileCollision = new FileCollision();
                            fileCollision.CollidingFile = Path.Combine(packageInfo.Name, relativeFilePath);
                            fileCollision.PreferredFile = Path.Combine(filesInPublication[relativeFilePath].PackageName, relativeFilePath);

                            fileCollisions.Add(fileCollision);

                            continue;
                        }
                        else
                        {
                            filesInPublication.Add(relativeFilePath, fileInfo);
                        }
                    }
                }
            }

            return(true);
        }
        public static bool DeployPublication(int publicationID)
        {
            using (var db = new DataAccess.CSSDataContext())
            {
                DataAccess.Lobby lobby = db.Lobbies.FirstOrDefault(p => p.Id == publicationID);

                if (lobby == null)
                {
                    throw new Exception("Couldn't get lobby for publication id: " + publicationID);
                }

                if (Directory.Exists(lobby.BasePath) == false)
                {
                    Directory.CreateDirectory(lobby.BasePath);
                }

                List <FileCollision>            fileCollisions     = new List <FileCollision>();
                Dictionary <string, UpdateItem> filesInPublication = new Dictionary <string, UpdateItem>();

                // Remove physical files from the directory. Not doing this with a recursive directory delete because
                // I don't want someone to put in a bad path into the content manager web UI, and then drill the
                // whole drive.
                foreach (DataAccess.AutoUpdateFile_Lobby file in db.AutoUpdateFile_Lobbies.Where(p => p.LobbyId == lobby.Id))
                {
                    string fileToDelete = Path.Combine(lobby.BasePath, file.AutoUpdateFile.Filename);

                    if (File.Exists(fileToDelete) == true)
                    {
                        File.Delete(fileToDelete);
                    }
                }

                // Clear all files for the lobby.
                db.AutoUpdateFile_Lobbies.DeleteAllOnSubmit(db.AutoUpdateFile_Lobbies.Where(p => p.LobbyId == lobby.Id));
                db.SubmitChanges();

                if (AutoUpdateManager.TryGetPublicationFiles(publicationID, out filesInPublication, out fileCollisions) == true)
                {
                    foreach (UpdateItem fileInfo in filesInPublication.Values)
                    {
                        string checksum;
                        using (SHA1 hasher = SHA1.Create())
                        {
                            using (FileStream fs = new FileStream(fileInfo.FileInfo.FullName, FileMode.Open, FileAccess.Read))
                                checksum = Convert.ToBase64String(hasher.ComputeHash(fs));
                        }

                        string          fileVersion     = String.Empty;
                        FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(fileInfo.FileInfo.FullName);

                        // Doing it this way, as sometimes there is product or vendor info at the
                        // end of the file version spec. ProductVersion may not correctly reflect the actual
                        // version of the file all the time.
                        if (fileVersionInfo != null && fileVersionInfo.FileVersion != null)
                        {
                            fileVersion = String.Format("{0}.{1}.{2}.{3}", fileVersionInfo.FileMajorPart, fileVersionInfo.FileMinorPart, fileVersionInfo.FileBuildPart, fileVersionInfo.FilePrivatePart);
                        }

                        string relativeFilePath = Path.Combine(fileInfo.RelativeDirectory, fileInfo.Name);

                        DataAccess.AutoUpdateFile autoUpdateFile = db.AutoUpdateFiles.FirstOrDefault(p => p.Filename == relativeFilePath);

                        if (autoUpdateFile == null)
                        {
                            autoUpdateFile = new Allegiance.CommunitySecuritySystem.DataAccess.AutoUpdateFile()
                            {
                                Filename    = relativeFilePath,
                                IsProtected = fileInfo.IsProtected
                            };

                            db.AutoUpdateFiles.InsertOnSubmit(autoUpdateFile);
                            db.SubmitChanges();
                        }
                        else
                        {
                            if (autoUpdateFile.IsProtected != fileInfo.IsProtected)
                            {
                                autoUpdateFile.IsProtected = fileInfo.IsProtected;
                                db.SubmitChanges();
                            }
                        }

                        DataAccess.AutoUpdateFile_Lobby lobbyFile = db.AutoUpdateFile_Lobbies.FirstOrDefault(p => p.AutoUpdateFileId == autoUpdateFile.Id && p.LobbyId == lobby.Id);

                        if (lobbyFile == null)
                        {
                            lobbyFile = new Allegiance.CommunitySecuritySystem.DataAccess.AutoUpdateFile_Lobby()
                            {
                                AutoUpdateFileId = autoUpdateFile.Id,
                                CurrentVersion   = fileVersion,
                                DateCreated      = fileInfo.FileInfo.CreationTime,
                                DateModified     = fileInfo.FileInfo.LastWriteTime,
                                ValidChecksum    = checksum,
                                LobbyId          = lobby.Id
                            };

                            db.AutoUpdateFile_Lobbies.InsertOnSubmit(lobbyFile);
                            db.SubmitChanges();
                        }

                        string targetFilePath      = Path.Combine(lobby.BasePath, relativeFilePath);
                        string targetFileDirectory = Path.GetDirectoryName(targetFilePath);
                        if (Directory.Exists(targetFileDirectory) == false)
                        {
                            Directory.CreateDirectory(targetFileDirectory);
                        }

                        File.Copy(fileInfo.FileInfo.FullName, targetFilePath, true);
                    }

                    GenerateFileListForAutoUpdate(lobby);
                }

                // Clean up any unused AutoUpdateFile records.
                //db.AutoUpdateFiles.DeleteAllOnSubmit(db.AutoUpdateFiles.Where(p => db.AutoUpdateFile_Lobbies.Select(r => r.AutoUpdateFileId).Contains(p.Id) == false));
                //db.SubmitChanges();
            }

            return(true);
        }