예제 #1
0
        /// <summary>
        /// Delete the directory
        /// </summary>
        /// <param name="path">Path to the directory</param>
        /// <returns>A task that represents the completion of the operation</returns>
        protected virtual async Task DeleteDirectoryAsync(string path)
        {
            path = GetVirtualPath(path);
            if (path == GetRootDirectory())
            {
                throw new Exception(GetLanguageResource("E_CannotDeleteRoot"));
            }

            path = GetFullPath(path);
            if (!_fileProvider.DirectoryExists(path))
            {
                throw new Exception(GetLanguageResource("E_DeleteDirInvalidPath"));
            }

            if (_fileProvider.GetDirectories(path).Length > 0 || _fileProvider.GetFiles(path).Length > 0)
            {
                throw new Exception(GetLanguageResource("E_DeleteNonEmpty"));
            }

            try
            {
                _fileProvider.DeleteDirectory(path);
                await HttpContext.Response.WriteAsync(GetSuccessResponse());
            }
            catch
            {
                throw new Exception(GetLanguageResource("E_CannotDeleteDir"));
            }
        }
예제 #2
0
        /// <summary>
        /// Delete plugins
        /// </summary>
        public virtual void DeletePlugins()
        {
            //get all uninstalled plugins (delete plugin only previously uninstalled)
            var pluginDescriptors = _pluginsInfo.PluginDescriptors.Where(descriptor => !descriptor.Installed).ToList();

            //filter plugins need to delete
            pluginDescriptors = pluginDescriptors
                                .Where(descriptor => _pluginsInfo.PluginNamesToDelete.Contains(descriptor.SystemName)).ToList();
            if (!pluginDescriptors.Any())
            {
                return;
            }

            //do not inject services via constructor because it'll cause circular references
            var localizationService     = EngineContext.Current.Resolve <ILocalizationService>();
            var customerActivityService = EngineContext.Current.Resolve <ICustomerActivityService>();

            //delete plugins
            foreach (var descriptor in pluginDescriptors)
            {
                try
                {
                    //try to delete a plugin directory from disk storage
                    var pluginDirectory = _fileProvider.GetDirectoryName(descriptor.OriginalAssemblyFile);
                    if (_fileProvider.DirectoryExists(pluginDirectory))
                    {
                        _fileProvider.DeleteDirectory(pluginDirectory);
                    }

                    //remove plugin system name from the appropriate list
                    _pluginsInfo.PluginNamesToDelete.Remove(descriptor.SystemName);

                    //activity log
                    customerActivityService.InsertActivity("DeletePlugin",
                                                           string.Format(localizationService.GetResource("ActivityLog.DeletePlugin"), descriptor.SystemName));
                }
                catch (Exception exception)
                {
                    //log error
                    var message = string.Format(localizationService.GetResource("Admin.Plugins.Errors.NotDeleted"), descriptor.SystemName);
                    _logger.Error(message, exception);
                }
            }

            //save changes
            _pluginsInfo.Save();
        }
예제 #3
0
        /// <summary>
        /// Initialize
        /// </summary>
        /// <param name="applicationPartManager">Application part manager</param>
        /// <param name="config">Config</param>
        public static void Initialize(ApplicationPartManager applicationPartManager, NopConfig config)
        {
            if (applicationPartManager == null)
            {
                throw new ArgumentNullException(nameof(applicationPartManager));
            }

            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            using (new WriteLockDisposable(Locker))
            {
                // TODO: Add verbose exception handling / raising here since this is happening on app startup and could
                // prevent app from starting altogether
                var pluginFolder = _fileProvider.MapPath(NopPluginDefaults.Path);
                _shadowCopyFolder        = _fileProvider.MapPath(NopPluginDefaults.ShadowCopyPath);
                _reserveShadowCopyFolder = _fileProvider.Combine(_fileProvider.MapPath(NopPluginDefaults.ShadowCopyPath), $"{NopPluginDefaults.ReserveShadowCopyPathName}{DateTime.Now.ToFileTimeUtc()}");

                var referencedPlugins   = new List <PluginDescriptor>();
                var incompatiblePlugins = new List <string>();

                try
                {
                    var installedPluginSystemNames = GetInstalledPluginNames(_fileProvider.MapPath(NopPluginDefaults.InstalledPluginsFilePath));

                    Debug.WriteLine("Creating shadow copy folder and querying for DLLs");
                    //ensure folders are created
                    _fileProvider.CreateDirectory(pluginFolder);
                    _fileProvider.CreateDirectory(_shadowCopyFolder);

                    //get list of all files in bin
                    var binFiles = _fileProvider.GetFiles(_shadowCopyFolder, "*", false);
                    if (config.ClearPluginShadowDirectoryOnStartup)
                    {
                        //clear out shadow copied plugins
                        foreach (var f in binFiles)
                        {
                            if (_fileProvider.GetFileName(f).Equals("placeholder.txt", StringComparison.InvariantCultureIgnoreCase))
                            {
                                continue;
                            }

                            Debug.WriteLine("Deleting " + f);
                            try
                            {
                                //ignore index.htm
                                var fileName = _fileProvider.GetFileName(f);
                                if (fileName.Equals("index.htm", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    continue;
                                }

                                _fileProvider.DeleteFile(f);
                            }
                            catch (Exception exc)
                            {
                                Debug.WriteLine("Error deleting file " + f + ". Exception: " + exc);
                            }
                        }

                        //delete all reserve folders
                        foreach (var directory in _fileProvider.GetDirectories(_shadowCopyFolder, NopPluginDefaults.ReserveShadowCopyPathNamePattern))
                        {
                            try
                            {
                                _fileProvider.DeleteDirectory(directory);
                            }
                            catch
                            {
                                //do nothing
                            }
                        }
                    }

                    //load description files
                    foreach (var dfd in GetDescriptionFilesAndDescriptors(pluginFolder))
                    {
                        var descriptionFile  = dfd.Key;
                        var pluginDescriptor = dfd.Value;

                        //ensure that version of plugin is valid
                        if (!pluginDescriptor.SupportedVersions.Contains(NopVersion.CurrentVersion, StringComparer.InvariantCultureIgnoreCase))
                        {
                            incompatiblePlugins.Add(pluginDescriptor.SystemName);
                            continue;
                        }

                        //some validation
                        if (string.IsNullOrWhiteSpace(pluginDescriptor.SystemName))
                        {
                            throw new Exception($"A plugin '{descriptionFile}' has no system name. Try assigning the plugin a unique name and recompiling.");
                        }
                        if (referencedPlugins.Contains(pluginDescriptor))
                        {
                            throw new Exception($"A plugin with '{pluginDescriptor.SystemName}' system name is already defined");
                        }

                        //set 'Installed' property
                        pluginDescriptor.Installed = installedPluginSystemNames
                                                     .FirstOrDefault(x => x.Equals(pluginDescriptor.SystemName, StringComparison.InvariantCultureIgnoreCase)) != null;

                        try
                        {
                            var directoryName = _fileProvider.GetDirectoryName(descriptionFile);
                            if (string.IsNullOrEmpty(directoryName))
                            {
                                throw new Exception($"Directory cannot be resolved for '{_fileProvider.GetFileName(descriptionFile)}' description file");
                            }

                            //get list of all DLLs in plugins (not in bin!)
                            var pluginFiles = _fileProvider.GetFiles(directoryName, "*.dll", false)
                                              //just make sure we're not registering shadow copied plugins
                                              .Where(x => !binFiles.Select(q => q).Contains(x))
                                              .Where(x => IsPackagePluginFolder(_fileProvider.GetDirectoryName(x)))
                                              .ToList();

                            //other plugin description info
                            var mainPluginFile = pluginFiles
                                                 .FirstOrDefault(x => _fileProvider.GetFileName(x).Equals(pluginDescriptor.AssemblyFileName, StringComparison.InvariantCultureIgnoreCase));

                            //plugin have wrong directory
                            if (mainPluginFile == null)
                            {
                                incompatiblePlugins.Add(pluginDescriptor.SystemName);
                                continue;
                            }

                            pluginDescriptor.OriginalAssemblyFile = mainPluginFile;

                            //shadow copy main plugin file
                            pluginDescriptor.ReferencedAssembly = PerformFileDeploy(mainPluginFile, applicationPartManager, config);

                            //load all other referenced assemblies now
                            foreach (var plugin in pluginFiles
                                     .Where(x => !_fileProvider.GetFileName(x).Equals(_fileProvider.GetFileName(mainPluginFile), StringComparison.InvariantCultureIgnoreCase))
                                     .Where(x => !IsAlreadyLoaded(x)))
                            {
                                PerformFileDeploy(plugin, applicationPartManager, config);
                            }

                            //init plugin type (only one plugin per assembly is allowed)
                            foreach (var t in pluginDescriptor.ReferencedAssembly.GetTypes())
                            {
                                if (typeof(IPlugin).IsAssignableFrom(t))
                                {
                                    if (!t.IsInterface)
                                    {
                                        if (t.IsClass && !t.IsAbstract)
                                        {
                                            pluginDescriptor.PluginType = t;
                                            break;
                                        }
                                    }
                                }
                            }

                            referencedPlugins.Add(pluginDescriptor);
                        }
                        catch (ReflectionTypeLoadException ex)
                        {
                            //add a plugin name. this way we can easily identify a problematic plugin
                            var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. ";
                            foreach (var e in ex.LoaderExceptions)
                            {
                                msg += e.Message + Environment.NewLine;
                            }

                            var fail = new Exception(msg, ex);
                            throw fail;
                        }
                        catch (Exception ex)
                        {
                            //add a plugin name. this way we can easily identify a problematic plugin
                            var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. {ex.Message}";

                            var fail = new Exception(msg, ex);
                            throw fail;
                        }
                    }
                }
                catch (Exception ex)
                {
                    var msg = string.Empty;
                    for (var e = ex; e != null; e = e.InnerException)
                    {
                        msg += e.Message + Environment.NewLine;
                    }

                    var fail = new Exception(msg, ex);
                    throw fail;
                }

                ReferencedPlugins   = referencedPlugins;
                IncompatiblePlugins = incompatiblePlugins;
            }
        }
예제 #4
0
        /// <summary>
        /// Upload single item from the archive into the physical directory
        /// </summary>
        /// <param name="archivePath">Path to the archive</param>
        /// <returns>Uploaded item descriptor</returns>
        protected virtual IDescriptor UploadSingleItem(string archivePath)
        {
            //get path to the plugins directory
            var pluginsDirectory = _fileProvider.MapPath(NopPluginDefaults.Path);

            //get path to the themes directory
            var themesDirectory = string.Empty;

            if (!string.IsNullOrEmpty(NopPluginDefaults.ThemesPath))
            {
                themesDirectory = _fileProvider.MapPath(NopPluginDefaults.ThemesPath);
            }

            IDescriptor descriptor = null;
            string      uploadedItemDirectoryName;

            using (var archive = ZipFile.OpenRead(archivePath))
            {
                //the archive should contain only one root directory (the plugin one or the theme one)
                var rootDirectories = archive.Entries.Select(p => p.FullName.Split('/')[0]).Distinct().ToList();

                if (rootDirectories.Count != 1)
                {
                    throw new Exception("The archive should contain only one root plugin or theme directory. " +
                                        "For example, Payments.PayPalDirect or DefaultClean. " +
                                        $"To upload multiple items, the archive should have the '{NopPluginDefaults.UploadedItemsFileName}' file in the root");
                }

                //get directory name (remove the ending /)
                uploadedItemDirectoryName = rootDirectories.First();

                //try to get descriptor of the uploaded item
                foreach (var entry in archive.Entries)
                {
                    //whether it's a plugin descriptor
                    var isPluginDescriptor = entry.FullName
                                             .Equals($"{uploadedItemDirectoryName}/{NopPluginDefaults.DescriptionFileName}", StringComparison.InvariantCultureIgnoreCase);

                    //or whether it's a theme descriptor
                    var isThemeDescriptor = entry.FullName
                                            .Equals($"{uploadedItemDirectoryName}/{NopPluginDefaults.ThemeDescriptionFileName}", StringComparison.InvariantCultureIgnoreCase);

                    if (!isPluginDescriptor && !isThemeDescriptor)
                    {
                        continue;
                    }

                    using var unzippedEntryStream = entry.Open();
                    using var reader = new StreamReader(unzippedEntryStream);
                    //whether a plugin is upload
                    if (isPluginDescriptor)
                    {
                        descriptor = PluginDescriptor.GetPluginDescriptorFromText(reader.ReadToEnd());

                        //ensure that the plugin current version is supported
                        if (!((PluginDescriptor)descriptor).SupportedVersions.Contains(NopVersion.CURRENT_VERSION))
                        {
                            throw new Exception($"This plugin doesn't support the current version - {NopVersion.CURRENT_VERSION}");
                        }
                    }

                    //or whether a theme is upload
                    if (isThemeDescriptor)
                    {
                        descriptor = _themeProvider.GetThemeDescriptorFromText(reader.ReadToEnd());
                    }

                    break;
                }
            }

            if (descriptor == null)
            {
                throw new Exception("No descriptor file is found. It should be in the root of the archive.");
            }

            if (string.IsNullOrEmpty(uploadedItemDirectoryName))
            {
                throw new Exception($"Cannot get the {(descriptor is PluginDescriptor ? "plugin" : "theme")} directory name");
            }

            //get path to upload
            var directoryPath = descriptor is PluginDescriptor ? pluginsDirectory : themesDirectory;
            var pathToUpload  = _fileProvider.Combine(directoryPath, uploadedItemDirectoryName);

            //ensure it's a new directory (e.g. some old files are not required when re-uploading a plugin)
            //furthermore, zip extract functionality cannot override existing files
            //but there could deletion issues (related to file locking, etc). In such cases the directory should be deleted manually
            if (_fileProvider.DirectoryExists(pathToUpload))
            {
                _fileProvider.DeleteDirectory(pathToUpload);
            }

            //unzip archive
            ZipFile.ExtractToDirectory(archivePath, directoryPath);

            return(descriptor);
        }