PageRenderTime 33ms CodeModel.GetById 7ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/BlogEngine/DotNetSlave.BusinessLogic/Web/HttpHandlers/Sioc.cs

#
C# | 707 lines | 391 code | 102 blank | 214 comment | 30 complexity | 0050623c1403cb623aeb18e8282a96bb MD5 | raw file
  1namespace BlogEngine.Core.Web.HttpHandlers
  2{
  3    using System;
  4    using System.Collections.Generic;
  5    using System.IO;
  6    using System.Linq;
  7    using System.Security.Cryptography;
  8    using System.Text;
  9    using System.Text.RegularExpressions;
 10    using System.Web;
 11    using System.Web.Security;
 12    using System.Xml;
 13
 14    /// <summary>
 15    /// Based on John Dyer's (http://johndyer.name/) extension.
 16    /// </summary>
 17    public class Sioc : IHttpHandler
 18    {
 19        #region Constants and Fields
 20
 21        /// <summary>
 22        ///     The xml namespaces.
 23        /// </summary>
 24        private static Dictionary<string, string> xmlNamespaces;
 25
 26        #endregion
 27
 28        #region Properties
 29
 30        /// <summary>
 31        ///     Gets a value indicating whether another request can use the <see cref = "T:System.Web.IHttpHandler"></see> instance.
 32        /// </summary>
 33        /// <value></value>
 34        /// <returns>true if the <see cref = "T:System.Web.IHttpHandler"></see> instance is reusable; otherwise, false.</returns>
 35        public bool IsReusable
 36        {
 37            get
 38            {
 39                return false;
 40            }
 41        }
 42
 43        /// <summary>
 44        ///     Gets SupportedNamespaces.
 45        /// </summary>
 46        private static Dictionary<string, string> SupportedNamespaces
 47        {
 48            get
 49            {
 50                return xmlNamespaces ??
 51                       (xmlNamespaces =
 52                        new Dictionary<string, string>
 53                            {
 54                                { "foaf", "http://xmlns.com/foaf/0.1/" },
 55                                { "rss", "http://purl.org/rss/1.0/" },
 56                                { "admin", "http://webns.net/mvcb/" },
 57                                { "dc", "http://purl.org/dc/elements/1.1/" },
 58                                { "dcterms", "http://purl.org/dc/terms/" },
 59                                { "rdfs", "http://www.w3.org/2000/01/rdf-schema#" },
 60                                { "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
 61                                { "content", "http://purl.org/rss/1.0/modules/content" },
 62                                { "sioc", "http://rdfs.org/sioc/ns#" }
 63                            });
 64            }
 65        }
 66
 67        #endregion
 68
 69        #region Implemented Interfaces
 70
 71        #region IHttpHandler
 72
 73        /// <summary>
 74        /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"></see> interface.
 75        /// </summary>
 76        /// <param name="context">
 77        /// An <see cref="T:System.Web.HttpContext"></see> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.
 78        /// </param>
 79        public void ProcessRequest(HttpContext context)
 80        {
 81            context.Response.ContentType = "text/xml";
 82            var siocType = context.Request["sioc_type"] + string.Empty;
 83            var siocId = context.Request["sioc_id"] + string.Empty;
 84
 85            switch (siocType)
 86            {
 87                default:
 88
 89                    // case "site":
 90                    var list = Post.Posts.ConvertAll(ConvertToIPublishable);
 91                    var max = Math.Min(BlogSettings.Instance.PostsPerFeed, list.Count);
 92                    list = list.GetRange(0, max);
 93                    WriteSite(context.Response.OutputStream, list);
 94                    break;
 95
 96                case "post":
 97                    Guid postId;
 98                    if (siocId.TryParse(out postId))
 99                    {
100                        var post = Post.GetPost(postId);
101                        if (post != null)
102                        {
103                            WritePub(context.Response.OutputStream, post);
104                        }
105                    }
106
107                    break;
108
109                case "comment":
110                    Guid commentId;
111                    if (siocId.TryParse(out commentId))
112                    {
113                        // TODO: is it possible to get a single comment?
114                        var comment = GetComment(commentId);
115
116                        if (comment != null)
117                        {
118                            WritePub(context.Response.OutputStream, comment);
119                        }
120                    }
121
122                    break;
123
124                case "user":
125                    WriteAuthor(context.Response.OutputStream, siocId);
126                    break;
127
128                    /*
129            case "post":
130                generator.WriteSite(context.Response.OutputStream);
131                break;
132            */
133            }
134        }
135
136        #endregion
137
138        #endregion
139
140        #region Methods
141
142        /// <summary>
143        /// Calculates the SHA1.
144        /// </summary>
145        /// <param name="text">
146        /// The text string.
147        /// </param>
148        /// <param name="enc">
149        /// The encoding.
150        /// </param>
151        /// <returns>
152        /// The hash string.
153        /// </returns>
154        private static string CalculateSha1(string text, Encoding enc)
155        {
156            var buffer = enc.GetBytes(text);
157            var cryptoTransformSha1 = new SHA1CryptoServiceProvider();
158            var hash = BitConverter.ToString(cryptoTransformSha1.ComputeHash(buffer)).Replace("-", string.Empty);
159
160            return hash.ToLower();
161        }
162
163        /// <summary>
164        /// Closes the writer.
165        /// </summary>
166        /// <param name="xmlWriter">
167        /// The XML writer.
168        /// </param>
169        private static void CloseWriter(XmlWriter xmlWriter)
170        {
171            xmlWriter.WriteEndElement(); // rdf:RDF
172            xmlWriter.WriteEndDocument();
173            xmlWriter.Close();
174        }
175
176        /// <summary>
177        /// Converts to publishable interface.
178        /// </summary>
179        /// <param name="item">
180        /// The publishable item.
181        /// </param>
182        /// <returns>
183        /// The publishable interface.
184        /// </returns>
185        private static IPublishable ConvertToIPublishable(IPublishable item)
186        {
187            return item;
188        }
189
190        /// <summary>
191        /// Gets the blog author URL.
192        /// </summary>
193        /// <param name="username">
194        /// The username.
195        /// </param>
196        /// <returns>
197        /// Blog author url.
198        /// </returns>
199        private static string GetBlogAuthorUrl(string username)
200        {
201            return string.Format("{0}author/{1}.aspx", Utils.AbsoluteWebRoot, HttpUtility.UrlEncode(username));
202        }
203
204        /// <summary>
205        /// Gets the comment.
206        /// </summary>
207        /// <param name="commentId">
208        /// The comment id.
209        /// </param>
210        /// <returns>
211        /// The comment.
212        /// </returns>
213        private static Comment GetComment(Guid commentId)
214        {
215            var posts = Post.Posts;
216            return posts.SelectMany(post => post.Comments).FirstOrDefault(comm => comm.Id == commentId);
217        }
218
219        /// <summary>
220        /// Gets the sioc author URL.
221        /// </summary>
222        /// <param name="username">
223        /// The username.
224        /// </param>
225        /// <returns>
226        /// The SIOC Author Url.
227        /// </returns>
228        private static string GetSiocAuthorUrl(string username)
229        {
230            return string.Format(
231                "{0}sioc.axd?sioc_type=user&sioc_id={1}", Utils.AbsoluteWebRoot, HttpUtility.UrlEncode(username));
232        }
233
234        /// <summary>
235        /// Gets the sioc authors URL.
236        /// </summary>
237        /// <returns>
238        /// The SIOC Author Url.
239        /// </returns>
240        private static string GetSiocAuthorsUrl()
241        {
242            return string.Format("{0}sioc.axd?sioc_type=site#authors", Utils.AbsoluteWebRoot);
243        }
244
245        /// <summary>
246        /// Gets the sioc blog URL.
247        /// </summary>
248        /// <returns>
249        /// The SIOC Blog Url.
250        /// </returns>
251        private static string GetSiocBlogUrl()
252        {
253            return string.Format("{0}sioc.axd?sioc_type=site#webblog", Utils.AbsoluteWebRoot);
254        }
255
256        /// <summary>
257        /// Gets the sioc comment URL.
258        /// </summary>
259        /// <param name="id">
260        /// The comment id.
261        /// </param>
262        /// <returns>
263        /// The SIOC Comment Url.
264        /// </returns>
265        private static string GetSiocCommentUrl(string id)
266        {
267            return string.Format("{0}sioc.axd?sioc_type=comment&sioc_id={1}", Utils.AbsoluteWebRoot, id);
268        }
269
270        /// <summary>
271        /// Gets the sioc post URL.
272        /// </summary>
273        /// <param name="id">
274        /// The SIOC post id.
275        /// </param>
276        /// <returns>
277        /// The SIOC Post Url.
278        /// </returns>
279        private static string GetSiocPostUrl(string id)
280        {
281            return string.Format("{0}sioc.axd?sioc_type=post&sioc_id={1}", Utils.AbsoluteWebRoot, id);
282        }
283
284        /*
285                /// <summary>
286                /// Gets the sioc site URL.
287                /// </summary>
288                /// <returns>
289                /// The SIOC Site Url.
290                /// </returns>
291                private static string GetSiocSiteUrl()
292                {
293                    return string.Format("{0}sioc.axd?sioc_type=site", Utils.AbsoluteWebRoot);
294                }
295        */
296
297        /// <summary>
298        /// Gets the writer.
299        /// </summary>
300        /// <param name="stream">
301        /// The stream.
302        /// </param>
303        /// <returns>
304        /// The Xml Writer.
305        /// </returns>
306        private static XmlWriter GetWriter(Stream stream)
307        {
308            var settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true };
309            var xmlWriter = XmlWriter.Create(stream, settings);
310
311            xmlWriter.WriteStartDocument();
312            xmlWriter.WriteStartElement("rdf", "RDF", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
313
314            // "http://xmlns.com/foaf/0.1/");
315            foreach (var prefix in SupportedNamespaces.Keys)
316            {
317                xmlWriter.WriteAttributeString("xmlns", prefix, null, SupportedNamespaces[prefix]);
318            }
319
320            return xmlWriter;
321        }
322
323        /// <summary>
324        /// Writes the author.
325        /// </summary>
326        /// <param name="stream">
327        /// The stream.
328        /// </param>
329        /// <param name="authorName">
330        /// Name of the author.
331        /// </param>
332        private static void WriteAuthor(Stream stream, string authorName)
333        {
334            var xmlWriter = GetWriter(stream);
335
336            WriteFoafDocument(xmlWriter, "user", GetSiocAuthorUrl(authorName));
337
338            var user = Membership.GetUser(authorName);
339            var ap = AuthorProfile.GetProfile(authorName);
340
341            // FOAF:Person
342            xmlWriter.WriteStartElement("foaf", "Person", null);
343            xmlWriter.WriteAttributeString("rdf", "about", null, GetSiocAuthorUrl(authorName));
344
345            xmlWriter.WriteElementString("foaf", "Name", null, authorName);
346            if (ap != null && !ap.Private && ap.FirstName != String.Empty)
347            {
348                xmlWriter.WriteElementString("foaf", "firstName", null, ap.FirstName);
349            }
350
351            if (ap != null && !ap.Private && ap.LastName != String.Empty)
352            {
353                xmlWriter.WriteElementString("foaf", "surname", null, ap.LastName);
354            }
355
356            xmlWriter.WriteElementString(
357                "foaf", "mbox_sha1sum", null, (user != null) ? CalculateSha1(user.Email, Encoding.UTF8) : string.Empty);
358            xmlWriter.WriteStartElement("foaf", "homepage", null);
359            xmlWriter.WriteAttributeString("rdf", "resource", null, Utils.AbsoluteWebRoot.ToString());
360            xmlWriter.WriteEndElement(); // foaf:homepage 
361
362            xmlWriter.WriteStartElement("foaf", "holdsAccount", null);
363            xmlWriter.WriteAttributeString("rdf", "resource", null, GetBlogAuthorUrl(authorName));
364            xmlWriter.WriteEndElement(); // foaf:holdsAccount  
365
366            xmlWriter.WriteEndElement(); // foaf:Person
367
368            // SIOC:User
369            xmlWriter.WriteStartElement("sioc", "User", null);
370            xmlWriter.WriteAttributeString("rdf", "about", null, GetBlogAuthorUrl(authorName));
371            xmlWriter.WriteElementString("foaf", "accountName", null, authorName);
372            xmlWriter.WriteElementString("sioc", "name", null, authorName);
373
374            // xmlWriter.WriteElementString("dcterms", "created", null, "TODO:" + authorName);
375            xmlWriter.WriteEndElement(); // sioc:User
376
377            CloseWriter(xmlWriter);
378        }
379
380        /// <summary>
381        /// Writes the foaf document.
382        /// </summary>
383        /// <param name="xmlWriter">
384        /// The XML writer.
385        /// </param>
386        /// <param name="siocType">
387        /// Type of the sioc.
388        /// </param>
389        /// <param name="url">
390        /// The URL string.
391        /// </param>
392        private static void WriteFoafDocument(XmlWriter xmlWriter, string siocType, string url)
393        {
394            var title = string.Format("SIOC {0} profile for \"{1}\"", siocType, BlogSettings.Instance.Name);
395            const string Description =
396                "A SIOC profile describes the structure and contents of a weblog in a machine readable form. For more information please refer to http://sioc-project.org/.";
397
398            xmlWriter.WriteStartElement("foaf", "Document", null);
399            xmlWriter.WriteAttributeString("rdf", "about", null, Utils.AbsoluteWebRoot.ToString());
400
401            xmlWriter.WriteElementString("dc", "title", null, title);
402            xmlWriter.WriteElementString("dc", "description", null, Description);
403            xmlWriter.WriteElementString("foaf", "primaryTopic", null, url);
404            xmlWriter.WriteElementString(
405                "admin", "generatorAgent", null, string.Format("BlogEngine.NET{0}", BlogSettings.Instance.Version()));
406
407            xmlWriter.WriteEndElement(); // foaf:Document
408        }
409
410        /// <summary>
411        /// Writes the forum.
412        /// </summary>
413        /// <param name="xmlWriter">
414        /// The xml writer.
415        /// </param>
416        /// <param name="list">
417        /// The enumerable of publishable interface.
418        /// </param>
419        private static void WriteForum(XmlWriter xmlWriter, IEnumerable<IPublishable> list)
420        {
421            xmlWriter.WriteStartElement("sioc", "Forum", null);
422
423            xmlWriter.WriteAttributeString("rdf", "about", null, GetSiocBlogUrl());
424            xmlWriter.WriteElementString("sioc", "name", null, BlogSettings.Instance.Name);
425            xmlWriter.WriteStartElement("sioc", "link", null);
426            xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocBlogUrl());
427            xmlWriter.WriteEndElement();
428
429            foreach (var pub in list)
430            {
431                xmlWriter.WriteStartElement("sioc", "container_of", null);
432                xmlWriter.WriteStartElement("sioc", "Post", null);
433                xmlWriter.WriteAttributeString("rdf", "about", null, pub.AbsoluteLink.ToString());
434                xmlWriter.WriteAttributeString("dc", "title", null, pub.Title);
435
436                xmlWriter.WriteStartElement("rdfs", "seeAlso", null);
437                xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocPostUrl(pub.Id.ToString()));
438                xmlWriter.WriteEndElement(); // sioc:Post
439
440                xmlWriter.WriteEndElement(); // sioc:Post
441                xmlWriter.WriteEndElement(); // sioc:Forum
442            }
443
444            xmlWriter.WriteEndElement(); // sioc:Forum
445        }
446
447        /// <summary>
448        /// Writes an IPublishable to a stream.
449        /// </summary>
450        /// <param name="stream">
451        /// The stream.
452        /// </param>
453        /// <param name="pub">
454        /// The publishable interface.
455        /// </param>
456        private static void WritePub(Stream stream, IPublishable pub)
457        {
458            var xmlWriter = GetWriter(stream);
459
460            if (pub is Post)
461            {
462                WriteFoafDocument(xmlWriter, "post", pub.AbsoluteLink.ToString());
463            }
464            else
465            {
466                WriteFoafDocument(xmlWriter, "comment", pub.AbsoluteLink.ToString());
467            }
468
469            WriteSiocPost(xmlWriter, pub);
470            CloseWriter(xmlWriter);
471        }
472
473        /// <summary>
474        /// Writes SIOC post.
475        /// </summary>
476        /// <param name="xmlWriter">
477        /// The xml writer.
478        /// </param>
479        /// <param name="pub">
480        /// The publishable interface.
481        /// </param>
482        private static void WriteSiocPost(XmlWriter xmlWriter, IPublishable pub)
483        {
484            xmlWriter.WriteStartElement("sioc", "Post", null);
485            xmlWriter.WriteAttributeString("rdf", "about", null, pub.AbsoluteLink.ToString());
486
487            xmlWriter.WriteStartElement("sioc", "link", null);
488            xmlWriter.WriteAttributeString("rdf", "resource", null, pub.AbsoluteLink.ToString());
489            xmlWriter.WriteEndElement(); // sioc:link
490
491            xmlWriter.WriteStartElement("sioc", "has_container", null);
492            xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocBlogUrl());
493            xmlWriter.WriteEndElement(); // sioc:has_container
494
495            xmlWriter.WriteElementString("dc", "title", null, pub.Title);
496
497            // SIOC:USER
498            if (pub is Post)
499            {
500                xmlWriter.WriteStartElement("sioc", "has_creator", null);
501                xmlWriter.WriteStartElement("sioc", "User", null);
502                xmlWriter.WriteAttributeString("rdf", "about", null, GetBlogAuthorUrl(pub.Author));
503                xmlWriter.WriteStartElement("rdfs", "seeAlso", null);
504                xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocAuthorUrl(pub.Author));
505                xmlWriter.WriteEndElement(); // rdf:about
506                xmlWriter.WriteEndElement(); // sioc:User
507                xmlWriter.WriteEndElement(); // sioc:has_creator
508            }
509
510            // FOAF:maker
511            xmlWriter.WriteStartElement("foaf", "maker", null);
512            xmlWriter.WriteStartElement("foaf", "Person", null);
513            if (pub is Post)
514            {
515                xmlWriter.WriteAttributeString("rdf", "about", null, GetBlogAuthorUrl(pub.Author));
516            }
517
518            xmlWriter.WriteAttributeString("foaf", "name", null, pub.Author);
519
520            if (pub is Post)
521            {
522                var user = Membership.GetUser(pub.Author);
523                xmlWriter.WriteElementString(
524                    "foaf", 
525                    "mbox_sha1sum", 
526                    null, 
527                    (user != null) ? CalculateSha1(user.Email, Encoding.UTF8) : string.Empty);
528            }
529            else
530            {
531                xmlWriter.WriteElementString(
532                    "foaf", "mbox_sha1sum", null, CalculateSha1(((Comment)pub).Email, Encoding.UTF8));
533            }
534
535            xmlWriter.WriteStartElement("foaf", "homepage", null);
536            if (pub is Post)
537            {
538                xmlWriter.WriteAttributeString("rdf", "resource", null, Utils.AbsoluteWebRoot.ToString());
539            }
540            else
541            {
542                xmlWriter.WriteAttributeString("rdf", "resource", null, "TODO:");
543            }
544
545            xmlWriter.WriteEndElement(); // foaf:homepage
546
547            if (pub is Post)
548            {
549                xmlWriter.WriteStartElement("rdfs", "seeAlso", null);
550                xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocAuthorUrl(pub.Author));
551                xmlWriter.WriteEndElement(); // rdfs:seeAlso
552            }
553
554            xmlWriter.WriteEndElement(); // foaf:Person
555            xmlWriter.WriteEndElement(); // foaf:maker
556
557            // CONTENT
558            // xmlWriter.WriteElementString("dcterms", "created", null, DpUtility.ToW3cDateTime(pub.DateCreated));
559            xmlWriter.WriteElementString("sioc", "content", null, Utils.StripHtml(pub.Content));
560            xmlWriter.WriteElementString("content", "encoded", null, pub.Content);
561
562            // TOPICS
563            if (pub is Post)
564            {
565                // categories
566                foreach (var category in ((Post)pub).Categories)
567                {
568                    xmlWriter.WriteStartElement("sioc", "topic", null);
569                    xmlWriter.WriteAttributeString("rdfs", "label", null, category.Title);
570                    xmlWriter.WriteAttributeString("rdf", "resource", null, category.AbsoluteLink.ToString());
571                    xmlWriter.WriteEndElement(); // sioc:topic
572                }
573
574                // tags are also supposed to be treated as sioc:topic 
575                foreach (var tag in ((Post)pub).Tags)
576                {
577                    xmlWriter.WriteStartElement("sioc", "topic", null);
578                    xmlWriter.WriteAttributeString("rdfs", "label", null, tag);
579                    xmlWriter.WriteAttributeString("rdf", "resource", null, Utils.AbsoluteWebRoot + "?tag=/" + tag);
580                    xmlWriter.WriteEndElement(); // sioc:topic
581                }
582
583                // COMMENTS
584                foreach (var comment in ((Post)pub).ApprovedComments)
585                {
586                    xmlWriter.WriteStartElement("sioc", "has_reply", null);
587                    xmlWriter.WriteStartElement("sioc", "Post", null);
588                    xmlWriter.WriteAttributeString("rdf", "about", null, comment.AbsoluteLink.ToString());
589
590                    xmlWriter.WriteStartElement("rdfs", "seeAlso", null);
591                    xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocCommentUrl(comment.Id.ToString()));
592                    xmlWriter.WriteEndElement(); // rdfs:seeAlso
593
594                    xmlWriter.WriteEndElement(); // sioc:Post
595                    xmlWriter.WriteEndElement(); // sioc:has_reply
596                }
597
598                // TODO: LINKS
599                var linkMatches = Regex.Matches(pub.Content, @"<a[^(href)]?href=""([^""]+)""[^>]?>([^<]+)</a>");
600                var linkPairs = new List<string>();
601
602                foreach (Match linkMatch in linkMatches)
603                {
604                    var url = linkMatch.Groups[1].Value;
605                    var text = linkMatch.Groups[2].Value;
606
607                    if (url.IndexOf(Utils.AbsoluteWebRoot.ToString()) == 0)
608                    {
609                        continue;
610                    }
611
612                    var pair = url + "|" + text;
613                    if (linkPairs.Contains(pair))
614                    {
615                        continue;
616                    }
617
618                    xmlWriter.WriteStartElement("sioc", "links_to", null);
619                    xmlWriter.WriteAttributeString("rdf", "resource", null, url);
620                    xmlWriter.WriteAttributeString("rdfs", "label", null, text);
621                    xmlWriter.WriteEndElement(); // sioc:links_to
622
623                    linkPairs.Add(pair);
624                }
625            }
626
627            xmlWriter.WriteEndElement(); // sioc:Post
628        }
629
630        /// <summary>
631        /// Writes sioc site.
632        /// </summary>
633        /// <param name="xmlWriter">
634        /// The xml writer.
635        /// </param>
636        private static void WriteSiocSite(XmlWriter xmlWriter)
637        {
638            xmlWriter.WriteStartElement("sioc", "Site", null);
639            xmlWriter.WriteAttributeString("rdf", "about", null, Utils.AbsoluteWebRoot.ToString());
640
641            xmlWriter.WriteElementString("dc", "title", null, BlogSettings.Instance.Name);
642            xmlWriter.WriteElementString("dc", "description", null, BlogSettings.Instance.Description);
643            xmlWriter.WriteElementString("sioc", "link", null, Utils.AbsoluteWebRoot.ToString());
644            xmlWriter.WriteElementString("sioc", "host_of", null, GetSiocBlogUrl());
645            xmlWriter.WriteElementString("sioc", "has_group", null, GetSiocAuthorsUrl());
646
647            xmlWriter.WriteEndElement(); // sioc:Site
648        }
649
650        /// <summary>
651        /// Writes site.
652        /// </summary>
653        /// <param name="stream">
654        /// The stream.
655        /// </param>
656        /// <param name="list">
657        /// The enumerable of IPublishable.
658        /// </param>
659        private static void WriteSite(Stream stream, IEnumerable<IPublishable> list)
660        {
661            var xmlWriter = GetWriter(stream);
662
663            WriteUserGroup(xmlWriter);
664            WriteFoafDocument(xmlWriter, "site", Utils.AbsoluteWebRoot.ToString());
665            WriteSiocSite(xmlWriter);
666            WriteForum(xmlWriter, list);
667
668            CloseWriter(xmlWriter);
669        }
670
671        /// <summary>
672        /// Writes the user group.
673        /// </summary>
674        /// <param name="xmlWriter">
675        /// The XML writer.
676        /// </param>
677        private static void WriteUserGroup(XmlWriter xmlWriter)
678        {
679            xmlWriter.WriteStartElement("sioc", "Usergroup", null);
680
681            xmlWriter.WriteAttributeString("rdf", "about", null, GetSiocAuthorsUrl());
682            xmlWriter.WriteElementString("dc", "title", null, "Authors at \"" + BlogSettings.Instance.Name + "\"");
683
684            int count;
685            var members = Membership.Provider.GetAllUsers(0, 999, out count);
686
687            foreach (MembershipUser user in members)
688            {
689                xmlWriter.WriteStartElement("sioc", "has_member", null);
690                xmlWriter.WriteStartElement("sioc", "User", null);
691                xmlWriter.WriteAttributeString("rdf", "about", null, GetBlogAuthorUrl(user.UserName));
692                xmlWriter.WriteAttributeString("rdfs", "label", null, user.UserName);
693
694                xmlWriter.WriteStartElement("sioc", "see_also", null);
695                xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocAuthorUrl(user.UserName));
696                xmlWriter.WriteEndElement(); // sioc:see_also
697
698                xmlWriter.WriteEndElement(); // sioc:User
699                xmlWriter.WriteEndElement(); // sioc:has_member
700            }
701
702            xmlWriter.WriteEndElement(); // foaf:Document
703        }
704
705        #endregion
706    }
707}