PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

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

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