public async Task ShouldProcess(string cdnBaseUrl, string text, string expected) { var fileStore = new DefaultMediaFileStore( Mock.Of <IFileStore>(), "/media", cdnBaseUrl, Enumerable.Empty <IMediaEventHandler>(), Enumerable.Empty <IMediaCreatingEventHandler>(), Mock.Of <ILogger <DefaultMediaFileStore> >()); var sanitizer = new HtmlSanitizerService(Options.Create(new HtmlSanitizerOptions())); var defaultHttpContext = new DefaultHttpContext(); defaultHttpContext.Request.PathBase = new PathString("/tenant"); var httpContextAccessor = Mock.Of <IHttpContextAccessor>(hca => hca.HttpContext == defaultHttpContext); var options = Options.Create(new ResourceManagementOptions { CdnBaseUrl = cdnBaseUrl }); var assetUrlProvider = new AssetUrlShortcodeProvider(fileStore, httpContextAccessor, options); var processor = new ShortcodeService(new IShortcodeProvider[] { assetUrlProvider }, Enumerable.Empty <IShortcodeContextProvider>()); var processed = await processor.ProcessAsync(text); // The markdown part sanitizes after processing. var sanitized = sanitizer.Sanitize(processed); Assert.Equal(expected, sanitized); }
public async Task ShouldProcess(string cdnBaseUrl, string text, string expected) { var sanitizerOptions = new HtmlSanitizerOptions(); sanitizerOptions.Configure.Add(opt => opt.AllowedAttributes.Add("class")); var fileStore = new DefaultMediaFileStore( Mock.Of <IFileStore>(), "/media", cdnBaseUrl, Enumerable.Empty <IMediaEventHandler>(), Enumerable.Empty <IMediaCreatingEventHandler>(), Mock.Of <ILogger <DefaultMediaFileStore> >()); var sanitizer = new HtmlSanitizerService(Options.Create(sanitizerOptions)); var defaultHttpContext = new DefaultHttpContext(); defaultHttpContext.Request.PathBase = new PathString("/tenant"); var httpContextAccessor = Mock.Of <IHttpContextAccessor>(hca => hca.HttpContext == defaultHttpContext); var options = Options.Create(new ResourceManagementOptions { CdnBaseUrl = cdnBaseUrl }); var imageProvider = new ImageShortcodeProvider(fileStore, sanitizer, httpContextAccessor, options); var processor = new ShortcodeService(new IShortcodeProvider[] { imageProvider }, Enumerable.Empty <IShortcodeContextProvider>()); var processed = await processor.ProcessAsync(text); Assert.Equal(expected, processed); }
public ReplyController( IOptions <AppSettingsModel> appSettings, BlogContext db, UsersContext udb, AdminUtil adminUtil, BlogUtil blogUtil, ExpUtil expUtil, MessageUtil msgUtil, RatingUtil ratingUtil, IWebHostEnvironment env, IMemoryCache cache, ICompositeViewEngine viewEngine, IActionContextAccessor actionAccessor, HtmlSanitizerService sanitizerService) { _appSettings = appSettings.Value; _db = db; _udb = udb; _adminUtil = adminUtil; _blogUtil = blogUtil; _cache = cache; _env = env; _expUtil = expUtil; _ratingUtil = ratingUtil; _msgUtil = msgUtil; _viewEngine = viewEngine; _actionAccessor = actionAccessor; _sanitizerService = sanitizerService; }
public void ShouldSanitizeUnprocessed(string text, string expected) { // The html parts santize on save, so do not process the shortcode first. var sanitizer = new HtmlSanitizerService(Options.Create(new HtmlSanitizerOptions())); var sanitized = sanitizer.Sanitize(text); Assert.Equal(expected, sanitized); }
public void IsValid_ShouldValidateHtml(string value, bool isValid) { var htmlSanitizer = new HtmlSanitizerService(new Mock <ILogger <HtmlSanitizerService> >().Object); var actual = htmlSanitizer.IsValid(value); Assert.Equal(isValid, actual); }
public void Sanitize_ShouldSanitizeHtml(string unsanitized, string sanitized) { var htmlSanitizer = new HtmlSanitizerService(new Mock <ILogger <HtmlSanitizerService> >().Object); var actual = htmlSanitizer.Sanitize(unsanitized); Assert.Equal(sanitized, actual); }
public PrivateMessageController(IFolkeConnection session, IForumUserService <TUser, TUserView> accountService, ForumsDataMapping <TUser, TUserView> forumsDataMapping, HtmlSanitizerService <TUser> htmlSanitizerService) { this.session = session; this.accountService = accountService; this.forumsDataMapping = forumsDataMapping; this.htmlSanitizerService = htmlSanitizerService; }
public ThreadController(IFolkeConnection session, IForumUserService <TUser, TUserView> accountService, ForumsDataMapping <TUser, TUserView> forumsDataMapping, HtmlSanitizerService <TUser> htmlSanitizerService, CommentService <Thread <TUser>, CommentInThread <TUser>, TUser, TUserView> commentService) { this.session = session; this.accountService = accountService; this.forumsDataMapping = forumsDataMapping; this.htmlSanitizerService = htmlSanitizerService; this.commentService = commentService; }
public ReplyController( BlogContext db, AdminUtil adminUtil, BlogUtil blogUtil, RatingUtil ratingUtil, HtmlSanitizerService sanitizerService) { _db = db; _adminUtil = adminUtil; _blogUtil = blogUtil; _ratingUtil = ratingUtil; _sanitizerService = sanitizerService; }
public ReplyController( IOptions <AppSettingsModel> appSettings, BlogContext db, UsersContext udb, AdminUtil adminUtil, BlogUtil blogUtil, ExpUtil expUtil, MessageUtil msgUtil, RatingUtil ratingUtil, HtmlSanitizerService sanitizerService) { _appSettings = appSettings.Value; _db = db; _udb = udb; _adminUtil = adminUtil; _blogUtil = blogUtil; _expUtil = expUtil; _ratingUtil = ratingUtil; _msgUtil = msgUtil; _sanitizerService = sanitizerService; }
// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddMvc(option => { option.EnableEndpointRouting = false; option.CacheProfiles.Add("Never", new CacheProfile { Location = ResponseCacheLocation.None, NoStore = true }); option.Filters.Add(typeof(GlobalExceptionFilter)); var SslPort = Configuration.GetSection("ApplicationSettings").GetValue <string>("HttpsPort"); if (!string.IsNullOrEmpty(SslPort)) { option.SslPort = int.Parse(SslPort); } }) .SetCompatibilityVersion(CompatibilityVersion.Latest) .AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver(); }) .AddSessionStateTempDataProvider(); services.Configure <MvcOptions>(o => { var serviceProvider = services.BuildServiceProvider(); var readerFactory = serviceProvider.GetRequiredService <IHttpRequestStreamReaderFactory>(); o.ModelBinderProviders.Insert(0, new DefaultHybridModelBinderProvider(o.InputFormatters, readerFactory)); }); services.AddOptions(); services.AddSingleton(Configuration); services.Configure <AppSettingsModel>(Configuration.GetSection("ApplicationSettings")); services.Configure <EmailSender.EmailSettings>(Configuration.GetSection("EmailSettings")); services.Configure <ElasticSearchProvider.ElasticSearchSettings>(Configuration.GetSection("ElasticSearchSettings")); services.Configure <RegisterSettingsModel>(ConfigFromDataFile("App_Data/RegisterSettings.json")); services.Configure <DataSettingsModel>(ConfigFromDataFile("App_Data/DataSettings.json")); services.Configure <BackgroundSetting>(ConfigFromDataFile("App_Data/BackgroundSetting.json")); services.Configure <Models.App.AuditExamConfig>(ConfigFromDataFile("App_Data/AuditExam.json")); services.Configure <Models.App.RaffleConfig>(ConfigFromDataFile("App_Data/RaffleConfig.json")); services.Configure <Models.App.WheelConfig>(ConfigFromDataFile("App_Data/WheelConfig.json")); services.AddMemoryCache(); services.AddSession(); services.AddScoped(p => new BlogContext(_dataDbConnectionString, p.GetRequiredService <ILoggerFactory>())); services.AddScoped(p => new UsersContext(_userDbConnectionString, p.GetRequiredService <ILoggerFactory>())); services.AddIdentity <UserProfile, AspNetCore.Identity.EntityFramework6.IdentityRole>(options => { options.Password.RequireDigit = false; options.Password.RequireLowercase = false; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = false; options.User.RequireUniqueEmail = true; options.User.AllowedUserNameCharacters = string.Empty; }) .AddUserStore <UserStore <UserProfile, UsersContext> >() .AddRoleStore <RoleStore <UsersContext> >() .AddErrorDescriber <GmIdentityErrorDescriber>() .AddDefaultTokenProviders(); services.ConfigureApplicationCookie(options => { options.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.None; options.AccessDeniedPath = "/403.html"; options.Events.OnRedirectToLogin = ctx => { if (ctx.Request.Path.StartsWithSegments("/api") && ctx.Response.StatusCode == (int)System.Net.HttpStatusCode.OK) { ctx.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized; } else { ctx.Response.Redirect(ctx.RedirectUri); } return(Task.CompletedTask); }; }); services.AddAuthorization(option => { option.AddPolicy("Harmony", policy => policy.AddRequirements(new HarmonyRequirement())); option.AddPolicy("AdminAccess", policy => policy.AddRequirements(new AdminAccessRequirement())); }); services.AddCors(option => { option.AddPolicy("GmAppOrigin", builder => builder.WithOrigins(IsDev ? SiteConstant.DevAppHostOrigins : SiteConstant.AppHostOrigins) .AllowAnyHeader() .AllowCredentials() .AllowAnyMethod()); }); services.AddAntiforgery(a => a.HeaderName = "X-CSRF-TOKEN"); services.AddSingleton <IAuthorizationHandler, HarmonyHandler>(); services.AddSingleton <IAuthorizationHandler, AdminAccessHandler>(); if (_env.IsProduction()) { services.AddSingleton(provider => { var scheduler = new SchedulerService( provider.GetRequiredService <IServiceScopeFactory>(), provider.GetRequiredService <IWebHostEnvironment>(), provider.GetRequiredService <IMemoryCache>(), provider.GetRequiredService <IOptions <AppSettingsModel> >(), provider.GetRequiredService <ILoggerFactory>()); JobManager.Initialize(scheduler); return(scheduler); }); } services.AddScoped <JobTaskRunner>(); services.AddSingleton <BackgroundTaskQueue>(); services.AddHostedService <BackgroundJobService>(); services.AddSingleton <QuestService>(); services.AddSingleton <IVisitCounter>(s => { if (_env.IsStaging()) { return(new ReadonlyVisitCounter(s.GetRequiredService <IServiceScopeFactory>())); } else { return(new VisitCounter(s.GetRequiredService <IServiceScopeFactory>())); } }); services.AddSingleton <CacheService>(); services.AddSingleton(_ => HtmlSanitizerService.CreateInstance()); services.AddScoped <ContextlessBlogUtil>(); services.AddScoped <BlogUtil>(); services.AddScoped <AdminUtil>(); services.AddScoped <CategoryUtil>(); services.AddScoped <ConstantUtil>(); services.AddScoped <ExpUtil>(); services.AddScoped <ImageUtil>(); services.AddScoped <IUpload, LinodeUtil>(); services.AddScoped <MessageUtil>(); services.AddScoped <RatingUtil>(); services.AddScoped <TagUtil>(); services.AddScoped <TopicUtil>(); services.AddScoped <UploadUtil>(); services.AddScoped <WidgetUtil>(); services.AddScoped <IRecommendationProvider, ElasticSearchProvider>(); bool enabelES = Configuration.GetSection("ApplicationSettings").GetValue <string>("SearchBackendType") == "ElasticSearch"; if (enabelES) { services.AddScoped <ISearchProvider, ElasticSearchProvider>(); } else { services.AddScoped <ISearchProvider, DbBlogSearchProvider>(); } services.AddScoped <DbBlogSearchProvider>(); services.AddTransient <HtmlUtil>(); services.AddTransient <GachaBonusService>(); services.AddTransient <INickNameProvider, TitleNickNameProvider>(); services.AddSingleton(ElasticSearchProvider.CreateClient); if (enabelES && !Configuration.GetSection("ElasticSearchSettings").GetValue <bool>("Readonly")) { services.AddSingleton <ElasticSearchUpdateService>(); } services.AddSingleton <EmailSender>(); services.AddSingleton <IActionContextAccessor, ActionContextAccessor>(); services.AddScoped(provider => { var factory = provider.GetService <IUrlHelperFactory>(); var actionContext = provider.GetService <IActionContextAccessor>(); return(factory.GetUrlHelper(actionContext.ActionContext)); }); services.Configure <WebEncoderOptions>(options => { options.TextEncoderSettings = new TextEncoderSettings(System.Text.Unicode.UnicodeRanges.All); }); services.AddLogging(builder => { if (IsDev) { builder.AddConsole(); builder.AddDebug(); builder.AddEventSourceLogger(); } builder.AddSerilog(); }); }
public async Task <ActionResult> Edit([FromServices] HtmlSanitizerService sanitizerService, int id, BlogEdit blog, IFormFile[] files, bool setmain = false) { ViewBag.CategoryList = _catUtil.GetCategoryDropdown(blog.CategoryID); ViewBag.id = id; if (NolinkCategories == null || !NolinkCategories.Contains(blog.CategoryID)) { if (blog.BlogLinks == null) { ModelState.AddModelError("", "链接地址不能为空"); return(View(blog)); } else { blog.BlogLinks = blog.BlogLinks.Where(b => !string.IsNullOrWhiteSpace(b.url)).ToArray(); if (!BlogHelper.checkBlogLinks(blog.BlogLinks)) { ModelState.AddModelError("", "链接地址不能为空,且不得包含javascript"); return(View(blog)); } } } if (blog.Content == null || string.IsNullOrWhiteSpace(BlogHelper.removeAllTags(blog.Content))) { ModelState.AddModelError("", "内容不能为空或纯图片"); return(View(blog)); } if (!_blogUtil.CheckAdmin()) { blog.Content = sanitizerService.Sanitize(blog.Content); } if (ModelState.IsValid) { Blog originalblog = _db.Blogs.Find(id); bool hasupload = false; List <string> dellist = null; List <string> newlist = null; string thumb = null; string newthumb = null; string[] originalImglist = originalblog.ImagePath?.Split(';') ?? new string[] { }; string[] currentImglist = blog.ImagePath?.Split(';') ?? new string[] { }; int imgcount = currentImglist.Length; bool[] uploadpos = null; if (originalblog.option != null) { originalblog.option.MergeWith(_blogUtil, blog.Option); } else if (!blog.Option.OverrideOption(_blogUtil).IsDefault()) { originalblog.option = blog.Option; } if (originalblog.IsLocalImg) { dellist = originalImglist.ToList(); thumb = dellist.First(); } if (currentImglist.Length != 0) //item has local image & might or might not changed { // foreach name in current imglist, if orignal imglist does not contain the name,it is not valid if (!currentImglist.All(n => originalImglist.Contains(n))) { ModelState.AddModelError("", "内部参数错误,请刷新重试"); return(View(blog)); } // foreach name in orignial imglist, if current imglist does not contain the name,delete it dellist = originalImglist.Except(currentImglist).ToList(); originalblog.ImagePath = blog.ImagePath; } if (files != null) { uploadpos = new bool[files.Length]; imgcount += files.Where(f => f != null).Count(); for (int i = 0; i < files.Length; i++) { var data = files[i]; if (data != null) { if (data.Length > 1048576 * 4 || !data.ContentType.Contains("image")) { ModelState.AddModelError("", "单个文件不得超过4MB,且必须是图片"); return(View(blog)); } hasupload = true; uploadpos[i] = true; } else { uploadpos[i] = false; } } } if (hasupload) // has upload file { try { newlist = await _uploadUtil.SaveImagesAsync(files, false); } catch (Exception e) { ModelState.AddModelError("", "保存图片时发生异常:(" + e.Message + ")。如多次出错,请汇报给管理员。"); return(View(blog)); } if (newlist.Count < 1) { ModelState.AddModelError("", "图片服务器上传出错,请稍后再试。如多次出错,请汇报给管理员。"); return(View(blog)); } int i = 0; if (originalblog.IsLocalImg && setmain && files[0] != null && currentImglist.Length > 0) { List <string> updatedImgList = new List <string>(currentImglist); updatedImgList.Insert(0, newlist[0]); updatedImgList.AddRange(newlist.Skip(1)); originalblog.ImagePath = string.Join(";", updatedImgList); blog.Content = BlogHelper.InsertImgPlaceholder(blog.Content); i++; } else if (!originalblog.IsLocalImg) { originalblog.ImagePath = string.Join(";", newlist); } else { originalblog.ImagePath = string.Join(";", currentImglist.Concat(newlist)); } blog.Content = BlogHelper.ReplaceNewImgPlaceholder(blog.Content, i, currentImglist.Length, uploadpos); originalblog.IsLocalImg = true; } if (!originalblog.IsLocalImg || imgcount == 0) //no img no upload { string imgname = BlogHelper.getFirstImg(blog.Content); if (imgname == null || imgname.Length < 5) { ModelState.AddModelError("", "请添加预览图!(上传或外链图片)"); blog.ImagePath = originalblog.ImagePath; return(View(blog)); } originalblog.ImagePath = imgname; originalblog.IsLocalImg = false; } else { newthumb = originalblog.ImagePath.Split(';').ToList().First(); } var mention = new MentionHandler(_udb); blog.Content = mention.ParseMentions(blog.Content); mention.SendMentionMsg(_msgUtil, originalblog.Author, originalblog.BlogTitle, Url.Action("Details", new { id = originalblog.BlogID })); if (blog.Option != null && (originalblog.option != null || !blog.Option.IsDefault())) { originalblog.option = blog.Option; } // else image uploaded before and did not changed string[] tags = TagUtil.SplitTags(blog.BlogTags); List <Tag> updatedTags = null; try { // Replace 【】() with []() originalblog.BlogTitle = blog.BlogTitle.ToSingleByteCharacterString(); originalblog.Content = BlogHelper.RemoveComments(blog.Content); originalblog.CategoryID = blog.CategoryID; originalblog.Links = Newtonsoft.Json.JsonConvert.SerializeObject(blog.BlogLinks); if (blog.Option.NoApprove) { originalblog.isApproved = false; } else if (originalblog.isApproved == false) { originalblog.isApproved = null; } else if (originalblog.isApproved == null) { // Remove pending votes since the blog has changed. var audits = _db.BlogAudits.Where(b => b.BlogID == originalblog.BlogID).ToList(); var lastDecision = audits.Where(ba => ba.AuditAction == BlogAudit.Action.Approve || ba.AuditAction == BlogAudit.Action.Deny).OrderByDescending(ba => ba.BlogVersion).FirstOrDefault(); int lastVersion = lastDecision == null ? 0 : lastDecision.BlogVersion; _db.BlogAudits.RemoveRange(audits.Where(ba => ba.BlogVersion > lastVersion && (ba.AuditAction == BlogAudit.Action.VoteApprove || ba.AuditAction == BlogAudit.Action.VoteDeny))); } updatedTags = _tagUtil.SetTagsForBlog(originalblog.BlogID, tags, originalblog.Author); originalblog.isHarmony = BlogHelper.BlogIsHarmony(_db, originalblog, HarmonySettings); _db.SaveChanges(); } catch { if (originalblog.IsLocalImg && newlist != null) { await _uploadUtil.DeleteFilesAsync(newlist); } throw; } if (dellist != null && dellist.Count > 0) { await _uploadUtil.DeleteFilesAsync(dellist); } if (thumb != null && thumb != newthumb && blog.IsLocalImg) { await _uploadUtil.DeleteFileAsync(thumb.Replace("/upload/", "/thumbs/")); } if (originalblog.IsLocalImg && thumb != newthumb) { await _uploadUtil.SaveThumbAsync(originalblog.ImagePath); } if (originalblog.Author != User.Identity.Name) { _adminUtil.log(User.Identity.Name, "editblog", originalblog.BlogID.ToString()); } TriggerEditBlog(originalblog, updatedTags); return(RedirectToAction("Details", new { id })); } return(View(blog)); }
public async Task <ActionResult> Create(BlogEdit blog, [FromServices] HtmlSanitizerService sanitizerService) { ViewBag.CategoryList = _catUtil.GetCategoryDropdown(); ViewBag.UserHanGroup = GetUserHanGroup(); string content = blog.Content; bool isLocalimg = false; Blog newblog; List <string> imglist = null; try { if (!ModelState.IsValid) { throw new BlogException(); } if (content == null || string.IsNullOrWhiteSpace(BlogHelper.removeAllTags(content))) { ModelState.AddModelError("", "内容不能为空或纯图片"); throw new BlogException(); } if (NolinkCategories == null || !NolinkCategories.Contains(blog.CategoryID)) { if (blog.BlogLinks == null) { ModelState.AddModelError("", "链接地址不能为空"); throw new BlogException(); } else { blog.BlogLinks = blog.BlogLinks.Where(b => !string.IsNullOrWhiteSpace(b.url)).ToArray(); if (!BlogHelper.checkBlogLinks(blog.BlogLinks)) { ModelState.AddModelError("", "链接地址不能为空,且不得包含javascript"); throw new BlogException(); } } } if (!_blogUtil.CheckAdmin()) { content = sanitizerService.Sanitize(content); } if (blog.HanGroupID.HasValue && !_db.HanGroupMembers.Any(h => h.Username == User.Identity.Name && h.HanGroupID == blog.HanGroupID)) { ModelState.AddModelError("", "汉化组ID无效,请刷新重试。"); throw new BlogException(); } List <IFormFile> BlogImages = new List <IFormFile>(); if (Request.Form.Files.Count > 0) { for (int i = 0; i < Request.Form.Files.Count; i++) { var file = Request.Form.Files[i]; if (file.Length > 0) { if (!file.ContentType.Contains("image")) { ModelState.AddModelError("", "不接受的文件类型"); throw new BlogException(); } else if (file.Length > 1048576 * 4) { ModelState.AddModelError("", "文件不得超过4MB"); throw new BlogException(); } isLocalimg = true; BlogImages.Add(file); } else { content = BlogHelper.removeImgPlaceholder(content, i); } } } if (!isLocalimg) { var imgname = BlogHelper.getFirstImg(content); if (imgname == null || imgname.Length < 5) { ModelState.AddModelError("", "请添加预览图!(上传或在文中外链图片)"); throw new BlogException(); } imglist = new List <string>() { imgname }; } else { try { imglist = await _uploadUtil.SaveImagesAsync(BlogImages); } catch (Exception e) { ModelState.AddModelError("", "保存图片时发生异常:(" + e.Message + ")。如多次出错,请汇报给管理员。"); throw new BlogException(e.Message, e); } if (imglist.Count < 1) { ModelState.AddModelError("", "图片服务器上传出错,请稍后再试。如多次出错,请汇报给管理员。"); throw new BlogException(); } } string imgpath = string.Empty; if (imglist != null) { imgpath = string.Join(";", imglist); } bool approve = User.IsInRole("Administrator") || User.IsInRole("Writers") || User.IsInRole("Moderator"); // Replace 【】() with []() blog.BlogTitle = blog.BlogTitle.ToSingleByteCharacterString(); blog.ImagePath = imgpath; content = BlogHelper.RemoveComments(content); newblog = _blogUtil.AddBlog(blog.BlogTitle, content, blog.CategoryID, imgpath, User.Identity.Name, approve, isLocalimg, blog.BlogLinks); var taglist = new List <Tag>(); if (!string.IsNullOrEmpty(blog.BlogTags)) { string[] tags = TagUtil.SplitTags(blog.BlogTags); taglist = _tagUtil.AddTagsForBlog(newblog.BlogID, tags, newblog.Author); } var save = false; if (BlogHelper.BlogIsHarmony(_db, newblog, HarmonySettings)) { newblog.isHarmony = true; save = true; } if (blog.HanGroupID.HasValue) { _db.HanGroupBlogs.Add(new HanGroupBlog { BlogID = newblog.BlogID, HanGroupID = blog.HanGroupID.Value }); save = true; } if (blog.Option != null && !blog.Option.IsDefault()) { newblog.option = blog.Option.OverrideOption(_blogUtil); if (newblog.option.NoApprove) { newblog.isApproved = false; } save = true; } if (save) { _db.SaveChanges(); } TriggerNewBlog(newblog, taglist); } catch (BlogException e) { if (Request.IsAjaxRequest()) { return(Json(new { err = e.Message + string.Join(";", ModelState.Values.SelectMany(m => m.Errors) .Select(err => err.ErrorMessage) .ToList()) })); } return(View(blog)); } catch { if (isLocalimg && imglist != null) { await _uploadUtil.DeleteFilesAsync(imglist.Concat(new[] { blog.ImagePath.Split(';')[0].Replace("/upload/", "/thumbs/") })); } throw; } if (Request.IsAjaxRequest()) { return(Json(new { id = newblog.BlogID, src = BlogHelper.firstImgPath(newblog, true) })); } return(RedirectToAction("Details", new { id = newblog.BlogID })); }
public async Task <ActionResult> Edit(int id, TopicEdit etopic, [FromServices] HtmlSanitizerService sanitizerService) { etopic.LoadBlog(_db); ViewBag.CategoryID = new SelectList(_catUtil.GetCategoryList(), "CategoryID", "CategoryName", etopic.CategoryID); int ret = TagUtil.CheckBlogTag(etopic.TagName, 1); if (ret != 0) { ModelState.AddModelError("", ret > 0 ? "专题标签只能有1个" : "标签不得超过20个字符"); } else if (!_blogUtil.CheckAdmin()) { etopic.Content = sanitizerService.Sanitize(etopic.Content); } else if (ModelState.IsValid) { var topic = _db.Topics.Find(id); bool uploadsaved = false; bool bannersaved = false; var blogcurrent = _db.BlogsInTopics.Where(bi => bi.TopicID == id).ToList(); foreach (var blog in blogcurrent) { _db.BlogsInTopics.Remove(blog); } int i = 0; foreach (var bid in etopic.BlogIDs.Distinct()) { var b = etopic.Blogs.SingleOrDefault(bb => bb.BlogID == bid); if (b == null) { ModelState.AddModelError("", "未找到ID编号为" + bid + "的资源"); return(View(topic)); } var blogintopic = new BlogsInTopic { blog = b, topic = topic, BlogOrder = i++ }; _db.BlogsInTopics.Add(blogintopic); } if (topic.tag.TagName != etopic.TagName) { var tag = _db.Tags.SingleOrDefault(t => t.TagName == etopic.TagName); if (tag == null) { tag = new Tag { TagName = etopic.TagName }; } topic.tag = tag; } try { var originalImage = topic.ImagePath; var originalBanner = topic.BannerPath; bool shouldDeleteOldImage = false; bool shouldDeleteOldBanner = string.IsNullOrWhiteSpace(etopic.BannerPath); if (etopic.TopicImage != null) { shouldDeleteOldImage = topic.isLocalImg; topic.isLocalImg = true; var imglist = await _uploadUtil.SaveImagesAsync(new IFormFile[] { etopic.TopicImage }, true); if (imglist.Count < 1) { ModelState.AddModelError("", "保存图片时发生异常。请尝试转换图片格式后再次上传。如多次出错,请汇报给管理员。"); return(View(etopic)); } topic.ImagePath = imglist[0]; uploadsaved = true; } else if (!topic.isLocalImg || (topic.isLocalImg && !etopic.IsLocalImg)) { string imgname = BlogHelper.getFirstImg(etopic.Content); if (imgname == null || imgname.Length < 5) { ModelState.AddModelError("", "请添加预览图!(上传或在文中外链图片)"); return(View(etopic)); } shouldDeleteOldImage = !etopic.IsLocalImg; topic.isLocalImg = false; topic.ImagePath = imgname; } if (etopic.TopicBanner != null) { var imglist = await _uploadUtil.SaveImagesAsync(new IFormFile[] { etopic.TopicBanner }, false); if (imglist.Count < 1) { ModelState.AddModelError("", "图片服务器上传出错,请尝试转换图片格式后再次上传。如多次出错,请汇报给管理员。"); return(View(topic)); } shouldDeleteOldBanner = true; bannersaved = true; topic.BannerPath = imglist[0]; } else { topic.BannerPath = etopic.BannerPath; } if (shouldDeleteOldBanner && !string.IsNullOrWhiteSpace(originalBanner)) { await _uploadUtil.DeleteFileAsync(originalBanner); } if (shouldDeleteOldImage && !string.IsNullOrWhiteSpace(originalImage)) { await _uploadUtil.DeleteFilesAsync(new[] { originalImage, originalImage.Replace("/upload/", "/thumbs/") }); } topic.UpdateDate = DateTime.Now; topic.TopicTitle = etopic.TopicTitle; topic.CategoryID = etopic.CategoryID; var mention = new MentionHandler(_udb); topic.Content = mention.ParseMentions(BlogHelper.RemoveComments(etopic.Content)); mention.SendMentionMsg(_msgUtil, User.Identity.Name, etopic.TopicTitle, Url.Action("Details", new { id = topic.TopicID })); _db.Entry(topic).State = EntityState.Modified; _db.SaveChanges(); TriggerEditTopic(topic); if (User.Identity.Name != topic.Author) { _adminUtil.log(User.Identity.Name, "edittopic", topic.TopicID.ToString()); } } catch { if (uploadsaved) { await _uploadUtil.DeleteFilesAsync(new[] { topic.ImagePath, topic.ImagePath.Replace("/upload/", "/thumbs/") }); } if (bannersaved) { await _uploadUtil.DeleteFileAsync(topic.BannerPath); } throw; } return(RedirectToAction("Details", new { id })); } return(View(etopic)); }
public async Task <ActionResult> Create(TopicEdit topic, [FromServices] HtmlSanitizerService sanitizerService) { ViewBag.CategoryID = sl; topic.LoadBlog(_db); if (ModelState.IsValid) { Topic ntopic = new Topic(); if (!_blogUtil.CheckAdmin()) { topic.Content = sanitizerService.Sanitize(topic.Content); } int i = 0; foreach (var bid in topic.BlogIDs.Distinct()) { var b = topic.Blogs.SingleOrDefault(bb => bb.BlogID == bid); if (b == null) { ModelState.AddModelError("", "未找到ID编号为" + bid + "的资源"); return(View(topic)); } var blogintopic = new BlogsInTopic { blog = b, topic = ntopic, BlogOrder = i++ }; _db.BlogsInTopics.Add(blogintopic); } ntopic.Author = User.Identity.Name; ntopic.CategoryID = topic.CategoryID; ntopic.Content = topic.Content; ntopic.CreateDate = DateTime.Now; ntopic.UpdateDate = DateTime.Now; ntopic.TopicVisit = 0; ntopic.TopicTitle = topic.TopicTitle; if (topic.TopicImage != null) { //ValidateFileAttribute里已经检查过了 ntopic.isLocalImg = true; var imglist = await _uploadUtil.SaveImagesAsync(new IFormFile[] { topic.TopicImage }); if (imglist.Count < 1) { ModelState.AddModelError("", "图片服务器上传出错,请稍后再试。如多次出错,请汇报给管理员。"); return(View(topic)); } ntopic.ImagePath = imglist[0]; } else { string imgname = BlogHelper.getFirstImg(ntopic.Content); if (imgname == null || imgname.Length < 5) { ModelState.AddModelError("", "请添加预览图!(上传或在文中外链图片)"); return(View(topic)); } ntopic.ImagePath = imgname; } if (topic.TopicBanner != null) { var imglist = await _uploadUtil.SaveImagesAsync(new IFormFile[] { topic.TopicBanner }, false); if (imglist.Count < 1) { ModelState.AddModelError("", "图片服务器上传出错,请稍后再试。如多次出错,请汇报给管理员。"); return(View(topic)); } ntopic.BannerPath = imglist[0]; } var tag = _db.Tags.SingleOrDefault(t => t.TagName == topic.TagName); if (tag == null) { tag = new Tag { TagName = topic.TagName }; } ntopic.tag = tag; var mention = new MentionHandler(_udb); ntopic.Content = mention.ParseMentions(BlogHelper.RemoveComments(ntopic.Content)); _db.Topics.Add(ntopic); _db.SaveChanges(); mention.SendMentionMsg(_msgUtil, ntopic.Author, ntopic.TopicTitle, Url.Action("Details", new { id = ntopic.TopicID })); TriggerNewTopic(ntopic); return(RedirectToAction("Details", new { id = ntopic.TopicID })); } return(View(topic)); }