You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.5 KiB

  1. using System;
  2. using System.Globalization;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using System.Web;
  7. public class PostHandler : IHttpHandler
  8. {
  9. public void ProcessRequest(HttpContext context)
  10. {
  11. if (!context.User.Identity.IsAuthenticated || Blog.MatchesUniqueId(context))
  12. throw new HttpException(403, "No access");
  13. string mode = context.Request.QueryString["mode"];
  14. string id = context.Request.Form["id"];
  15. if (mode == "delete")
  16. {
  17. DeletePost(id);
  18. }
  19. else if (mode == "save")
  20. {
  21. EditPost(id, context.Request.Form["title"], context.Request.Form["content"], bool.Parse(context.Request.Form["isPublished"]), context.Request.Form["categories"].Split(','));
  22. }
  23. }
  24. private void DeletePost(string id)
  25. {
  26. Post post = Storage.GetAllPosts().FirstOrDefault(p => p.ID == id);
  27. if (post == null)
  28. throw new HttpException(404, "The post does not exist");
  29. Storage.Delete(post);
  30. }
  31. private void EditPost(string id, string title, string content, bool isPublished, string[] categories)
  32. {
  33. Post post = Storage.GetAllPosts().FirstOrDefault(p => p.ID == id);
  34. if (post != null)
  35. {
  36. post.Title = title;
  37. post.Content = content;
  38. post.Categories = categories;
  39. }
  40. else
  41. {
  42. post = new Post() { Title = title, Content = content, Slug = CreateSlug(title), Categories = categories };
  43. HttpContext.Current.Response.Write(post.Url);
  44. }
  45. SaveFilesToDisk(post);
  46. post.IsPublished = isPublished;
  47. Storage.Save(post);
  48. }
  49. private void SaveFilesToDisk(Post post)
  50. {
  51. foreach (Match match in Regex.Matches(post.Content, "(src|href)=\"(data:([^\"]+))\""))
  52. {
  53. string extension = Regex.Match(match.Value, "data:([^/]+)/([a-z]+);base64").Groups[2].Value;
  54. byte[] bytes = ConvertToBytes(match.Groups[2].Value);
  55. string path = Blog.SaveFileToDisk(bytes, extension);
  56. string value = string.Format("src=\"{0}\" alt=\"\" /", path);
  57. if (match.Groups[1].Value == "href")
  58. value = string.Format("href=\"{0}\"", path);
  59. post.Content = post.Content.Replace(match.Value, value);
  60. }
  61. }
  62. private byte[] ConvertToBytes(string base64)
  63. {
  64. int index = base64.IndexOf("base64,", StringComparison.Ordinal) + 7;
  65. return Convert.FromBase64String(base64.Substring(index));
  66. }
  67. public static string CreateSlug(string title)
  68. {
  69. title = title.ToLowerInvariant().Replace(" ", "-");
  70. title = RemoveDiacritics(title);
  71. title = Regex.Replace(title, @"([^0-9a-z-])", string.Empty);
  72. if (Storage.GetAllPosts().Any(p => string.Equals(p.Slug, title)))
  73. throw new HttpException(409, "Already in use");
  74. return title.ToLowerInvariant();
  75. }
  76. static string RemoveDiacritics(string text)
  77. {
  78. var normalizedString = text.Normalize(NormalizationForm.FormD);
  79. var stringBuilder = new StringBuilder();
  80. foreach (var c in normalizedString)
  81. {
  82. var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
  83. if (unicodeCategory != UnicodeCategory.NonSpacingMark)
  84. {
  85. stringBuilder.Append(c);
  86. }
  87. }
  88. return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
  89. }
  90. public bool IsReusable
  91. {
  92. get { return false; }
  93. }
  94. }