public static PluginInfo LoadPluginFromConfig(string configFile, bool pendingRestart = false) { //read the file content var fileContent = File.ReadAllText(configFile); PluginInfo pluginInfo; try { pluginInfo = JsonConvert.DeserializeObject <PluginInfo>(fileContent); if (pluginInfo == null) { return(null);//invalid file found } //ignore any invalid ones if (IsNullEmptyOrWhitespace(pluginInfo.SystemName) || IsNullEmptyOrWhitespace(pluginInfo.Name) || IsNullEmptyOrWhitespace(pluginInfo.AssemblyName)) { return(null); } //is this plugin version supported? if (pluginInfo.SupportedVersions.All(x => !AppVersionEvaluator.IsVersionSupported(x))) { return(null); } } catch { //something must be wrong with the file content. Ignore the file return(null); } var fileInfo = new FileInfo(configFile); pluginInfo.PluginDirectory = fileInfo.DirectoryName; var assemblyPath = Path.Combine(pluginInfo.PluginDirectory, pluginInfo.AssemblyName); if (!File.Exists(assemblyPath)) { throw new System.Exception( $"Can't load the assembly {assemblyPath} for the plugin {pluginInfo.Name} ({pluginInfo.SystemName})"); } var mainAssemblyFileInfo = new FileInfo(assemblyPath); //copy the assembly file to bin directory SafeFileCopy(mainAssemblyFileInfo, Path.Combine(_binDirectory, mainAssemblyFileInfo.Name)); var pluginAssembly = Assembly.LoadFile(Path.Combine(_binDirectory, mainAssemblyFileInfo.Name)); //copy the dependent assemblies var dependentAssemblies = GetPluginDirectoryDlls(pluginInfo); //GetDependentAssemblies(pluginAssembly); var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var da in dependentAssemblies) { if (loadedAssemblies.Any(x => x.FullName == da.Key)) { continue; } var dAssemblyPath = Path.Combine(pluginInfo.PluginDirectory, da.Value); if (!File.Exists(dAssemblyPath)) { continue; } var assemblyFileInfo = new FileInfo(dAssemblyPath); var targetPath = Path.Combine(_binDirectory, da.Value); SafeFileCopy(assemblyFileInfo, targetPath); } //set the assembly to the copied one pluginInfo.Assembly = pluginAssembly; pluginInfo.PluginType = TypeFinder.OfType <IPlugin>(pluginAssembly); //set startup var startupType = TypeFinder.OfType <IAppStartup>(pluginAssembly); if (startupType != null) { pluginInfo.Startup = (IAppStartup)Activator.CreateInstance(startupType); } //set container var diType = TypeFinder.OfType <IDependencyContainer>(pluginAssembly); if (diType != null) { pluginInfo.DependencyContainer = (IDependencyContainer)Activator.CreateInstance(diType); } _loadedPlugins.Add(pluginInfo); pluginInfo.PendingRestart = pendingRestart; return(pluginInfo); }
public bool HandleZipUpload(byte[] fileBytes) { //get a temporary file from provided bytes var zipFile = _localFileProvider.GetTemporaryFile(fileBytes); //get temporary directory to extract the package var tempDirectory = _localFileProvider.GetTemporaryDirectory(); try { //first extract the zip _localFileProvider.ExtractArchive(zipFile, tempDirectory); var metaJsonFile = _localFileProvider.CombinePaths(tempDirectory, "meta.json"); if (!_localFileProvider.FileExists(metaJsonFile)) { _logger.Log <PluginAccountant>(LogLevel.Error, "Unsupported or damaged package uploaded"); return(false); } var packageMeta = _dataSerializer.DeserializeAs <PackageMeta>(_localFileProvider.ReadAllText(metaJsonFile)); if (packageMeta?.Items == null || !packageMeta.Items.Any()) { _logger.Log <PluginAccountant>(LogLevel.Error, "Unsupported or damaged package uploaded"); return(false); } var pluginsDirectory = ServerHelper.MapPath("~/Plugins"); var themesDirectory = ServerHelper.MapPath("~/Content/Themes"); //extract each supported folder to themes and plugins foreach (var itemMeta in packageMeta.Items) { //skip the version not supported if (!AppVersionEvaluator.IsVersionSupported(itemMeta.SupportedVersion)) { continue; } var itemDirectory = _localFileProvider.CombinePaths(tempDirectory, itemMeta.Path); var destinationDirectory = ""; destinationDirectory = _localFileProvider.CombinePaths( packageMeta.Package == PackageMeta.PackageType.Plugin ? pluginsDirectory : themesDirectory, packageMeta.PackageDirectoryName); _localFileProvider.CopyDirectory(itemDirectory, destinationDirectory, true); //load the package var configFile = _localFileProvider.CombinePaths(destinationDirectory, "config.json"); if (packageMeta.Package == PackageMeta.PackageType.Plugin) { PluginLoader.LoadPluginFromConfig(configFile, true); } if (packageMeta.Package == PackageMeta.PackageType.Theme) { DependencyResolver.Resolve <IThemeProvider>().LoadTheme(destinationDirectory, true); } } return(true); } catch (InvalidDataException ex) { _logger.Log <PluginAccountant>(LogLevel.Error, "The package doesn't appear to be a valid zip file.", ex); return(false); } catch (Exception ex) { _logger.Log <PluginAccountant>(LogLevel.Error, ex.Message, ex); return(false); } finally { _localFileProvider.DeleteDirectory(tempDirectory, true); _localFileProvider.DeleteFile(zipFile); } }