private bool EnsureAvailableName(ref string destinationDisplayName, Folder parent, bool creatingDocument, bool newVersion = false)
        {
            const int MaxIterations = 10;

            string originalDisplayName = destinationDisplayName;
            string name = destinationDisplayName.ToUpperInvariant();

            if (NameConflicts(parent, name, creatingDocument, newVersion))
            {
                int iteration = 0;

                do
                {
                    if (iteration == MaxIterations)
                    {
                        // Try one last time with a random name.
                        destinationDisplayName = Utilities.GenerateNewName(originalDisplayName, creatingDocument, Utilities.GenerateRandomString("0123456789", 8));
                        name = destinationDisplayName.ToUpperInvariant();
                        iteration++;
                        continue;
                    }
                    else if (iteration == MaxIterations + 1)
                    {
                        return false;
                    }

                    destinationDisplayName = Utilities.GenerateNewName(originalDisplayName, creatingDocument, (iteration + 2).ToString());
                    name = destinationDisplayName.ToUpperInvariant();
                    iteration++;

                    // Don't allow new versions if we already had a name conflict.
                    newVersion = false;
                } while (NameConflicts(parent, name, creatingDocument, newVersion));
            }

            return true;
        }
        private bool NameConflicts(Folder parent, string name, bool creatingDocument, bool newVersion)
        {
            File file = parent.Files.AsQueryable().Where(f => f.Name == name).SingleOrDefault();

            if (file == null || file.State == ObjectState.Deleted)
                return false;

            if (creatingDocument && newVersion && file is Document)
                return false;

            return true;
        }
        private FileBrowseViewModel CreateBrowseModelForFolder(Folder folder, string fullDisplayName)
        {
            long userId = User.Identity.GetUserId();
            Folder userRootFolder = _fileManager.GetUserRootFolder(userId);

            if (folder == null)
            {
                folder = userRootFolder;
                fullDisplayName = "";
            }

            Folder originalFolder = folder;

            // Follow any invitation link.
            if (folder.InvitationId != null)
                folder = folder.Invitation.Target;

            FileBrowseViewModel model = new FileBrowseViewModel();

            model.FullDisplayName = fullDisplayName;
            model.DisplayName = originalFolder == userRootFolder ? "Home" : originalFolder.DisplayName;
            model.State = originalFolder.State;
            model.Files = (
                from file in folder.Files.AsQueryable()
                where file.State == ObjectState.Normal || file.State == folder.State // Always show deleted files in a deleted folder
                orderby !(file is Folder) ascending, file.Name ascending
                let latestVersion = (file is Document) ? (from version in ((Document)file).DocumentVersions.AsQueryable()
                                                          orderby version.TimeStamp descending
                                                          select version).FirstOrDefault()
                                                         : null
                select new FileBrowseViewModel.FileEntry
                {
                    Id = file.Id,
                    FullDisplayName = fullDisplayName + "/" + file.DisplayName,
                    DisplayName = file.DisplayName,
                    IsFolder = file is Folder,
                    Size = latestVersion != null ? latestVersion.Blob.Size : 0,
                    TimeStamp = latestVersion != null ? latestVersion.TimeStamp : DateTime.UtcNow,
                    State = file.State,
                    HasInvitation = (file is Folder) ? ((Folder)file).InvitationId != null : false,
                    HasTargetInvitations = (file is Folder) ? ((Folder)file).TargetOfInvitations.Any() : false
                }
                ).ToList();
            model.Parents = new List<Tuple<string, string>>();

            // Construct the parent list for the breadcrumb.

            List<Folder> parentFolders = new List<Folder>();
            Folder currentFolder = folder;

            while (currentFolder != userRootFolder)
            {
                if (currentFolder.TargetOfInvitations.Any())
                {
                    model.SharedFolder = true;

                    // Follow any invitation link backwards.

                    var invitation = _fileManager.GetInvitationForUser(currentFolder, userId);
                    Folder acceptedFolder = null;

                    if (invitation != null)
                        acceptedFolder = invitation.AcceptedFolders.SingleOrDefault();

                    if (acceptedFolder != null)
                    {
                        currentFolder = acceptedFolder;
                        model.SharedWithMe = true;
                    }
                }

                if (currentFolder != userRootFolder)
                    parentFolders.Add(currentFolder);

                currentFolder = currentFolder.ParentFolder;
            };

            parentFolders.Reverse();

            if (parentFolders.Count != 0)
                parentFolders.RemoveAt(parentFolders.Count - 1);

            if (folder != userRootFolder)
                model.Parents.Add(new Tuple<string, string>("Home", ""));

            StringBuilder sb = new StringBuilder();

            foreach (var f in parentFolders)
            {
                sb.Append('/');
                sb.Append(f.DisplayName);

                model.Parents.Add(new Tuple<string, string>(f.DisplayName, sb.ToString()));
            }

            return model;
        }