The next generation of the Teknik Services. Written in ASP.NET. Fork for blog tags.
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.

PasteController.cs 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.Linq;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. using System.Web;
  8. using System.Web.Mvc;
  9. using Teknik.Pygments;
  10. using Teknik.Areas.Error.Controllers;
  11. using Teknik.Areas.Paste.ViewModels;
  12. using Teknik.Areas.Users.Utility;
  13. using Teknik.Controllers;
  14. using Teknik.Filters;
  15. using Teknik.Utilities;
  16. using Teknik.Models;
  17. using Teknik.Attributes;
  18. using Teknik.Utilities.Cryptography;
  19. namespace Teknik.Areas.Paste.Controllers
  20. {
  21. [TeknikAuthorize]
  22. public class PasteController : DefaultController
  23. {
  24. [TrackPageView]
  25. [AllowAnonymous]
  26. public ActionResult Index()
  27. {
  28. ViewBag.Title = "Paste - " + Config.Title;
  29. ViewBag.Description = "Paste your code or text easily and securely. Set an expiration, set a password, or leave it open for the world to see.";
  30. PasteCreateViewModel model = new PasteCreateViewModel();
  31. return View(model);
  32. }
  33. [TrackDownload]
  34. [AllowAnonymous]
  35. public ActionResult ViewPaste(string type, string url, string password)
  36. {
  37. TeknikEntities db = new TeknikEntities();
  38. Models.Paste paste = db.Pastes.Where(p => p.Url == url).FirstOrDefault();
  39. if (paste != null)
  40. {
  41. ViewBag.Title = ((string.IsNullOrEmpty(paste.Title)) ? string.Empty : paste.Title + " - ") + Config.Title + " Paste";
  42. ViewBag.Description = "Paste your code or text easily and securely. Set an expiration, set a password, or leave it open for the world to see.";
  43. // Increment Views
  44. paste.Views += 1;
  45. db.Entry(paste).State = EntityState.Modified;
  46. db.SaveChanges();
  47. // Check Expiration
  48. if (PasteHelper.CheckExpiration(paste))
  49. {
  50. db.Pastes.Remove(paste);
  51. db.SaveChanges();
  52. return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
  53. }
  54. PasteViewModel model = new PasteViewModel();
  55. model.Url = url;
  56. model.Content = paste.Content;
  57. model.Title = paste.Title;
  58. model.Syntax = paste.Syntax;
  59. model.DatePosted = paste.DatePosted;
  60. byte[] data = Encoding.UTF8.GetBytes(paste.Content);
  61. if (User.Identity.IsAuthenticated && type.ToLower() == "full")
  62. {
  63. Users.Models.User user = UserHelper.GetUser(db, User.Identity.Name);
  64. if (user != null)
  65. {
  66. model.Vaults = user.Vaults.ToList();
  67. }
  68. }
  69. // The paste has a password set
  70. if (!string.IsNullOrEmpty(paste.HashedPassword))
  71. {
  72. string hash = string.Empty;
  73. if (!string.IsNullOrEmpty(password))
  74. {
  75. byte[] passBytes = Utilities.SHA384.Hash(paste.Key, password);
  76. hash = passBytes.ToHex();
  77. // We need to convert old pastes to the new password scheme
  78. if (paste.Transfers.ToList().Exists(t => t.Type == TransferTypes.ASCIIPassword))
  79. {
  80. hash = Encoding.ASCII.GetString(passBytes);
  81. // Remove the transfer types
  82. paste.Transfers.Clear();
  83. db.Entry(paste).State = EntityState.Modified;
  84. db.SaveChanges();
  85. }
  86. }
  87. if (string.IsNullOrEmpty(password) || hash != paste.HashedPassword)
  88. {
  89. PasswordViewModel passModel = new PasswordViewModel();
  90. passModel.Url = url;
  91. passModel.Type = type;
  92. // Redirect them to the password request page
  93. return View("~/Areas/Paste/Views/Paste/PasswordNeeded.cshtml", passModel);
  94. }
  95. data = Convert.FromBase64String(paste.Content);
  96. // Now we decrypt the content
  97. byte[] ivBytes = Encoding.Unicode.GetBytes(paste.IV);
  98. byte[] keyBytes = AES.CreateKey(password, ivBytes, paste.KeySize);
  99. data = AES.Decrypt(data, keyBytes, ivBytes);
  100. model.Content = Encoding.Unicode.GetString(data);
  101. }
  102. if (type.ToLower() == "full" || type.ToLower() == "simple")
  103. {
  104. // Transform content into HTML
  105. if (!Highlighter.Lexers.ToList().Exists(l => l.Aliases.Contains(model.Syntax)))
  106. {
  107. model.Syntax = "text";
  108. }
  109. Highlighter highlighter = new Highlighter();
  110. // Add a space in front of the content due to bug with pygment (No idea why yet)
  111. model.Content = highlighter.HighlightToHtml(" " + model.Content, model.Syntax, Config.PasteConfig.SyntaxVisualStyle, generateInlineStyles: true, fragment: true);
  112. }
  113. switch (type.ToLower())
  114. {
  115. case "full":
  116. return View("~/Areas/Paste/Views/Paste/Full.cshtml", model);
  117. case "simple":
  118. return View("~/Areas/Paste/Views/Paste/Simple.cshtml", model);
  119. case "raw":
  120. return Content(model.Content, "text/plain");
  121. case "download":
  122. //Create File
  123. var cd = new System.Net.Mime.ContentDisposition
  124. {
  125. FileName = url,
  126. Inline = true
  127. };
  128. Response.AppendHeader("Content-Disposition", cd.ToString());
  129. return File(data, "application/octet-stream");
  130. default:
  131. return View("~/Areas/Paste/Views/Paste/Full.cshtml", model);
  132. }
  133. }
  134. return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
  135. }
  136. [HttpPost]
  137. [AllowAnonymous]
  138. public ActionResult Paste([Bind(Include = "Content, Title, Syntax, ExpireLength, ExpireUnit, Password, Hide")]PasteCreateViewModel model)
  139. {
  140. if (ModelState.IsValid)
  141. {
  142. if (Config.PasteConfig.Enabled)
  143. {
  144. try
  145. {
  146. using (TeknikEntities db = new TeknikEntities())
  147. {
  148. Models.Paste paste = PasteHelper.CreatePaste(db, model.Content, model.Title, model.Syntax, model.ExpireUnit, model.ExpireLength ?? 1, model.Password, model.Hide);
  149. if (model.ExpireUnit == "view")
  150. {
  151. paste.Views = -1;
  152. }
  153. if (User.Identity.IsAuthenticated)
  154. {
  155. Users.Models.User user = UserHelper.GetUser(db, User.Identity.Name);
  156. if (user != null)
  157. {
  158. paste.UserId = user.UserId;
  159. }
  160. }
  161. db.Pastes.Add(paste);
  162. db.SaveChanges();
  163. return Redirect(Url.SubRouteUrl("p", "Paste.View", new { type = "Full", url = paste.Url }));
  164. }
  165. }
  166. catch (Exception ex)
  167. {
  168. return Redirect(Url.SubRouteUrl("error", "Error.500", new { exception = ex }));
  169. }
  170. }
  171. Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  172. }
  173. return View("~/Areas/Paste/Views/Paste/Index.cshtml", model);
  174. }
  175. }
  176. }