Added backup/restore functionality.
This commit is contained in:
parent
5d7e8c3c4a
commit
74981f98aa
11 changed files with 860 additions and 5 deletions
673
BackupRestore/BackupRestore.cs
Normal file
673
BackupRestore/BackupRestore.cs
Normal file
|
@ -0,0 +1,673 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ScrewTurn.Wiki.PluginFramework;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Collections;
|
||||
using ScrewTurn.Wiki.AclEngine;
|
||||
using Ionic.Zip;
|
||||
using System.IO;
|
||||
|
||||
namespace ScrewTurn.Wiki.BackupRestore {
|
||||
|
||||
/// <summary>
|
||||
/// Implements a Backup and Restore procedure for settings storage providers.
|
||||
/// </summary>
|
||||
public static class BackupRestore {
|
||||
|
||||
private const string BACKUP_RESTORE_UTILITY_VERSION = "1.0";
|
||||
|
||||
private static VersionFile generateVersionFile(string backupName) {
|
||||
return new VersionFile() {
|
||||
BackupRestoreVersion = BACKUP_RESTORE_UTILITY_VERSION,
|
||||
WikiVersion = typeof(BackupRestore).Assembly.GetName().Version.ToString(),
|
||||
BackupName = backupName
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backups all the providers (excluded global settings storage provider).
|
||||
/// </summary>
|
||||
/// <param name="backupZipFileName">The name of the zip file where to store the backup file.</param>
|
||||
/// <param name="plugins">The available plugins.</param>
|
||||
/// <param name="settingsStorageProvider">The settings storage provider.</param>
|
||||
/// <param name="pagesStorageProviders">The pages storage providers.</param>
|
||||
/// <param name="usersStorageProviders">The users storage providers.</param>
|
||||
/// <param name="filesStorageProviders">The files storage providers.</param>
|
||||
/// <returns><c>true</c> if the backup has been succesfull.</returns>
|
||||
public static bool BackupAll(string backupZipFileName, string[] plugins, ISettingsStorageProviderV30 settingsStorageProvider, IPagesStorageProviderV30[] pagesStorageProviders, IUsersStorageProviderV30[] usersStorageProviders, IFilesStorageProviderV30[] filesStorageProviders) {
|
||||
string tempPath = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using(ZipFile backupZipFile = new ZipFile(backupZipFileName)) {
|
||||
|
||||
// Find all namespaces
|
||||
List<string> namespaces = new List<string>();
|
||||
foreach(IPagesStorageProviderV30 pagesStorageProvider in pagesStorageProviders) {
|
||||
foreach(NamespaceInfo ns in pagesStorageProvider.GetNamespaces()) {
|
||||
namespaces.Add(ns.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// Backup settings storage provider
|
||||
string zipSettingsBackup = Path.Combine(tempPath, "SettingsBackup-" + settingsStorageProvider.GetType().FullName + ".zip");
|
||||
BackupSettingsStorageProvider(zipSettingsBackup, settingsStorageProvider, namespaces.ToArray(), plugins);
|
||||
backupZipFile.AddFile(zipSettingsBackup, "");
|
||||
|
||||
// Backup pages storage providers
|
||||
foreach(IPagesStorageProviderV30 pagesStorageProvider in pagesStorageProviders) {
|
||||
string zipPagesBackup = Path.Combine(tempPath, "PagesBackup-" + pagesStorageProvider.GetType().FullName + ".zip");
|
||||
BackupPagesStorageProvider(zipPagesBackup, pagesStorageProvider);
|
||||
backupZipFile.AddFile(zipPagesBackup, "");
|
||||
}
|
||||
|
||||
// Backup users storage providers
|
||||
foreach(IUsersStorageProviderV30 usersStorageProvider in usersStorageProviders) {
|
||||
string zipUsersProvidersBackup = Path.Combine(tempPath, "UsersBackup-" + usersStorageProvider.GetType().FullName + ".zip");
|
||||
BackupUsersStorageProvider(zipUsersProvidersBackup, usersStorageProvider);
|
||||
backupZipFile.AddFile(zipUsersProvidersBackup, "");
|
||||
}
|
||||
|
||||
// Backup files storage providers
|
||||
foreach(IFilesStorageProviderV30 filesStorageProvider in filesStorageProviders) {
|
||||
string zipFilesProviderBackup = Path.Combine(tempPath, "FilesBackup-" + filesStorageProvider.GetType().FullName + ".zip");
|
||||
BackupFilesStorageProvider(zipFilesProviderBackup, filesStorageProvider, pagesStorageProviders);
|
||||
backupZipFile.AddFile(zipFilesProviderBackup, "");
|
||||
}
|
||||
backupZipFile.Save();
|
||||
}
|
||||
|
||||
Directory.Delete(tempPath, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backups the specified settings provider.
|
||||
/// </summary>
|
||||
/// <param name="zipFileName">The zip file name where to store the backup.</param>
|
||||
/// <param name="settingsStorageProvider">The source settings provider.</param>
|
||||
/// <param name="knownNamespaces">The currently known page namespaces.</param>
|
||||
/// <param name="knownPlugins">The currently known plugins.</param>
|
||||
/// <returns><c>true</c> if the backup file has been succesfully created.</returns>
|
||||
public static bool BackupSettingsStorageProvider(string zipFileName, ISettingsStorageProviderV30 settingsStorageProvider, string[] knownNamespaces, string[] knownPlugins) {
|
||||
SettingsBackup settingsBackup = new SettingsBackup();
|
||||
|
||||
// Settings
|
||||
settingsBackup.Settings = (Dictionary<string, string>)settingsStorageProvider.GetAllSettings();
|
||||
|
||||
// Plugins Status and Configuration
|
||||
Dictionary<string, bool> pluginsStatus = new Dictionary<string, bool>();
|
||||
Dictionary<string, string> pluginsConfiguration = new Dictionary<string, string>();
|
||||
foreach(string plugin in knownPlugins) {
|
||||
pluginsStatus[plugin] = settingsStorageProvider.GetPluginStatus(plugin);
|
||||
pluginsConfiguration[plugin] = settingsStorageProvider.GetPluginConfiguration(plugin);
|
||||
}
|
||||
settingsBackup.PluginsStatus = pluginsStatus;
|
||||
settingsBackup.PluginsConfiguration = pluginsConfiguration;
|
||||
|
||||
// Metadata
|
||||
List<MetaData> metadataList = new List<MetaData>();
|
||||
// Meta-data (global)
|
||||
metadataList.Add(new MetaData() {
|
||||
Item = MetaDataItem.AccountActivationMessage,
|
||||
Tag = null,
|
||||
Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.AccountActivationMessage, null)
|
||||
});
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.PasswordResetProcedureMessage, Tag = null, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.PasswordResetProcedureMessage, null) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.LoginNotice, Tag = null, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.LoginNotice, null) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.PageChangeMessage, Tag = null, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.PageChangeMessage, null) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.DiscussionChangeMessage, Tag = null, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.DiscussionChangeMessage, null) });
|
||||
// Meta-data (ns-specific)
|
||||
List<string> namespacesToProcess = new List<string>();
|
||||
namespacesToProcess.Add("");
|
||||
namespacesToProcess.AddRange(knownNamespaces);
|
||||
foreach(string nspace in namespacesToProcess) {
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.EditNotice, Tag = nspace, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.EditNotice, nspace) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.Footer, Tag = nspace, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.Footer, nspace) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.Header, Tag = nspace, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.Header, nspace) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.HtmlHead, Tag = nspace, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.HtmlHead, nspace) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.PageFooter, Tag = nspace, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.PageFooter, nspace) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.PageHeader, Tag = nspace, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.PageHeader, nspace) });
|
||||
metadataList.Add(new MetaData() { Item = MetaDataItem.Sidebar, Tag = nspace, Content = settingsStorageProvider.GetMetaDataItem(MetaDataItem.Sidebar, nspace) });
|
||||
}
|
||||
settingsBackup.Metadata = metadataList;
|
||||
|
||||
// RecentChanges
|
||||
settingsBackup.RecentChanges = settingsStorageProvider.GetRecentChanges().ToList();
|
||||
|
||||
// OutgoingLinks
|
||||
settingsBackup.OutgoingLinks = (Dictionary<string, string[]>)settingsStorageProvider.GetAllOutgoingLinks();
|
||||
|
||||
// ACLEntries
|
||||
AclEntry[] aclEntries = settingsStorageProvider.AclManager.RetrieveAllEntries();
|
||||
settingsBackup.AclEntries = new List<AclEntryBackup>(aclEntries.Length);
|
||||
foreach(AclEntry aclEntry in aclEntries) {
|
||||
settingsBackup.AclEntries.Add(new AclEntryBackup() {
|
||||
Action = aclEntry.Action,
|
||||
Resource = aclEntry.Resource,
|
||||
Subject = aclEntry.Subject,
|
||||
Value = aclEntry.Value
|
||||
});
|
||||
}
|
||||
|
||||
JavaScriptSerializer javascriptSerializer = new JavaScriptSerializer();
|
||||
javascriptSerializer.MaxJsonLength = javascriptSerializer.MaxJsonLength * 10;
|
||||
|
||||
string tempDir = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDir);
|
||||
|
||||
FileStream tempFile = File.Create(Path.Combine(tempDir, "Settings.json"));
|
||||
byte[] buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(settingsBackup));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
|
||||
tempFile = File.Create(Path.Combine(tempDir, "Version.json"));
|
||||
buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(generateVersionFile("Settings")));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
|
||||
List<string> plugins = settingsStorageProvider.ListPluginAssemblies().ToList();
|
||||
foreach(string pluginFileName in plugins) {
|
||||
tempFile = File.Create(Path.Combine(tempDir, pluginFileName));
|
||||
buffer = settingsStorageProvider.RetrievePluginAssembly(pluginFileName);
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
}
|
||||
|
||||
using(ZipFile zipFile = new ZipFile()) {
|
||||
zipFile.AddDirectory(tempDir, "");
|
||||
zipFile.Save(zipFileName);
|
||||
}
|
||||
Directory.Delete(tempDir, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backups the pages storage provider.
|
||||
/// </summary>
|
||||
/// <param name="zipFileName">The zip file name where to store the backup.</param>
|
||||
/// <param name="pagesStorageProvider">The pages storage provider.</param>
|
||||
/// <returns><c>true</c> if the backup file has been succesfully created.</returns>
|
||||
public static bool BackupPagesStorageProvider(string zipFileName, IPagesStorageProviderV30 pagesStorageProvider) {
|
||||
JavaScriptSerializer javascriptSerializer = new JavaScriptSerializer();
|
||||
javascriptSerializer.MaxJsonLength = javascriptSerializer.MaxJsonLength * 10;
|
||||
|
||||
string tempDir = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDir);
|
||||
|
||||
List<NamespaceInfo> nspaces = new List<NamespaceInfo>(pagesStorageProvider.GetNamespaces());
|
||||
nspaces.Add(null);
|
||||
List<NamespaceBackup> namespaceBackupList = new List<NamespaceBackup>(nspaces.Count);
|
||||
foreach(NamespaceInfo nspace in nspaces) {
|
||||
|
||||
// Backup categories
|
||||
CategoryInfo[] categories = pagesStorageProvider.GetCategories(nspace);
|
||||
List<CategoryBackup> categoriesBackup = new List<CategoryBackup>(categories.Length);
|
||||
foreach(CategoryInfo category in categories) {
|
||||
// Add this category to the categoriesBackup list
|
||||
categoriesBackup.Add(new CategoryBackup() {
|
||||
FullName = category.FullName,
|
||||
Pages = category.Pages
|
||||
});
|
||||
}
|
||||
|
||||
// Backup NavigationPaths
|
||||
NavigationPath[] navigationPaths = pagesStorageProvider.GetNavigationPaths(nspace);
|
||||
List<NavigationPathBackup> navigationPathsBackup = new List<NavigationPathBackup>(navigationPaths.Length);
|
||||
foreach(NavigationPath navigationPath in navigationPaths) {
|
||||
navigationPathsBackup.Add(new NavigationPathBackup() {
|
||||
FullName = navigationPath.FullName,
|
||||
Pages = navigationPath.Pages
|
||||
});
|
||||
}
|
||||
|
||||
// Add this namespace to the namespaceBackup list
|
||||
namespaceBackupList.Add(new NamespaceBackup() {
|
||||
Name = nspace == null ? "" : nspace.Name,
|
||||
DefaultPageFullName = nspace == null ? "" : nspace.DefaultPage.FullName,
|
||||
Categories = categoriesBackup,
|
||||
NavigationPaths = navigationPathsBackup
|
||||
});
|
||||
|
||||
// Backup pages (one json file for each page containing a maximum of 100 revisions)
|
||||
PageInfo[] pages = pagesStorageProvider.GetPages(nspace);
|
||||
foreach(PageInfo page in pages) {
|
||||
PageContent pageContent = pagesStorageProvider.GetContent(page);
|
||||
PageBackup pageBackup = new PageBackup();
|
||||
pageBackup.FullName = page.FullName;
|
||||
pageBackup.CreationDateTime = page.CreationDateTime;
|
||||
pageBackup.LastModified = pageContent.LastModified;
|
||||
pageBackup.Content = pageContent.Content;
|
||||
pageBackup.Comment = pageContent.Comment;
|
||||
pageBackup.Description = pageContent.Description;
|
||||
pageBackup.Keywords = pageContent.Keywords;
|
||||
pageBackup.Title = pageContent.Title;
|
||||
pageBackup.User = pageContent.User;
|
||||
pageBackup.LinkedPages = pageContent.LinkedPages;
|
||||
pageBackup.Categories = (from c in pagesStorageProvider.GetCategoriesForPage(page)
|
||||
select c.FullName).ToArray();
|
||||
|
||||
// Backup the 100 most recent versions of the page
|
||||
List<PageRevisionBackup> pageContentBackupList = new List<PageRevisionBackup>();
|
||||
int[] revisions = pagesStorageProvider.GetBackups(page);
|
||||
for(int i = 0; i < Math.Min(revisions.Length, 100); i++) {
|
||||
PageContent pageRevision = pagesStorageProvider.GetBackupContent(page, revisions[i]);
|
||||
PageRevisionBackup pageContentBackup = new PageRevisionBackup() {
|
||||
Revision = revisions[i],
|
||||
Content = pageRevision.Content,
|
||||
Comment = pageRevision.Comment,
|
||||
Description = pageRevision.Description,
|
||||
Keywords = pageRevision.Keywords,
|
||||
Title = pageRevision.Title,
|
||||
User = pageRevision.User,
|
||||
LastModified = pageRevision.LastModified
|
||||
};
|
||||
pageContentBackupList.Add(pageContentBackup);
|
||||
}
|
||||
pageBackup.Revisions = pageContentBackupList;
|
||||
|
||||
// Backup draft of the page
|
||||
PageContent draft = pagesStorageProvider.GetDraft(page);
|
||||
if(draft != null) {
|
||||
pageBackup.Draft = new PageRevisionBackup() {
|
||||
Content = draft.Content,
|
||||
Comment = draft.Comment,
|
||||
Description = draft.Description,
|
||||
Keywords = draft.Keywords,
|
||||
Title = draft.Title,
|
||||
User = draft.User,
|
||||
LastModified = draft.LastModified
|
||||
};
|
||||
}
|
||||
|
||||
// Backup all messages of the page
|
||||
List<MessageBackup> messageBackupList = new List<MessageBackup>();
|
||||
foreach(Message message in pagesStorageProvider.GetMessages(page)) {
|
||||
messageBackupList.Add(BackupMessage(message));
|
||||
}
|
||||
pageBackup.Messages = messageBackupList;
|
||||
|
||||
FileStream tempFile = File.Create(Path.Combine(tempDir, page.FullName + ".json"));
|
||||
byte[] buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(pageBackup));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
}
|
||||
}
|
||||
FileStream tempNamespacesFile = File.Create(Path.Combine(tempDir, "Namespaces.json"));
|
||||
byte[] namespacesBuffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(namespaceBackupList));
|
||||
tempNamespacesFile.Write(namespacesBuffer, 0, namespacesBuffer.Length);
|
||||
tempNamespacesFile.Close();
|
||||
|
||||
// Backup content templates
|
||||
ContentTemplate[] contentTemplates = pagesStorageProvider.GetContentTemplates();
|
||||
List<ContentTemplateBackup> contentTemplatesBackup = new List<ContentTemplateBackup>(contentTemplates.Length);
|
||||
foreach(ContentTemplate contentTemplate in contentTemplates) {
|
||||
contentTemplatesBackup.Add(new ContentTemplateBackup() {
|
||||
Name = contentTemplate.Name,
|
||||
Content = contentTemplate.Content
|
||||
});
|
||||
}
|
||||
FileStream tempContentTemplatesFile = File.Create(Path.Combine(tempDir, "ContentTemplates.json"));
|
||||
byte[] contentTemplateBuffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(contentTemplatesBackup));
|
||||
tempContentTemplatesFile.Write(contentTemplateBuffer, 0, contentTemplateBuffer.Length);
|
||||
tempContentTemplatesFile.Close();
|
||||
|
||||
// Backup Snippets
|
||||
Snippet[] snippets = pagesStorageProvider.GetSnippets();
|
||||
List<SnippetBackup> snippetsBackup = new List<SnippetBackup>(snippets.Length);
|
||||
foreach(Snippet snippet in snippets) {
|
||||
snippetsBackup.Add(new SnippetBackup() {
|
||||
Name = snippet.Name,
|
||||
Content = snippet.Content
|
||||
});
|
||||
}
|
||||
FileStream tempSnippetsFile = File.Create(Path.Combine(tempDir, "Snippets.json"));
|
||||
byte[] snippetBuffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(snippetsBackup));
|
||||
tempSnippetsFile.Write(snippetBuffer, 0, snippetBuffer.Length);
|
||||
tempSnippetsFile.Close();
|
||||
|
||||
FileStream tempVersionFile = File.Create(Path.Combine(tempDir, "Version.json"));
|
||||
byte[] versionBuffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(generateVersionFile("Pages")));
|
||||
tempVersionFile.Write(versionBuffer, 0, versionBuffer.Length);
|
||||
tempVersionFile.Close();
|
||||
|
||||
using(ZipFile zipFile = new ZipFile()) {
|
||||
zipFile.AddDirectory(tempDir, "");
|
||||
zipFile.Save(zipFileName);
|
||||
}
|
||||
Directory.Delete(tempDir, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Backup a message with a recursive function to backup all its replies.
|
||||
private static MessageBackup BackupMessage(Message message) {
|
||||
MessageBackup messageBackup = new MessageBackup() {
|
||||
Id = message.ID,
|
||||
Subject = message.Subject,
|
||||
Body = message.Body,
|
||||
DateTime = message.DateTime,
|
||||
Username = message.Username
|
||||
};
|
||||
List<MessageBackup> repliesBackup = new List<MessageBackup>(message.Replies.Length);
|
||||
foreach(Message reply in message.Replies) {
|
||||
repliesBackup.Add(BackupMessage(reply));
|
||||
}
|
||||
messageBackup.Replies = repliesBackup;
|
||||
return messageBackup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backups the users storage provider.
|
||||
/// </summary>
|
||||
/// <param name="zipFileName">The zip file name where to store the backup.</param>
|
||||
/// <param name="usersStorageProvider">The users storage provider.</param>
|
||||
/// <returns><c>true</c> if the backup file has been succesfully created.</returns>
|
||||
public static bool BackupUsersStorageProvider(string zipFileName, IUsersStorageProviderV30 usersStorageProvider) {
|
||||
JavaScriptSerializer javascriptSerializer = new JavaScriptSerializer();
|
||||
javascriptSerializer.MaxJsonLength = javascriptSerializer.MaxJsonLength * 10;
|
||||
|
||||
string tempDir = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDir);
|
||||
|
||||
// Backup users
|
||||
UserInfo[] users = usersStorageProvider.GetUsers();
|
||||
List<UserBackup> usersBackup = new List<UserBackup>(users.Length);
|
||||
foreach(UserInfo user in users) {
|
||||
usersBackup.Add(new UserBackup() {
|
||||
Username = user.Username,
|
||||
Active = user.Active,
|
||||
DateTime = user.DateTime,
|
||||
DisplayName = user.DisplayName,
|
||||
Email = user.Email,
|
||||
Groups = user.Groups,
|
||||
UserData = usersStorageProvider.RetrieveAllUserData(user)
|
||||
});
|
||||
}
|
||||
FileStream tempFile = File.Create(Path.Combine(tempDir, "Users.json"));
|
||||
byte[] buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(usersBackup));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
|
||||
// Backup UserGroups
|
||||
UserGroup[] userGroups = usersStorageProvider.GetUserGroups();
|
||||
List<UserGroupBackup> userGroupsBackup = new List<UserGroupBackup>(userGroups.Length);
|
||||
foreach(UserGroup userGroup in userGroups) {
|
||||
userGroupsBackup.Add(new UserGroupBackup() {
|
||||
Name = userGroup.Name,
|
||||
Description = userGroup.Description
|
||||
});
|
||||
}
|
||||
|
||||
tempFile = File.Create(Path.Combine(tempDir, "Groups.json"));
|
||||
buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(userGroupsBackup));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
|
||||
tempFile = File.Create(Path.Combine(tempDir, "Version.json"));
|
||||
buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(generateVersionFile("Users")));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
|
||||
|
||||
using(ZipFile zipFile = new ZipFile()) {
|
||||
zipFile.AddDirectory(tempDir, "");
|
||||
zipFile.Save(zipFileName);
|
||||
}
|
||||
Directory.Delete(tempDir, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backups the files storage provider.
|
||||
/// </summary>
|
||||
/// <param name="zipFileName">The zip file name where to store the backup.</param>
|
||||
/// <param name="filesStorageProvider">The files storage provider.</param>
|
||||
/// <param name="pagesStorageProviders">The pages storage providers.</param>
|
||||
/// <returns><c>true</c> if the backup file has been succesfully created.</returns>
|
||||
public static bool BackupFilesStorageProvider(string zipFileName, IFilesStorageProviderV30 filesStorageProvider, IPagesStorageProviderV30[] pagesStorageProviders) {
|
||||
JavaScriptSerializer javascriptSerializer = new JavaScriptSerializer();
|
||||
javascriptSerializer.MaxJsonLength = javascriptSerializer.MaxJsonLength * 10;
|
||||
|
||||
string tempDir = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDir);
|
||||
|
||||
DirectoryBackup directoriesBackup = BackupDirectory(filesStorageProvider, tempDir, null);
|
||||
FileStream tempFile = File.Create(Path.Combine(tempDir, "Files.json"));
|
||||
byte[] buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(directoriesBackup));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
|
||||
|
||||
// Backup Pages Attachments
|
||||
string[] pagesWithAttachment = filesStorageProvider.GetPagesWithAttachments();
|
||||
foreach(string pageWithAttachment in pagesWithAttachment) {
|
||||
PageInfo pageInfo = FindPageInfo(pageWithAttachment, pagesStorageProviders);
|
||||
if(pageInfo != null) {
|
||||
string[] attachments = filesStorageProvider.ListPageAttachments(pageInfo);
|
||||
List<AttachmentBackup> attachmentsBackup = new List<AttachmentBackup>(attachments.Length);
|
||||
foreach(string attachment in attachments) {
|
||||
FileDetails attachmentDetails = filesStorageProvider.GetPageAttachmentDetails(pageInfo, attachment);
|
||||
attachmentsBackup.Add(new AttachmentBackup() {
|
||||
Name = attachment,
|
||||
PageFullName = pageWithAttachment,
|
||||
LastModified = attachmentDetails.LastModified,
|
||||
Size = attachmentDetails.Size
|
||||
});
|
||||
using(MemoryStream stream = new MemoryStream()) {
|
||||
filesStorageProvider.RetrievePageAttachment(pageInfo, attachment, stream, false);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
byte[] tempBuffer = new byte[stream.Length];
|
||||
stream.Read(tempBuffer, 0, (int)stream.Length);
|
||||
|
||||
DirectoryInfo dir = Directory.CreateDirectory(Path.Combine(tempDir, Path.Combine("__attachments", pageInfo.FullName)));
|
||||
tempFile = File.Create(Path.Combine(dir.FullName, attachment));
|
||||
tempFile.Write(tempBuffer, 0, tempBuffer.Length);
|
||||
tempFile.Close();
|
||||
}
|
||||
}
|
||||
tempFile = File.Create(Path.Combine(tempDir, Path.Combine("__attachments", Path.Combine(pageInfo.FullName, "Attachments.json"))));
|
||||
buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(attachmentsBackup));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
}
|
||||
}
|
||||
|
||||
tempFile = File.Create(Path.Combine(tempDir, "Version.json"));
|
||||
buffer = Encoding.Unicode.GetBytes(javascriptSerializer.Serialize(generateVersionFile("Files")));
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
|
||||
using(ZipFile zipFile = new ZipFile()) {
|
||||
zipFile.AddDirectory(tempDir, "");
|
||||
zipFile.Save(zipFileName);
|
||||
}
|
||||
Directory.Delete(tempDir, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PageInfo FindPageInfo(string pageWithAttachment, IPagesStorageProviderV30[] pagesStorageProviders) {
|
||||
foreach(IPagesStorageProviderV30 pagesStorageProvider in pagesStorageProviders) {
|
||||
PageInfo pageInfo = pagesStorageProvider.GetPage(pageWithAttachment);
|
||||
if(pageInfo != null) return pageInfo;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DirectoryBackup BackupDirectory(IFilesStorageProviderV30 filesStorageProvider, string zipFileName, string directory) {
|
||||
DirectoryBackup directoryBackup = new DirectoryBackup();
|
||||
|
||||
string[] files = filesStorageProvider.ListFiles(directory);
|
||||
List<FileBackup> filesBackup = new List<FileBackup>(files.Length);
|
||||
foreach(string file in files) {
|
||||
FileDetails fileDetails = filesStorageProvider.GetFileDetails(file);
|
||||
filesBackup.Add(new FileBackup() {
|
||||
Name = file,
|
||||
Size = fileDetails.Size,
|
||||
LastModified = fileDetails.LastModified
|
||||
});
|
||||
|
||||
FileStream tempFile = File.Create(Path.Combine(zipFileName.Trim('/').Trim('\\'), file.Trim('/').Trim('\\')));
|
||||
using(MemoryStream stream = new MemoryStream()) {
|
||||
filesStorageProvider.RetrieveFile(file, stream, false);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
byte[] buffer = new byte[stream.Length];
|
||||
stream.Read(buffer, 0, buffer.Length);
|
||||
tempFile.Write(buffer, 0, buffer.Length);
|
||||
tempFile.Close();
|
||||
}
|
||||
}
|
||||
directoryBackup.Name = directory;
|
||||
directoryBackup.Files = filesBackup;
|
||||
|
||||
string[] directories = filesStorageProvider.ListDirectories(directory);
|
||||
List<DirectoryBackup> subdirectoriesBackup = new List<DirectoryBackup>(directories.Length);
|
||||
foreach(string d in directories) {
|
||||
subdirectoriesBackup.Add(BackupDirectory(filesStorageProvider, zipFileName, d));
|
||||
}
|
||||
directoryBackup.SubDirectories = subdirectoriesBackup;
|
||||
|
||||
return directoryBackup;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class SettingsBackup {
|
||||
public Dictionary<string, string> Settings { get; set; }
|
||||
public Dictionary<string, bool> PluginsStatus { get; set; }
|
||||
public Dictionary<string, string> PluginsConfiguration { get; set; }
|
||||
public List<MetaData> Metadata { get; set; }
|
||||
public List<RecentChange> RecentChanges { get; set; }
|
||||
public Dictionary<string, string[]> OutgoingLinks { get; set; }
|
||||
public List<AclEntryBackup> AclEntries { get; set; }
|
||||
}
|
||||
|
||||
internal class AclEntryBackup {
|
||||
public Value Value { get; set; }
|
||||
public string Subject { get; set; }
|
||||
public string Resource { get; set; }
|
||||
public string Action { get; set; }
|
||||
}
|
||||
|
||||
internal class MetaData {
|
||||
public MetaDataItem Item {get; set;}
|
||||
public string Tag {get; set;}
|
||||
public string Content {get; set;}
|
||||
}
|
||||
|
||||
internal class GlobalSettingsBackup {
|
||||
public Dictionary<string, string> Settings { get; set; }
|
||||
public List<string> pluginsFileNames { get; set; }
|
||||
}
|
||||
|
||||
internal class PageBackup {
|
||||
public String FullName { get; set; }
|
||||
public DateTime CreationDateTime { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string Comment { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string[] Keywords { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string User { get; set; }
|
||||
public string[] LinkedPages { get; set; }
|
||||
public List<PageRevisionBackup> Revisions { get; set; }
|
||||
public PageRevisionBackup Draft { get; set; }
|
||||
public List<MessageBackup> Messages { get; set; }
|
||||
public string[] Categories { get; set; }
|
||||
}
|
||||
|
||||
internal class PageRevisionBackup {
|
||||
public string Content { get; set; }
|
||||
public string Comment { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string[] Keywords { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string User { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public int Revision { get; set; }
|
||||
}
|
||||
|
||||
internal class NamespaceBackup {
|
||||
public string Name { get; set; }
|
||||
public string DefaultPageFullName { get; set; }
|
||||
public List<CategoryBackup> Categories { get; set; }
|
||||
public List<NavigationPathBackup> NavigationPaths { get; set; }
|
||||
}
|
||||
|
||||
internal class CategoryBackup {
|
||||
public string FullName { get; set; }
|
||||
public string[] Pages { get; set; }
|
||||
}
|
||||
|
||||
internal class ContentTemplateBackup {
|
||||
public string Name { get; set; }
|
||||
public string Content { get; set; }
|
||||
}
|
||||
|
||||
internal class MessageBackup {
|
||||
public List<MessageBackup> Replies { get; set; }
|
||||
public int Id { get; set; }
|
||||
public string Subject { get; set; }
|
||||
public string Body { get; set; }
|
||||
public DateTime DateTime { get; set; }
|
||||
public string Username { get; set; }
|
||||
}
|
||||
|
||||
internal class NavigationPathBackup {
|
||||
public string FullName { get; set; }
|
||||
public string[] Pages { get; set; }
|
||||
}
|
||||
|
||||
internal class SnippetBackup {
|
||||
public string Name { get; set; }
|
||||
public string Content { get; set; }
|
||||
}
|
||||
|
||||
internal class UserBackup {
|
||||
public string Username { get; set; }
|
||||
public bool Active { get; set; }
|
||||
public DateTime DateTime { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string[] Groups { get; set; }
|
||||
public IDictionary<string, string> UserData { get; set; }
|
||||
}
|
||||
|
||||
internal class UserGroupBackup {
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
|
||||
internal class DirectoryBackup {
|
||||
public List<FileBackup> Files { get; set; }
|
||||
public List<DirectoryBackup> SubDirectories { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
internal class FileBackup {
|
||||
public string Name { get; set; }
|
||||
public long Size { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public string DirectoryName { get; set; }
|
||||
}
|
||||
|
||||
internal class VersionFile {
|
||||
public string BackupRestoreVersion { get; set; }
|
||||
public string WikiVersion { get; set; }
|
||||
public string BackupName { get; set; }
|
||||
}
|
||||
|
||||
internal class AttachmentBackup {
|
||||
public string Name { get; set; }
|
||||
public string PageFullName { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public long Size { get; set; }
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue