public static void SendNoticeToAdmin(string subject, string content, MimeType mime) { UserBE adminUser = UserBL.GetAdmin(); ; if (adminUser == null) { throw new DreamAbortException(DreamMessage.InternalError(DekiResources.CANNOT_RETRIEVE_ADMIN_ACCOUNT)); } string smtphost = string.Empty; int smtpport = 0; if (smtphost == string.Empty) throw new DreamAbortException(DreamMessage.Conflict(DekiResources.SMTP_SERVER_NOT_CONFIGURED)); if (string.IsNullOrEmpty(adminUser.Email)) throw new DreamAbortException(DreamMessage.Conflict(DekiResources.ADMIN_EMAIL_NOT_SET)); System.Net.Mail.SmtpClient smtpclient = new System.Net.Mail.SmtpClient(); System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(); msg.To.Add(adminUser.Email); msg.From = new System.Net.Mail.MailAddress(DekiContext.Current.User.Email, DekiContext.Current.User.Name); msg.Subject = DekiContext.Current.Instance.SiteName + ": " + subject; msg.Body = content; smtpclient.Host = smtphost; if (smtpport != 0) smtpclient.Port = smtpport; smtpclient.Send(msg); }
//--- Methods --- public void SendNoticeToAdmin(string subject, string content, MimeType mime) { // TODO (arnec): should this be using the email service? UserBE adminUser = UserBL.GetAdmin(); if(adminUser == null) { throw new SiteNoAdminFatalException(); } string smtphost = string.Empty; int smtpport = 0; if(smtphost == string.Empty) { throw new SiteConflictException(DekiResources.SMTP_SERVER_NOT_CONFIGURED()); } if(string.IsNullOrEmpty(adminUser.Email)) { throw new SiteConflictException(DekiResources.ADMIN_EMAIL_NOT_SET()); } var smtpclient = new SmtpClient(); var msg = new MailMessage(); msg.To.Add(adminUser.Email); msg.From = new MailAddress(_user.Email, _user.Name); msg.Subject = _dekiInstance.SiteName + ": " + subject; msg.Body = content; smtpclient.Host = smtphost; if(smtpport != 0) { smtpclient.Port = smtpport; } smtpclient.Send(msg); }
public ResourceContentBE(string value, MimeType mimeType) : this(true) { if(value == null) { throw new ArgumentNullException("value"); } if(mimeType == null) { throw new ArgumentNullException("mimeType"); } _mimeType = mimeType; _stream = new ChunkedMemoryStream(); _stream.Write(mimeType.CharSet, value); _size = (uint)_stream.Length; }
public ResourceContentBE(Stream stream, MimeType mimeType) : this(true) { if(stream == null) { throw new ArgumentNullException("stream"); } if(mimeType == null) { throw new ArgumentNullException("mimeType"); } if(!stream.IsStreamMemorized()) { throw new ArgumentException("The provided stream must be a supported memory stream type"); } _stream = stream; _size = (uint)stream.Length; _mimeType = mimeType; }
/* ========================================================================= * Asynchronous methods * =======================================================================*/ /// <summary> /// <para>Adds an attachment to a document. The document revision must be /// specified when using this method.</para> /// <para>(This method is asynchronous.)</para> /// </summary> /// <param name="id">ID of the CouchDB document.</param> /// <param name="rev">Revision of the CouchDB document.</param> /// <param name="attachment">Stream of the attachment. Will be closed once /// the request is sent.</param> /// <param name="attachmentLength">Length of the attachment stream.</param> /// <param name="fileName">Filename of the attachment.</param> /// <param name="contentType">Content type of the document.</param> /// <param name="result"></param> /// <returns></returns> public Result<JObject> AddAttachment( string id, string rev, Stream attachment, long attachmentLength, string fileName, MimeType contentType, Result<JObject> result) { if (String.IsNullOrEmpty(id)) throw new ArgumentNullException("id"); if (String.IsNullOrEmpty(rev)) throw new ArgumentNullException("rev"); if (attachment == null) throw new ArgumentNullException("attachment"); if (attachmentLength < 0) throw new ArgumentOutOfRangeException("attachmentLength"); if (String.IsNullOrEmpty(fileName)) throw new ArgumentNullException("fileName"); if (contentType == null) throw new ArgumentNullException("contentType"); if (result == null) throw new ArgumentNullException("result"); BasePlug .AtPath(XUri.EncodeFragment(id)) .At(XUri.EncodeFragment(fileName)) .With(Constants.REV, rev) .Put(DreamMessage.Ok(contentType, attachmentLength, attachment), new Result<DreamMessage>()) .WhenDone( a => { if (a.Status == DreamStatus.Created) result.Return(JObject.Parse(a.ToText())); else result.Throw(new CouchException(a)); }, result.Throw ); return result; }
public StreamInfo(Stream stream, long size, MimeType type, DateTime? modified) { if(stream == null) { throw new ArgumentNullException("stream"); } this.Stream = stream; this.Length = size; this.Type = type ?? MimeType.BINARY; this.Modified = modified; }
public virtual ResourceBE BuildRevForContentUpdate(ResourceBE currentResource, MimeType mimeType, uint size, string description, string name, ResourceContentBE newContent) { ResourceBE newRev = BuildRevForExistingResource(currentResource, mimeType, size, description); newRev.Content = newContent; newRev.ContentId = 0; newRev.ChangeMask |= ResourceBE.ChangeOperations.CONTENT; if(name != null && !StringUtil.EqualsInvariant(name, newRev.Name)) { newRev.ChangeMask |= ResourceBE.ChangeOperations.NAME; newRev.Name = name; } return newRev; }
private ResourceBE BuildRevForNewResource(string resourcename, MimeType mimeType, uint size, string description, ResourceBE.Type resourceType, uint userId, ResourceContentBE content) { ResourceBE newResource = new ResourceBE(resourceType); newResource.Name = resourcename; newResource.ChangeMask = newResource.ChangeMask | ResourceBE.ChangeOperations.NAME; newResource.Size = size; newResource.MimeType = mimeType; newResource.ChangeDescription = description; newResource.ResourceCreateUserId = newResource.ResourceUpdateUserId = newResource.UserId = userId; newResource.ChangeSetId = 0; newResource.Timestamp = newResource.ResourceCreateTimestamp = newResource.ResourceUpdateTimestamp = DateTime.UtcNow; newResource.Content = content; newResource.ChangeMask = newResource.ChangeMask | ResourceBE.ChangeOperations.CONTENT; newResource.ResourceHeadRevision = ResourceBE.TAILREVISION; newResource.Revision = ResourceBE.TAILREVISION; newResource.IsHidden = false; return newResource; }
private StreamInfo GetFileInternal(string filename, MimeType type, bool allowFileLink) { if(allowFileLink && _allowRedirects) { return new StreamInfo(BuildS3Uri(Verb.GET, _s3.AtPath(filename), _redirectTimeout)); } // check if file is cached var entry = GetCachedEntry(filename); if(entry != null) { Stream filestream = File.Open(entry.Item1, FileMode.Open, FileAccess.Read, FileShare.Read); return new StreamInfo(filestream, filestream.Length, type, entry.Item3); } // get file from S3 var result = new Result<DreamMessage>(); _s3.AtPath(filename).InvokeEx(Verb.GET, DreamMessage.Ok(), result); var response = result.Wait(); try { if(response.IsSuccessful) { return new StreamInfo(response.AsStream(), response.ContentLength, response.ContentType, GetLastModifiedTimestampFromResponse(response)); } if(response.Status == DreamStatus.NotFound) { response.Close(); return null; } throw new DreamInternalErrorException(string.Format("S3 unable to fetch file (status {0}, message {1})", response.Status, response.AsText())); } catch { if(response != null) { response.Close(); } throw; } }
/// <summary> /// Create a document from a text reader. /// </summary> /// <param name="reader">Document text reader.</param> /// <param name="mime">Document mime-type.</param> /// <returns>New document instance.</returns> public static XDoc From(TextReader reader, MimeType mime) { if(reader == null) { throw new ArgumentNullException("reader"); } if(mime == null) { throw new ArgumentNullException("mime"); } if(mime.Match(MimeType.VCAL)) { return VersitUtil.FromVersit(reader, "vcal"); } if(mime.Match(MimeType.VERSIT)) { return VersitUtil.FromVersit(reader, "vcard"); } if(mime.Match(MimeType.HTML)) { return FromHtml(reader); } if(mime.IsXml) { return FromXml(reader); } if(mime.Match(MimeType.FORM_URLENCODED)) { return XPostUtil.FromXPathValuePairs(XUri.ParseParamsAsPairs(reader.ReadToEnd()), "form"); } throw new ArgumentException("unsupported mime-type: " + mime.FullType, "mime"); }
/// <summary> /// Create a document from a stream. /// </summary> /// <param name="stream">Document stream.</param> /// <param name="mime">Document mime-type.</param> /// <returns>New document instance.</returns> public static XDoc From(Stream stream, MimeType mime) { if(stream == null) { throw new ArgumentNullException("stream"); } if(mime == null) { throw new ArgumentNullException("mime"); } if(!stream.CanSeek && !(stream is BufferedStream)) { stream = new BufferedStream(stream); } using(TextReader reader = new StreamReader(stream, mime.CharSet)) { return From(reader, mime); } }
/// <summary> /// Add an entry summary document. /// </summary> /// <param name="mime">Mime type of the summary document to be added.</param> /// <param name="xml">Summary document.</param> /// <returns>Returns the current document instance.</returns> public XAtomEntry AddSummary(MimeType mime, XDoc xml) { AddText("summary", mime, xml); return this; }
/// <summary> /// Derive a mime-type from a file extension. /// </summary> /// <remarks>The default mimetype returned is <see cref="BINARY"/>.</remarks> /// <param name="filename">Filename to get extension from.</param> /// <returns>Best match mime-type.</returns> public static MimeType FromFileExtension(string filename) { MimeType result = BINARY; switch (Path.GetExtension(filename).ToLowerInvariant()) { // document formats case ".html": case ".htm": result = HTML; break; case ".txt": result = TEXT; break; case ".xml": case ".xhtml": case ".xsl": case ".xsd": case ".xslt": result = XML; break; case ".css": result = CSS; break; case ".js": result = JS; break; case ".pdf": result = PDF; break; // image formats case ".gif": result = GIF; break; case ".jpg": case ".jpeg": result = JPEG; break; case ".png": result = PNG; break; case ".svg": result = SVG; break; case ".tif": case ".tiff": result = TIFF; break; case ".bmp": result = BMP; break; // Microsoft office formats case ".doc": result = MSOFFICE_DOC; break; case ".docx": result = MSOFFICE_DOCX; break; case ".xls": result = MSOFFICE_XLS; break; case ".xlsx": result = MSOFFICE_XLSX; break; case ".ppt": result = MSOFFICE_PPT; break; case ".pptx": result = MSOFFICE_PPTX; break; } return(result); }
/// <summary> /// New Message with HTTP status: Ok (200). /// </summary> /// <param name="contentType">Content Mime-Type.</param> /// <param name="text">Message body.</param> /// <returns>New DreamMessage.</returns> public static DreamMessage Ok(MimeType contentType, string text) { return(new DreamMessage(DreamStatus.Ok, null, contentType, text)); }
/// <summary> /// New Message with HTTP status: Ok (200). /// </summary> /// <param name="contentType">Content Mime-Type.</param> /// <param name="doc">Message body.</param> /// <returns>New DreamMessage.</returns> public static DreamMessage Ok(MimeType contentType, XDoc doc) { return(new DreamMessage(DreamStatus.Ok, null, contentType, doc)); }
/// <summary> /// Create a new message. /// </summary> /// <param name="status">Http status.</param> /// <param name="headers">Header collection.</param> /// <param name="contentType">Content Mime-Type.</param> /// <param name="text">Message body.</param> public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, string text) : this(status, headers, contentType, contentType.CharSet.GetBytes(text)) { }
/// <summary> /// New Message with HTTP status: Ok (200). /// </summary> /// <param name="contentType">Content Mime-Type.</param> /// <param name="contentLength">Content length.</param> /// <param name="content">Message body.</param> /// <returns>New DreamMessage.</returns> public static DreamMessage Ok(MimeType contentType, long contentLength, Stream content) { return(new DreamMessage(DreamStatus.Ok, null, contentType, contentLength, content)); }
/// <summary> /// New Message with HTTP status: Ok (200). /// </summary> /// <param name="contentType">Content Mime-Type.</param> /// <param name="content">Message body.</param> /// <returns>New DreamMessage.</returns> public static DreamMessage Ok(MimeType contentType, byte[] content) { return(new DreamMessage(DreamStatus.Ok, null, contentType, content)); }
/// <summary> /// Add content to the entry. /// </summary> /// <param name="mime">Mime type of the content to be added.</param> /// <param name="data">Content as byte array.</param> /// <returns>Returns the current document instance.</returns> public XAtomEntry AddContent(MimeType mime, byte[] data) { AddText("content", mime, data); return this; }
/// <summary> /// Try to parse a mime-type from a content-type string. /// </summary> /// <param name="contentTypeWithParameters">Content type string.</param> /// <param name="result">Mime-type instance return value.</param> /// <returns><see langword="True"/> if a mime-type could be parsed.</returns> public static bool TryParse(string contentTypeWithParameters, out MimeType result) { string type; string subtype; Dictionary<string, string> parameters; if(!TryParse(contentTypeWithParameters, out type, out subtype, out parameters)) { result = null; return false; } result = new MimeType(type, subtype, parameters); return true; }
/// <summary> /// Get the best matching Mimetype given a list of mime-type options and accepted mime-types. /// </summary> /// <param name="have">Array of possible mime-types.</param> /// <param name="accept">Array of mime-types accepted.</param> /// <returns>Best match mime-type instance.</returns> public static MimeType MatchBestContentType(MimeType[] have, MimeType[] accept) { // match each available content-type against accepted content-types MimeType result = null; float best = 0.0f; foreach(MimeType haveType in have) { foreach(MimeType acceptType in accept) { // check if current combination yields a better result float current = acceptType.Quality; if((current > best) && haveType.Match(acceptType)) { best = current; result = haveType; } } } return result; }
/// <summary> /// Create a document from a stream. /// </summary> /// <param name="stream">Document stream.</param> /// <param name="mime">Document mime-type.</param> /// <returns>New document instance.</returns> public static XDoc From(Stream stream, MimeType mime) { return From(stream, mime, false); }
//--- Methods --- /// <summary> /// Try to match instance against another instance. /// </summary> /// <param name="other">Other mime-type.</param> /// <returns><see langword="True"/> if the two types match.</returns> public bool Match(MimeType other) { // match main type if((MainType != "*") && (other.MainType != "*") && (MainType != other.MainType)) { return false; } // match subtype if((SubType != "*") && (other.SubType != "*") && (SubType != other.SubType)) { return false; } return true; }
/// <summary> /// Create a document from a stream. /// </summary> /// <param name="stream">Document stream.</param> /// <param name="mime">Document mime-type.</param> /// <param name="detectEncoding">Detect character encoding in stream.</param> /// <returns>New document instance.</returns> public static XDoc From(Stream stream, MimeType mime, bool detectEncoding) { if(stream == null) { throw new ArgumentNullException("stream"); } if(mime == null) { throw new ArgumentNullException("mime"); } if(!stream.CanSeek && !(stream is BufferedStream)) { stream = new BufferedStream(stream); } var encoding = detectEncoding ? stream.DetectEncoding() : mime.CharSet; using(TextReader reader = new StreamReader(stream, encoding ?? mime.CharSet)) { return From(reader, mime); } }
/// <summary> /// Create a document from an xml string. /// </summary> /// <param name="value">Document string.</param> /// <param name="mime">Document mime-type.</param> /// <returns>New document instance.</returns> public static XDoc From(string value, MimeType mime) { if(value == null) { throw new ArgumentNullException("value"); } if(mime == null) { throw new ArgumentNullException("mime"); } return From(new TrimmingStringReader(value), mime); }
private static void ValidateCommentText(MimeType mimetype, string content) { if (!MimeType.TEXT.Match(mimetype)) throw new DreamBadRequestException(string.Format(DekiResources.COMMENT_MIMETYPE_UNSUPPORTED, mimetype.ToString(), MimeType.HTML.ToString(), MimeType.TEXT.ToString())); }
//--- Class Methods --- /// <summary> /// Load a document from a file. /// </summary> /// <param name="filename">Path to document.</param> /// <param name="mime">Document mime-type.</param> /// <returns>New document instance.</returns> public static XDoc LoadFrom(string filename, MimeType mime) { if(string.IsNullOrEmpty(filename)) { throw new ArgumentNullException("filename"); } if(mime == null) { throw new ArgumentNullException("mime"); } using(TextReader reader = new StreamReader(filename, mime.CharSet, true)) { return From(reader, mime); } }
private Plug GetResoucePlug(string graph, string app, string format, MimeType mime) { string hash = StringUtil.ComputeHashString(graph); string key = string.Format("{0}.{1}.{2}", hash, Path.GetFileNameWithoutExtension(app), format); Plug location = Storage.At(key); // check if the target resource needs to be generated if(!location.InvokeAsync("HEAD", DreamMessage.Ok()).Wait().IsSuccessful) { Stream data; using(Stream input = new MemoryStream(Encoding.UTF8.GetBytes(graph))) { // execute process Stream output; Stream error; Tuplet<int, Stream, Stream> exitValues = Async.ExecuteProcess(app, "-T" + format, input, new Result<Tuplet<int, Stream, Stream>>(TimeSpan.FromSeconds(30))).Wait(); int status = exitValues.Item1; using(output = exitValues.Item2) { using(error = exitValues.Item3) { if(status != 0) { string message; using(StreamReader reader = new StreamReader(error, Encoding.ASCII)) { message = reader.ReadToEnd(); } throw new DreamInternalErrorException(string.Format("graphviz failed with status {0}:\n{1}", status, message)); } data = output.ToChunkedMemoryStream(-1, new Result<ChunkedMemoryStream>()).Wait(); } } } // create result location.With("ttl", TimeSpan.FromDays(7).TotalSeconds).Put(DreamMessage.Ok(mime, data.Length, data)); } return Self.At("images", key); }
public virtual ResourceBE BuildRevForNewResource(uint? parentId, ResourceBE.ParentType parentType, string resourcename, MimeType mimeType, uint size, string description, ResourceBE.Type resourceType, uint userId, ResourceContentBE content) { ResourceBE newResource = BuildRevForNewResource(resourcename, mimeType, size, description, resourceType, userId, content); switch(parentType) { case ResourceBE.ParentType.PAGE: newResource.ParentPageId = parentId; break; case ResourceBE.ParentType.USER: newResource.ParentUserId = parentId; break; default: newResource.ParentId = parentId; break; } newResource.ChangeMask = newResource.ChangeMask | ResourceBE.ChangeOperations.PARENT; return newResource; }
/// <summary> /// Add a link to the document. /// </summary> /// <param name="href">Uri to the linked resource.</param> /// <param name="relation">Relationship of the linked resource to the current document.</param> /// <param name="type">Type of resource being linked.</param> /// <param name="length">Size in bytes.</param> /// <param name="title">Title of the linked resource.</param> /// <returns>Returns the current document instance.</returns> public XAtomBase AddLink(XUri href, LinkRelation relation, MimeType type, long? length, string title) { Start("link"); Attr("href", href); Attr("rel", relation.ToString().ToLowerInvariant()); if(type != null) { Attr("type", type.FullType); } if(length != null) { Attr("length", length ?? 0); } if(!string.IsNullOrEmpty(title)) { Attr("title", title); } End(); return this; }
private ResourceBE BuildRevForExistingResource(ResourceBE currentResource, MimeType mimeType, uint size, string description) { ResourceBE newRev = BuildResourceRev(currentResource); newRev.MimeType = mimeType; newRev.Size = size; newRev.ChangeDescription = description; newRev.Content = currentResource.Content; newRev.ContentId = currentResource.ContentId; return newRev; }
/// <summary> /// Add text to the document. /// </summary> /// <param name="tag">Enclosing tag for the text.</param> /// <param name="mime">Mime type of the enclosed text.</param> /// <param name="data">The text body as a byte array.</param> /// <returns>Returns the current document instance.</returns> public XAtomBase AddText(string tag, MimeType mime, byte[] data) { Start(tag).Attr("type", mime.FullType).Value(data).End(); return this; }
public StreamInfo(Stream stream, long size, MimeType type) : this(stream, size, type, null) { }
/// <summary> /// Add text to the document. /// </summary> /// <param name="tag">Enclosing tag for the text.</param> /// <param name="mime">Mime type of the enclosed text.</param> /// <param name="xml">The body document to add.</param> /// <returns>Returns the current document instance.</returns> public XAtomBase AddText(string tag, MimeType mime, XDoc xml) { if(mime.Match(MimeType.XHTML)) { Start(tag).Attr("type", "xhtml"); // add content and normalize the root node XDoc added = xml.Clone().Rename("div"); if(added["@xmlns"].IsEmpty) { added.Attr("xmlns", "http://www.w3.org/1999/xhtml"); } Add(added); } else if(mime.Match(MimeType.HTML)) { Start(tag).Attr("type", "html"); // embed HTML as text Value(xml.ToInnerXHtml()); } else { Start(tag).Attr("type", mime.FullType); Add(xml); } // close element End(); return this; }
private void AppendDiff(bool diffCacheEnabled, XDoc body, RecentChangeEntry change, RC type, Title title, IDictionary<string, XDoc> cache) { var resources = DekiContext.Current.Resources; ulong pageid = change.CurId; int? after = (change.Revision > 0) ? (int?)change.Revision : null; int? before = change.PreviousRevision; // append edit summary, if any body.Elem("p", change.Summary); // append comment(s) int count = (change.ExtraComments == null) ? (string.IsNullOrEmpty(change.Comment) ? 0 : 1) : change.ExtraComments.Count; switch(count) { case 0: // nothing to do break; case 1: body.Elem("p", (change.ExtraComments != null) ? change.ExtraComments[0].Item3 : change.Comment); break; default: body.Start("ol"); foreach(var comment in ((IEnumerable<Tuplet<string, string, string>>)change.ExtraComments).Reverse()) { string author = string.IsNullOrEmpty(comment.Item2) ? comment.Item1 : comment.Item2; body.Elem("li", string.IsNullOrEmpty(author) ? comment.Item3 : string.Format("{0} ({1})", comment.Item3, author)); } body.End(); break; } // check if page was modified if(after.HasValue && before.HasValue && (after != before)) { // check if we have a cached version of this page diff XDoc diffXml = null; Plug store = Storage.At("site_" + XUri.EncodeSegment(DekiContext.Current.Instance.Id), DreamContext.Current.Culture.Name, "feeds", string.Format("page_{0}", pageid), string.Format("diff_{0}-{1}.xml", before, after)); if(diffCacheEnabled) { var v = store.Get(new Result<DreamMessage>(TimeSpan.MaxValue)).Wait(); diffXml = (v.IsSuccessful && v.HasDocument) ? v.ToDocument() : null; if(diffXml != null) { // TODO (steveb): this problem only exists b/c we can't determine the actual revision number that we should use for diffing (see bug 7824) // check if either revision has been hidden since we computed the diff var session = DbUtils.CurrentSession; if(after.Value != change.CurrentRevision) { OldBE afterRevision = session.Old_GetOldByRevision(pageid, (ulong)after.Value); if((afterRevision == null) || afterRevision.IsHidden) { diffXml = null; } } if((diffXml != null) && (before.Value != change.CurrentRevision) && (before.Value > 0)) { OldBE beforeRevision = session.Old_GetOldByRevision(pageid, (ulong)before.Value); if((beforeRevision == null) || beforeRevision.IsHidden) { diffXml = null; } } } } if(diffXml == null) { diffXml = new XDoc("diff"); // retrieve page versions XDoc res = QueryPageVersions(pageid, after, before, cache); XDoc beforeDoc = res["before/body"]; XDoc afterDoc = res["after/body"]; // check if either both versions or only one version were retrieved XDoc diff = XDoc.Empty; XDoc invisibleDiff = XDoc.Empty; string summary = null; if(!beforeDoc.IsEmpty && !afterDoc.IsEmpty) { XDoc beforeChanges; XDoc afterChanges; DekiResource summaryResource = null; // compute differences between 'before' and 'after' versions diff = Utils.GetPageDiff(beforeDoc, afterDoc, true, DekiContext.Current.Instance.MaxDiffSize, out invisibleDiff, out summaryResource, out beforeChanges, out afterChanges); // TODO (arnec): why are we using ToLower here at all and without a culture? summary = resources.Localize(summaryResource).ToLower(); } else if(!afterDoc.IsEmpty) { // since we don't have a 'before' version, just show the entire 'after' version (can happen for new pages or hidden revisions) diff = afterDoc; } else if(!beforeDoc.IsEmpty) { // since we don't have a 'after' version, just show the entire 'before' version (can happen for hidden revisions) diff = beforeDoc; } // add change summary diffXml.Start("blockquote"); diffXml.Start("p").Elem("strong", summary).End(); // check if a diff was computed if(!diff.IsEmpty) { diffXml.Start("hr").Attr("width", "100%").Attr("size", "2").End(); diffXml.AddNodes(diff); diffXml.Start("hr").Attr("width", "100%").Attr("size", "2").End(); // check if there are invisible changes as well to show if(!invisibleDiff.IsEmpty) { diffXml.Start("p").Elem("strong", resources.Localize(DekiResources.PAGE_DIFF_OTHER_CHANGES())).End(); diffXml.Add(invisibleDiff); } } else if(!invisibleDiff.IsEmpty) { // only show invisible changes diffXml.Start("hr").Attr("width", "100%").Attr("size", "2").End(); diffXml.Start("p").Elem("strong", resources.Localize(DekiResources.PAGE_DIFF_OTHER_CHANGES())).End(); diffXml.Add(invisibleDiff); } else if(beforeDoc.IsEmpty && afterDoc.IsEmpty) { // show message that page contents were not available anymore diffXml.Elem("p", resources.Localize(DekiResources.PAGE_NOT_AVAILABLE())); } diffXml.End(); // store diff in cache if(diffCacheEnabled && !afterDoc.IsEmpty) { store.With("ttl", TimeSpan.FromDays(30).TotalSeconds).Put(diffXml, new Result<DreamMessage>(TimeSpan.MaxValue)).Block(); } } body.AddNodes(diffXml); } // check if we have a comment text if(Utils.IsPageComment(type)) { string text = change.CmntContent; if(!string.IsNullOrEmpty(text) && !change.CmntDeleted) { MimeType mime = new MimeType(change.CmntMimetype ?? MimeType.TEXT_UTF8.ToString()); if(mime.Match(MimeType.HTML)) { XDoc html = XDocFactory.From(string.Format("<html><body>{0}</body></html>", text), MimeType.HTML); body.Start("blockquote").AddNodes(html["body"]).End(); } else { // anything else should be consider to be text body.Start("blockquote").Elem("p", text).End(); } } else { // anything else should be consider to be text body.Start("blockquote").Elem("p", resources.Localize(DekiResources.COMMENT_NOT_AVAILABLE())).End(); } } // adds links body.Start("table").Attr("border", 0).Attr("padding", "5").Attr("width", "80%").Start("tr"); // add link for viewing the page if(change.PageExists) { Title view = new Title(title); body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(view, true)).Value(resources.Localize(DekiResources.VIEW_PAGE())).End().End(); } // check if we need to add link for editing the page if(after.HasValue && before.HasValue && (after != before)) { Title edit = new Title(title) { Query = "action=edit" }; body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(edit)).Value(resources.Localize(DekiResources.EDIT_PAGE())).End().End(); } // check if we need to add link for viewing the complete diff if(after.HasValue && before.HasValue && (after != before)) { Title show = new Title(title) { Query = string.Format("diff={0}&revision={1}", after.Value, before.Value) }; body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(show, true)).Value(resources.Localize(DekiResources.VIEW_PAGE_DIFF())).End().End(); } // check if we need to add link for seeing full page history if(after.HasValue && before.HasValue && (after != before)) { Title history = new Title(title) { Query = "action=history" }; body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(history)).Value(resources.Localize(DekiResources.VIEW_PAGE_HISTORY())).End().End(); } // check if we need to add link for banning the user List<KeyValuePair<string, string>> authors = change.SortedAuthors; if((authors == null) || (authors.Count == 0)) { authors = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>(change.Username, change.Fullname) }; } for(int i = 0; i < authors.Count; ++i) { string username = authors[i].Key; string fullname = authors[i].Value; if(!string.IsNullOrEmpty(username)) { // don't put up ban link for admins. UserBE user = DbUtils.CurrentSession.Users_GetByName(username); if(!UserBL.IsAnonymous(user) && !PermissionsBL.IsUserAllowed(user, Permissions.ADMIN)) { Title ban = Title.FromUIUri(null, "Special:Userban"); ban.Query += string.Format("username={0}", username); body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(ban)).Value(resources.Localize(DekiResources.BAN_USER(string.IsNullOrEmpty(fullname) ? username : fullname))).End().End(); } } } // close HTML body.End().End(); }
/// <summary> /// Add a subdocument as content to the entry. /// </summary> /// <param name="mime">Mime type of the document to be added.</param> /// <param name="xml">Document to add.</param> /// <returns>Returns the current document instance.</returns> public XAtomEntry AddContent(MimeType mime, XDoc xml) { AddText("content", mime, xml); return this; }