using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ScrewTurn.Wiki.PluginFramework;
using System.Net;
using System.Linq;
using System.IO;
namespace ScrewTurn.Wiki {
public partial class AdminProviders : BasePage {
protected void Page_Load(object sender, EventArgs e) {
AdminMaster.RedirectToLoginIfNeeded();
if(!AdminMaster.CanManageProviders(SessionFacade.GetCurrentUsername(), SessionFacade.GetCurrentGroupNames())) UrlTools.Redirect("AccessDenied.aspx");
if(!Page.IsPostBack) {
// Load providers and related data
rptProviders.DataBind();
LoadDlls();
LoadSourceProviders();
}
}
#region Providers List
protected void rdo_CheckedChanged(object sender, EventArgs e) {
ResetEditor();
rptProviders.DataBind();
}
///
/// Resets the editor.
///
private void ResetEditor() {
pnlProviderDetails.Visible = false;
btnAutoUpdateProviders.Visible = true;
txtCurrentProvider.Value = "";
lblResult.CssClass = "";
lblResult.Text = "";
}
protected void rptProviders_DataBinding(object sender, EventArgs e) {
List providers = new List(5);
int enabledCount = 0;
if(rdoPages.Checked) {
enabledCount = Collectors.PagesProviderCollector.AllProviders.Length;
providers.AddRange(Collectors.PagesProviderCollector.AllProviders);
providers.AddRange(Collectors.DisabledPagesProviderCollector.AllProviders);
}
else if(rdoUsers.Checked) {
enabledCount = Collectors.UsersProviderCollector.AllProviders.Length;
providers.AddRange(Collectors.UsersProviderCollector.AllProviders);
providers.AddRange(Collectors.DisabledUsersProviderCollector.AllProviders);
}
else if(rdoFiles.Checked) {
enabledCount = Collectors.FilesProviderCollector.AllProviders.Length;
providers.AddRange(Collectors.FilesProviderCollector.AllProviders);
providers.AddRange(Collectors.DisabledFilesProviderCollector.AllProviders);
}
else if(rdoCache.Checked) {
enabledCount = Collectors.CacheProviderCollector.AllProviders.Length;
providers.AddRange(Collectors.CacheProviderCollector.AllProviders);
providers.AddRange(Collectors.DisabledCacheProviderCollector.AllProviders);
}
else if(rdoFormatter.Checked) {
enabledCount = Collectors.FormatterProviderCollector.AllProviders.Length;
providers.AddRange(Collectors.FormatterProviderCollector.AllProviders);
providers.AddRange(Collectors.DisabledFormatterProviderCollector.AllProviders);
}
List result = new List(providers.Count);
for(int i = 0; i < providers.Count; i++) {
IProviderV30 prov = providers[i];
result.Add(new ProviderRow(prov.Information,
prov.GetType().FullName,
GetUpdateStatus(prov.Information),
i > enabledCount - 1,
txtCurrentProvider.Value == prov.GetType().FullName));
}
rptProviders.DataSource = result;
}
///
/// Gets the update status of a provider.
///
/// The component information.
/// The update status.
private string GetUpdateStatus(ComponentInformation info) {
if(!Settings.DisableAutomaticVersionCheck) {
if(string.IsNullOrEmpty(info.UpdateUrl)) return "n/a";
else {
string newVersion = null;
string newAssemblyUrl = null;
UpdateStatus status = Tools.GetUpdateStatus(info.UpdateUrl, info.Version, out newVersion, out newAssemblyUrl);
if(status == UpdateStatus.Error) {
return "" + Properties.Messages.Error + "";
}
else if(status == UpdateStatus.NewVersionFound) {
return "" + Properties.Messages.NewVersion + " " + newVersion + "" +
(string.IsNullOrEmpty(newAssemblyUrl) ? "" : " (" + Properties.Messages.AutoUpdateAvailable + ")") + "";
}
else if(status == UpdateStatus.UpToDate) {
return "" + Properties.Messages.UpToDate + "";
}
else throw new NotSupportedException();
}
}
else return "n/a";
}
///
/// Gets the currently selected provider.
///
/// The provider.
/// A value indicating whether the returned provider is enabled.
/// A value indicating whether the returned provider can be disabled.
private IProviderV30 GetCurrentProvider(out bool enabled, out bool canDisable) {
return Collectors.FindProvider(txtCurrentProvider.Value, out enabled, out canDisable);
}
protected void rptProviders_ItemCommand(object sender, CommandEventArgs e) {
txtCurrentProvider.Value = e.CommandArgument as string;
if(e.CommandName == "Select") {
bool enabled;
bool canDisable;
IProviderV30 provider = GetCurrentProvider(out enabled, out canDisable);
// Cannot disable the provider that handles the default page of the root namespace
if(Pages.FindPage(Settings.DefaultPage).Provider == provider) canDisable = false;
pnlProviderDetails.Visible = true;
lblProviderName.Text = provider.Information.Name + " (" + provider.Information.Version + ")";
string dll = provider.GetType().Assembly.FullName;
lblProviderDll.Text = dll.Substring(0, dll.IndexOf(",")) + ".dll";
txtConfigurationString.Text = ProviderLoader.LoadConfiguration(provider.GetType().FullName);
if(provider.ConfigHelpHtml != null) {
lblProviderConfigHelp.Text = provider.ConfigHelpHtml;
}
else {
lblProviderConfigHelp.Text = Properties.Messages.NoConfigurationRequired;
}
btnEnable.Visible = !enabled;
btnAutoUpdateProviders.Visible = false;
btnDisable.Visible = enabled;
btnDisable.Enabled = canDisable;
lblCannotDisable.Visible = !canDisable;
btnUnload.Enabled = !enabled;
rptProviders.DataBind();
}
}
///
/// Performs all the actions that are needed after a provider status is changed.
///
private void PerformPostProviderChangeActions() {
Content.InvalidateAllPages();
Content.ClearPseudoCache();
}
protected void btnSave_Click(object sender, EventArgs e) {
bool enabled, canDisable;
IProviderV30 prov = GetCurrentProvider(out enabled, out canDisable);
Log.LogEntry("Configuration change requested for Provider " + prov.Information.Name, EntryType.General, SessionFacade.CurrentUsername);
string error;
if(ProviderLoader.TryChangeConfiguration(txtCurrentProvider.Value, txtConfigurationString.Text, out error)) {
PerformPostProviderChangeActions();
lblResult.CssClass = "resultok";
lblResult.Text = Properties.Messages.ProviderConfigurationSaved;
ResetEditor();
rptProviders.DataBind();
}
else {
lblResult.CssClass = "resulterror";
lblResult.Text = Properties.Messages.ProviderRejectedConfiguration +
(string.IsNullOrEmpty(error) ? "" : (": " + error));
}
}
protected void btnDisable_Click(object sender, EventArgs e) {
bool enabled, canDisable;
IProviderV30 prov = GetCurrentProvider(out enabled, out canDisable);
Log.LogEntry("Deactivation requested for Provider " + prov.Information.Name, EntryType.General, SessionFacade.CurrentUsername);
ProviderLoader.DisableProvider(txtCurrentProvider.Value);
PerformPostProviderChangeActions();
lblResult.CssClass = "resultok";
lblResult.Text = Properties.Messages.ProviderDisabled;
ResetEditor();
rptProviders.DataBind();
LoadSourceProviders();
ReloadDefaultProviders();
}
protected void btnEnable_Click(object sender, EventArgs e) {
bool enabled, canDisable;
IProviderV30 prov = GetCurrentProvider(out enabled, out canDisable);
Log.LogEntry("Activation requested for provider provider " + prov.Information.Name, EntryType.General, SessionFacade.CurrentUsername);
ProviderLoader.EnableProvider(txtCurrentProvider.Value);
PerformPostProviderChangeActions();
lblResult.CssClass = "resultok";
lblResult.Text = Properties.Messages.ProviderEnabled;
ResetEditor();
rptProviders.DataBind();
LoadSourceProviders();
ReloadDefaultProviders();
}
protected void btnUnload_Click(object sender, EventArgs e) {
bool enabled, canDisable;
IProviderV30 prov = GetCurrentProvider(out enabled, out canDisable);
Log.LogEntry("Unloading requested for provider provider " + prov.Information.Name, EntryType.General, SessionFacade.CurrentUsername);
ProviderLoader.UnloadProvider(txtCurrentProvider.Value);
PerformPostProviderChangeActions();
lblResult.CssClass = "resultok";
lblResult.Text = Properties.Messages.ProviderUnloaded;
ResetEditor();
rptProviders.DataBind();
LoadSourceProviders();
ReloadDefaultProviders();
}
protected void btnCancel_Click(object sender, EventArgs e) {
ResetEditor();
rptProviders.DataBind();
}
protected void btnAutoUpdateProviders_Click(object sender, EventArgs e) {
lblAutoUpdateResult.CssClass = "";
lblAutoUpdateResult.Text = "";
Log.LogEntry("Providers auto-update requested", EntryType.General, SessionFacade.CurrentUsername);
ProviderUpdater updater = new ProviderUpdater(Settings.Provider,
Collectors.FileNames,
Collectors.PagesProviderCollector.AllProviders,
Collectors.DisabledPagesProviderCollector.AllProviders,
Collectors.UsersProviderCollector.AllProviders,
Collectors.DisabledUsersProviderCollector.AllProviders,
Collectors.FilesProviderCollector.AllProviders,
Collectors.DisabledFilesProviderCollector.AllProviders,
Collectors.CacheProviderCollector.AllProviders,
Collectors.DisabledCacheProviderCollector.AllProviders,
Collectors.FormatterProviderCollector.AllProviders,
Collectors.DisabledFormatterProviderCollector.AllProviders);
int count = updater.UpdateAll();
lblAutoUpdateResult.CssClass = "resultok";
if(count > 0) lblAutoUpdateResult.Text = Properties.Messages.ProvidersUpdated;
else lblAutoUpdateResult.Text = Properties.Messages.NoProvidersToUpdate;
rptProviders.DataBind();
}
#endregion
#region Defaults
///
/// Reloads the default providers.
///
private void ReloadDefaultProviders() {
lstPagesProvider.Reload();
lstUsersProvider.Reload();
lstFilesProvider.Reload();
}
protected void btnSaveDefaultProviders_Click(object sender, EventArgs e) {
Log.LogEntry("Default providers change requested", EntryType.General, SessionFacade.CurrentUsername);
Settings.BeginBulkUpdate();
Settings.DefaultPagesProvider = lstPagesProvider.SelectedProvider;
Settings.DefaultUsersProvider = lstUsersProvider.SelectedProvider;
Settings.DefaultFilesProvider = lstFilesProvider.SelectedProvider;
Settings.DefaultCacheProvider = lstCacheProvider.SelectedProvider;
Settings.EndBulkUpdate();
lblDefaultProvidersResult.CssClass = "resultok";
lblDefaultProvidersResult.Text = Properties.Messages.DefaultProvidersSaved;
ResetEditor();
rptProviders.DataBind();
}
#endregion
#region DLLs
///
/// Loads all the providers' DLLs.
///
private void LoadDlls() {
string[] files = Settings.Provider.ListPluginAssemblies();
lstDlls.Items.Clear();
lstDlls.Items.Add(new ListItem("- " + Properties.Messages.SelectAndDelete + " -", ""));
for(int i = 0; i < files.Length; i++) {
lstDlls.Items.Add(new ListItem(files[i], files[i]));
}
}
protected void lstDlls_SelectedIndexChanged(object sender, EventArgs e) {
btnDeleteDll.Enabled = lstDlls.SelectedIndex >= 0 && !string.IsNullOrEmpty(lstDlls.SelectedValue);
}
protected void btnDeleteDll_Click(object sender, EventArgs e) {
if(Settings.Provider.DeletePluginAssembly(lstDlls.SelectedValue)) {
LoadDlls();
lstDlls_SelectedIndexChanged(sender, e);
lblDllResult.CssClass = "resultok";
lblDllResult.Text = Properties.Messages.DllDeleted;
}
else {
lblDllResult.CssClass = "resulterror";
lblDllResult.Text = Properties.Messages.CouldNotDeleteDll;
}
}
protected void btnUpload_Click(object sender, EventArgs e) {
string file = upDll.FileName;
string ext = System.IO.Path.GetExtension(file);
if(ext != null) ext = ext.ToLowerInvariant();
if(ext != ".dll") {
lblUploadResult.CssClass = "resulterror";
lblUploadResult.Text = Properties.Messages.VoidOrInvalidFile;
return;
}
Log.LogEntry("Provider DLL upload requested " + upDll.FileName, EntryType.General, SessionFacade.CurrentUsername);
string[] asms = Settings.Provider.ListPluginAssemblies();
if(Array.Find(asms, delegate(string v) {
if(v.Equals(file)) return true;
else return false;
}) != null) {
// DLL already exists
lblUploadResult.CssClass = "resulterror";
lblUploadResult.Text = Properties.Messages.DllAlreadyExists;
return;
}
else {
Settings.Provider.StorePluginAssembly(file, upDll.FileBytes);
int count = ProviderLoader.LoadFromAuto(file);
lblUploadResult.CssClass = "resultok";
lblUploadResult.Text = Properties.Messages.LoadedProviders.Replace("###", count.ToString());
upDll.Attributes.Add("value", "");
PerformPostProviderChangeActions();
LoadDlls();
ResetEditor();
rptProviders.DataBind();
LoadSourceProviders();
}
}
#endregion
#region Data Migration
///
/// Loads source providers for data migration.
///
private void LoadSourceProviders() {
lstPagesSource.Items.Clear();
lstPagesSource.Items.Add(new ListItem("", ""));
foreach(IPagesStorageProviderV30 prov in Collectors.PagesProviderCollector.AllProviders) {
if(!prov.ReadOnly) {
lstPagesSource.Items.Add(new ListItem(prov.Information.Name, prov.GetType().ToString()));
}
}
lstUsersSource.Items.Clear();
lstUsersSource.Items.Add(new ListItem("", ""));
foreach(IUsersStorageProviderV30 prov in Collectors.UsersProviderCollector.AllProviders) {
if(IsUsersProviderFullWriteEnabled(prov)) {
lstUsersSource.Items.Add(new ListItem(prov.Information.Name, prov.GetType().ToString()));
}
}
lstFilesSource.Items.Clear();
lstFilesSource.Items.Add(new ListItem("", ""));
foreach(IFilesStorageProviderV30 prov in Collectors.FilesProviderCollector.AllProviders) {
if(!prov.ReadOnly) {
lstFilesSource.Items.Add(new ListItem(prov.Information.Name, prov.GetType().ToString()));
}
}
lblSettingsSource.Text = Settings.Provider.Information.Name;
lstSettingsDestination.Items.Clear();
lstSettingsDestination.Items.Add(new ListItem("", ""));
if(Settings.Provider.GetType().FullName != typeof(SettingsStorageProvider).FullName) {
lstSettingsDestination.Items.Add(new ListItem(SettingsStorageProvider.ProviderName, typeof(SettingsStorageProvider).FullName));
}
foreach(ISettingsStorageProviderV30 prov in ProviderLoader.LoadAllSettingsStorageProviders(Settings.Provider)) {
if(prov.GetType().FullName != Settings.Provider.GetType().FullName) {
lstSettingsDestination.Items.Add(new ListItem(prov.Information.Name, prov.GetType().FullName));
}
}
}
protected void lstPagesSource_SelectedIndexChanged(object sender, EventArgs e) {
lstPagesDestination.Items.Clear();
if(lstPagesSource.SelectedValue != "") {
foreach(IPagesStorageProviderV30 prov in Collectors.PagesProviderCollector.AllProviders) {
if(!prov.ReadOnly && lstPagesSource.SelectedValue != prov.GetType().ToString()) {
lstPagesDestination.Items.Add(new ListItem(prov.Information.Name, prov.GetType().ToString()));
}
}
}
btnMigratePages.Enabled = lstPagesDestination.Items.Count > 0;
}
protected void lstUsersSource_SelectedIndexChanged(object sender, EventArgs e) {
lstUsersDestination.Items.Clear();
if(lstUsersSource.SelectedValue != "") {
foreach(IUsersStorageProviderV30 prov in Collectors.UsersProviderCollector.AllProviders) {
if(IsUsersProviderFullWriteEnabled(prov) && lstUsersSource.SelectedValue != prov.GetType().ToString()) {
lstUsersDestination.Items.Add(new ListItem(prov.Information.Name, prov.GetType().ToString()));
}
}
}
btnMigrateUsers.Enabled = lstUsersDestination.Items.Count > 0;
}
protected void lstFilesSource_SelectedIndexChanged(object sender, EventArgs e) {
lstFilesDestination.Items.Clear();
if(lstFilesSource.SelectedValue != "") {
foreach(IFilesStorageProviderV30 prov in Collectors.FilesProviderCollector.AllProviders) {
if(!prov.ReadOnly && lstFilesSource.SelectedValue != prov.GetType().ToString()) {
lstFilesDestination.Items.Add(new ListItem(prov.Information.Name, prov.GetType().ToString()));
}
}
}
btnMigrateFiles.Enabled = lstFilesDestination.Items.Count > 0;
}
protected void lstSettingsDestination_SelectedIndexChanged(object sender, EventArgs e) {
btnCopySettings.Enabled = lstSettingsDestination.SelectedValue != "";
}
protected void btnMigratePages_Click(object sender, EventArgs e) {
IPagesStorageProviderV30 from = Collectors.PagesProviderCollector.GetProvider(lstPagesSource.SelectedValue);
IPagesStorageProviderV30 to = Collectors.PagesProviderCollector.GetProvider(lstPagesDestination.SelectedValue);
Log.LogEntry("Pages data migration requested from " + from.Information.Name + " to " + to.Information.Name, EntryType.General, SessionFacade.CurrentUsername);
DataMigrator.MigratePagesStorageProviderData(from, to);
lblMigratePagesResult.CssClass = "resultok";
lblMigratePagesResult.Text = Properties.Messages.DataMigrated;
}
protected void btnMigrateUsers_Click(object sender, EventArgs e) {
IUsersStorageProviderV30 from = Collectors.UsersProviderCollector.GetProvider(lstUsersSource.SelectedValue);
IUsersStorageProviderV30 to = Collectors.UsersProviderCollector.GetProvider(lstUsersDestination.SelectedValue);
Log.LogEntry("Users data migration requested from " + from.Information.Name + " to " + to.Information.Name, EntryType.General, SessionFacade.CurrentUsername);
DataMigrator.MigrateUsersStorageProviderData(from, to, true);
lblMigrateUsersResult.CssClass = "resultok";
lblMigrateUsersResult.Text = Properties.Messages.DataMigrated;
}
protected void btnMigrateFiles_Click(object sender, EventArgs e) {
IFilesStorageProviderV30 from = Collectors.FilesProviderCollector.GetProvider(lstFilesSource.SelectedValue);
IFilesStorageProviderV30 to = Collectors.FilesProviderCollector.GetProvider(lstFilesDestination.SelectedValue);
Log.LogEntry("Files data migration requested from " + from.Information.Name + " to " + to.Information.Name, EntryType.General, SessionFacade.CurrentUsername);
DataMigrator.MigrateFilesStorageProviderData(from, to, Settings.Provider);
lblMigrateFilesResult.CssClass = "resultok";
lblMigrateFilesResult.Text = Properties.Messages.DataMigrated;
}
protected void btnCopySettings_Click(object sender, EventArgs e) {
ISettingsStorageProviderV30 to = null;
ISettingsStorageProviderV30[] allProviders = ProviderLoader.LoadAllSettingsStorageProviders(Settings.Provider);
foreach(ISettingsStorageProviderV30 prov in allProviders) {
if(prov.GetType().ToString() == lstSettingsDestination.SelectedValue) {
to = prov;
break;
}
}
Log.LogEntry("Settings data copy requested to " + to.Information.Name, EntryType.General, SessionFacade.CurrentUsername);
try {
to.Init(Host.Instance, txtSettingsDestinationConfig.Text);
}
catch(InvalidConfigurationException ex) {
Log.LogEntry("Provider rejected configuration: " + ex.ToString(), EntryType.Error, Log.SystemUsername);
lblCopySettingsResult.CssClass = "resulterror";
lblCopySettingsResult.Text = Properties.Messages.ProviderRejectedConfiguration;
return;
}
// Find namespaces
List namespaces = new List(5);
foreach(NamespaceInfo ns in Pages.GetNamespaces()) {
namespaces.Add(ns.Name);
}
DataMigrator.CopySettingsStorageProviderData(Settings.Provider, to, namespaces.ToArray(), Collectors.GetAllProviders());
lblCopySettingsResult.CssClass = "resultok";
lblCopySettingsResult.Text = Properties.Messages.DataCopied;
}
#endregion
protected void btnExport_Click(object sender, EventArgs e) {
Log.LogEntry("Data export requested.", EntryType.General, SessionFacade.GetCurrentUsername());
string tempDir = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
string zipFileName = Path.Combine(tempDir, "Backup.zip");
bool backupFileSucceded = BackupRestore.BackupRestore.BackupAll(zipFileName, Settings.Provider.ListPluginAssemblies(),
Settings.Provider,
(from p in Collectors.PagesProviderCollector.AllProviders where !p.ReadOnly select p).ToArray(),
(from p in Collectors.UsersProviderCollector.AllProviders where IsUsersProviderFullWriteEnabled(p) select p).ToArray(),
(from p in Collectors.FilesProviderCollector.AllProviders where !p.ReadOnly select p).ToArray());
FileInfo file = new FileInfo(zipFileName);
Response.Clear();
Response.AddHeader("content-type", GetMimeType(zipFileName));
Response.AddHeader("content-disposition", "attachment;filename=Backup.zip");
Response.AddHeader("content-length", file.Length.ToString());
Response.TransmitFile(zipFileName);
Response.Flush();
Directory.Delete(tempDir, true);
Log.LogEntry("Data export completed.", EntryType.General, SessionFacade.GetCurrentUsername());
}
private string GetMimeType(string ext) {
string mime = "";
if(MimeTypes.Types.TryGetValue(ext, out mime)) return mime;
else return "application/octet-stream";
}
///
/// Detects whether a users storage provider fully supports writing to all managed data.
///
/// The provider.
/// true if the provider fully supports writing all managed data, false otherwise.
private static bool IsUsersProviderFullWriteEnabled(IUsersStorageProviderV30 provider) {
return
!provider.UserAccountsReadOnly &&
!provider.UserGroupsReadOnly &&
!provider.GroupMembershipReadOnly &&
!provider.UsersDataReadOnly;
}
}
///
/// Represents a provider for display purposes.
///
public class ProviderRow {
private string name, typeName, version, author, authorUrl, updateStatus, additionalClass;
///
/// Initializes a new instance of the class.
///
/// The original component information.
/// The type name.
/// A value indicating whether the provider is disabled.
/// A value indicating whether the provider is selected.
public ProviderRow(ComponentInformation info, string typeName, string updateStatus, bool disabled, bool selected) {
name = info.Name;
this.typeName = typeName;
version = info.Version;
author = info.Author;
authorUrl = info.Url;
this.updateStatus = updateStatus;
additionalClass = disabled ? " disabled" : "";
additionalClass += selected ? " selected" : "";
}
///
/// Gets the name.
///
public string Name {
get { return name; }
}
///
/// Gets the type name.
///
public string TypeName {
get { return typeName; }
}
///
/// Gets the version.
///
public string Version {
get { return version; }
}
///
/// Gets the author.
///
public string Author {
get { return author; }
}
///
/// Gets the author URL.
///
public string AuthorUrl {
get { return authorUrl; }
}
///
/// Gets the provider update status.
///
public string UpdateStatus {
get { return updateStatus; }
}
///
/// Gets the additional CSS class.
///
public string AdditionalClass {
get { return additionalClass; }
}
}
}