PageRenderTime 58ms CodeModel.GetById 14ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/BlogEngine/DotNetSlave.BusinessLogic/Packaging/FileSystem.cs

#
C# | 296 lines | 232 code | 43 blank | 21 comment | 35 complexity | 1abe5c6296ea47850d0b8507089aa67c MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.IO;
  4using System.Linq;
  5using System.Xml;
  6using System.Web;
  7using BlogEngine.Core.Json;
  8using BlogEngine.Core.Providers;
  9
 10namespace BlogEngine.Core.Packaging
 11{
 12    /// <summary>
 13    /// Class for packaging IO
 14    /// </summary>
 15    public class FileSystem
 16    {
 17        private static int fileOrder;
 18
 19        /// <summary>
 20        /// 
 21        /// </summary>
 22        /// <param name="packages"></param>
 23        public static void Load(List<JsonPackage> packages)
 24        {
 25            try
 26            {
 27                var themes = GetThemes();
 28                var widgets = GetWidgets();
 29                
 30                if(themes != null && themes.Count > 0)
 31                {
 32                    foreach (var theme in from theme in themes
 33                        let found = packages.Any(pkg => theme.Id == pkg.Id)
 34                        where !found select theme)
 35                    {
 36                        packages.Add(theme);
 37                    }
 38                }
 39
 40                if (widgets != null && widgets.Count > 0)
 41                {
 42                    foreach (var wdg in from wdg in widgets
 43                        let found = packages.Any(pkg => wdg.Id == pkg.Id)
 44                        where !found select wdg)
 45                    {
 46                        packages.Add(wdg);
 47                    }
 48                }
 49            }
 50            catch (Exception ex)
 51            {
 52                Utils.Log(System.Reflection.MethodBase.GetCurrentMethod().Name, ex);
 53            }
 54        }
 55
 56        /// <summary>
 57        /// Copy uncompressed package files
 58        /// to application directories
 59        /// </summary>
 60        /// <param name="pkgId">Package Id</param>
 61        /// <param name="version">Package Version</param>
 62        public static List<PackageFile> InstallPackage(string pkgId, string version)
 63        {
 64            var packgeFiles = new List<PackageFile>();
 65
 66            var content = HttpContext.Current.Server.MapPath(Utils.ApplicationRelativeWebRoot +
 67                string.Format("App_Data/packages/{0}.{1}/content", pkgId, version));
 68
 69            var lib = HttpContext.Current.Server.MapPath(Utils.ApplicationRelativeWebRoot +
 70                string.Format("App_Data/packages/{0}.{1}/lib", pkgId, version));
 71
 72            var root = HttpContext.Current.Server.MapPath(Utils.ApplicationRelativeWebRoot);
 73            var bin = HttpContext.Current.Server.MapPath(Utils.ApplicationRelativeWebRoot + "bin");
 74
 75            // copy content files
 76            var source = new DirectoryInfo(content);
 77            var target = new DirectoryInfo(root);
 78            
 79            fileOrder = 0;
 80            CopyDirectory(source, target, pkgId, packgeFiles);
 81
 82            // copy DLLs from lib to bin
 83            if (Directory.Exists(lib))
 84            {
 85                source = new DirectoryInfo(lib);
 86                target = new DirectoryInfo(bin);
 87
 88                fileOrder = 0;
 89                CopyDirectory(source, target, pkgId, packgeFiles);
 90            }
 91
 92            return packgeFiles;
 93        }
 94
 95        /// <summary>
 96        /// Remove package files
 97        /// </summary>
 98        /// <param name="pkgId">Package Id</param>
 99        public static void UninstallPackage(string pkgId)
100        {
101            var installedFiles = BlogService.InstalledFromGalleryPackageFiles(pkgId);
102
103            foreach (var file in installedFiles.OrderByDescending(f => f.FileOrder))
104            {
105                if(file.IsDirectory)
106                {
107                    var folder = new DirectoryInfo(file.FilePath);
108                    if (folder.Exists)
109                    {
110                        if(folder.GetFileSystemInfos().Length == 0)
111                        {
112                            ForceDeleteDirectory(file.FilePath);
113                        }
114                        else
115                        {
116                            Utils.Log(string.Format("Package Uninstaller: can not remove directory if it is not empty ({0})", file.FilePath));
117                        }
118                    }
119
120                }else
121                {
122                    File.Delete(file.FilePath);
123                }
124            }
125        }
126
127        #region Private methods
128
129        static List<JsonPackage> GetThemes()
130        {
131            var installedThemes = new List<JsonPackage>();
132            var path = HttpContext.Current.Server.MapPath(string.Format("{0}themes/", Utils.ApplicationRelativeWebRoot));
133
134            foreach (var p in from d in Directory.GetDirectories(path)
135                let index = d.LastIndexOf(Path.DirectorySeparatorChar) + 1
136                select d.Substring(index)
137                into themeId select GetPackageManifest(themeId, Constants.Theme) ?? 
138                new JsonPackage {Id = themeId, PackageType = Constants.Theme, Location = "L"}
139                into p where p.Id != "RazorHost" select p)
140            {
141                if (string.IsNullOrEmpty(p.IconUrl))
142                    p.IconUrl = DefaultIconUrl(p);
143
144                installedThemes.Add(p);
145            }
146            return installedThemes;
147        }
148
149        static List<JsonPackage> GetWidgets()
150        {
151            var installedWidgets = new List<JsonPackage>();
152            var path = HttpContext.Current.Server.MapPath(string.Format("{0}widgets/", Utils.ApplicationRelativeWebRoot));
153
154            foreach (var p in from d in Directory.GetDirectories(path)
155                let index = d.LastIndexOf(Path.DirectorySeparatorChar) + 1
156                select d.Substring(index)
157                into widgetId select GetPackageManifest(widgetId, Constants.Widget) ?? 
158                new JsonPackage {Id = widgetId, PackageType = Constants.Widget, Location = "L"})
159            {
160                if (string.IsNullOrEmpty(p.IconUrl))
161                    p.IconUrl = DefaultIconUrl(p);
162
163                installedWidgets.Add(p);
164            }
165            return installedWidgets;
166        }
167
168        static JsonPackage GetPackageManifest(string id, string pkgType)
169        {
170            var jp = new JsonPackage { Id = id, PackageType = pkgType };
171
172            var pkgUrl = pkgType == "Theme" ?
173                string.Format("{0}themes/{1}/theme.xml", Utils.ApplicationRelativeWebRoot, id) :
174                string.Format("{0}widgets/{1}/widget.xml", Utils.ApplicationRelativeWebRoot, id);
175
176            var pkgPath = HttpContext.Current.Server.MapPath(pkgUrl);
177            try
178            {
179                if (File.Exists(pkgPath))
180                {
181                    var textReader = new XmlTextReader(pkgPath);
182                    textReader.Read();
183
184                    while (textReader.Read())
185                    {
186                        textReader.MoveToElement();
187
188                        if (textReader.Name == "description")
189                            jp.Description = textReader.ReadString();
190
191                        if (textReader.Name == "authors")
192                            jp.Authors = textReader.ReadString();
193
194                        if (textReader.Name == "website")
195                            jp.Website = textReader.ReadString();
196
197                        if (textReader.Name == "version")
198                            jp.LocalVersion = textReader.ReadString();
199
200                        if (textReader.Name == "iconurl")
201                            jp.IconUrl = textReader.ReadString();
202                    }
203                    return jp;
204                }
205            }
206            catch (Exception ex)
207            {
208                Utils.Log("Packaging.FileSystem.GetPackageManifest", ex);
209            }
210            return null;
211        }
212
213        static void CopyDirectory(DirectoryInfo source, DirectoryInfo target, string pkgId, List<PackageFile> installedFiles)
214        {
215            foreach (var dir in source.GetDirectories())
216            {
217                // save directory if it is created by package
218                // so we can remove it on package uninstall
219                if (!Directory.Exists(Path.Combine(target.FullName, dir.Name)))
220                {
221                    fileOrder++;
222                    var fileToCopy = new PackageFile
223                    {
224                        FilePath = Path.Combine(target.FullName, dir.Name),
225                        PackageId = pkgId,
226                        FileOrder = fileOrder,
227                        IsDirectory = true
228                    };
229                    installedFiles.Add(fileToCopy);
230                }                   
231                CopyDirectory(dir, target.CreateSubdirectory(dir.Name), pkgId, installedFiles);
232            }
233             
234            foreach (var file in source.GetFiles())
235            {
236                file.CopyTo(Path.Combine(target.FullName, file.Name));
237
238                fileOrder++;
239                var fileToCopy = new PackageFile
240                {
241                    FileOrder = fileOrder,
242                    IsDirectory = false,
243                    FilePath = Path.Combine(target.FullName, file.Name),
244                    PackageId = pkgId
245                };
246                installedFiles.Add(fileToCopy);
247            }   
248        }
249
250        static void ForceDeleteDirectory(string path)
251        {
252            DirectoryInfo fol;
253            var fols = new Stack<DirectoryInfo>();
254            var root = new DirectoryInfo(path);
255            fols.Push(root);
256            while (fols.Count > 0)
257            {
258                fol = fols.Pop();
259                fol.Attributes = fol.Attributes & ~(FileAttributes.Archive | FileAttributes.ReadOnly | FileAttributes.Hidden);
260                foreach (DirectoryInfo d in fol.GetDirectories())
261                {
262                    fols.Push(d);
263                }
264                foreach (FileInfo f in fol.GetFiles())
265                {
266                    f.Attributes = f.Attributes & ~(FileAttributes.Archive | FileAttributes.ReadOnly | FileAttributes.Hidden);
267                    f.Delete();
268                }
269            }
270            root.Delete(true);
271        }
272
273        static string DefaultIconUrl(JsonPackage pkg)
274        {
275            var validImages = new List<string> {"screenshot.jpg", "screenshot.png", "theme.jpg", "theme.png"};
276            var pkgDir = pkg.PackageType == "Widget" ? "widgets" : "themes";
277
278            foreach (var img in validImages)
279            {
280                var url = string.Format("{0}{1}/{2}/{3}",
281                Utils.ApplicationRelativeWebRoot, pkgDir, pkg.Id, img);
282
283                var path = HttpContext.Current.Server.MapPath(url);
284
285                if (File.Exists(path)) return url;
286            }
287
288            if (pkg.PackageType == "Widget") 
289                return Utils.ApplicationRelativeWebRoot + "pics/Widget.png";
290
291            return Utils.ApplicationRelativeWebRoot + "pics/Theme.png";
292        }
293
294        #endregion
295    }
296}