Example #1
0
        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);
        }
Example #2
0
        //--- 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);
        }
Example #3
0
 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;
 }
Example #4
0
 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;
        }
Example #6
0
 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;
 }
Example #7
0
 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;
 }
Example #8
0
 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;
 }
Example #9
0
        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;
            }
        }
Example #10
0
 /// <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");
 }
Example #11
0
 /// <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);
     }
 }
Example #12
0
 /// <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;
 }
Example #13
0
        /// <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);
        }
Example #14
0
 /// <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));
 }
Example #15
0
 /// <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));
 }
Example #16
0
 /// <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))
 {
 }
Example #17
0
 /// <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));
 }
Example #18
0
 /// <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));
 }
Example #19
0
 /// <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;
 }
Example #20
0
 /// <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;
 }
Example #21
0
        /// <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;
        }
Example #22
0
 /// <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);
 }
Example #23
0
        //--- 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;
        }
Example #24
0
 /// <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);
     }
 }
Example #25
0
 /// <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);
 }
Example #26
0
 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()));
 }
Example #27
0
 //--- 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);
     }
 }
Example #28
0
        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);
        }
Example #29
0
 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;
 }
Example #30
0
 /// <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;
 }
Example #31
0
 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;
 }
Example #32
0
 /// <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;
 }
Example #33
0
 public StreamInfo(Stream stream, long size, MimeType type) : this(stream, size, type, null) { }
Example #34
0
        /// <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;
        }
Example #35
0
        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();
        }
Example #36
0
 /// <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;
 }