/BlogEngine/DotNetSlave.BusinessLogic/API/MetaWeblog/XMLRPCRequest.cs
C# | 508 lines | 304 code | 65 blank | 139 comment | 56 complexity | e2dabc8553c7ffcded96993ceec14f6e MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
- namespace BlogEngine.Core.API.MetaWeblog
- {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Globalization;
- using System.Linq;
- using System.Text;
- using System.Web;
- using System.Xml;
-
- /// <summary>
- /// Obejct is the incoming XML-RPC Request. Handles parsing the XML-RPC and
- /// fills its properties with the values sent in the request.
- /// </summary>
- internal class XMLRPCRequest
- {
- #region Constants and Fields
-
- /// <summary>
- /// The input params.
- /// </summary>
- private List<XmlNode> inputParams;
-
- #endregion
-
- #region Constructors and Destructors
-
- /// <summary>
- /// Initializes a new instance of the <see cref="XMLRPCRequest"/> class.
- /// Loads XMLRPCRequest object from HttpContext
- /// </summary>
- /// <param name="input">
- /// incoming HttpContext
- /// </param>
- public XMLRPCRequest(HttpContext input)
- {
- var inputXml = ParseRequest(input);
-
- // LogMetaWeblogCall(inputXml);
- this.LoadXmlRequest(inputXml); // Loads Method Call and Associated Variables
- }
-
- #endregion
-
- #region Properties
-
- /// <summary>
- /// Gets AppKey is a key generated by the calling application. It is sent with blogger API calls.
- /// </summary>
- /// <remarks>
- /// BlogEngine.NET doesn't require specific AppKeys for API calls. It is no longer standard practive.
- /// </remarks>
- public string AppKey { get; private set; }
-
- /// <summary>
- /// Gets ID of the Blog to call the function on. Since BlogEngine supports only a single blog instance,
- /// this incoming parameter is not used.
- /// </summary>
- public string BlogID { get; private set; }
-
- /// <summary>
- /// Gets MediaObject is a struct sent by the metaWeblog.newMediaObject function.
- /// It contains information about the media and the object in a bit array.
- /// </summary>
- public MWAMediaObject MediaObject { get; private set; }
-
- /// <summary>
- /// Gets Name of Called Metaweblog Function
- /// </summary>
- public string MethodName { get; private set; }
-
- /// <summary>
- /// Gets Number of post request by the metaWeblog.getRecentPosts function
- /// </summary>
- public int NumberOfPosts { get; private set; }
-
- /// <summary>
- /// Gets Metaweblog Page Struct
- /// </summary>
- public MWAPage Page { get; private set; }
-
- /// <summary>
- /// Gets PageID Guid in string format
- /// </summary>
- public string PageID { get; private set; }
-
- /// <summary>
- /// Gets Password for user validation
- /// </summary>
- public string Password { get; private set; }
-
- /// <summary>
- /// Gets Metaweblog Post struct containing information post including title, content, and categories.
- /// </summary>
- public MWAPost Post { get; private set; }
-
- /// <summary>
- /// Gets The PostID Guid in string format
- /// </summary>
- public string PostID { get; private set; }
-
- /// <summary>
- /// Gets a value indicating whether or not a post will be marked as published by BlogEngine.
- /// </summary>
- public bool Publish { get; private set; }
-
- /// <summary>
- /// Gets Login for user validation
- /// </summary>
- public string UserName { get; private set; }
-
- #endregion
-
- #region Methods
-
- /// <summary>
- /// Creates a Metaweblog Media object from the XML struct
- /// </summary>
- /// <param name="node">
- /// XML contains a Metaweblog MediaObject Struct
- /// </param>
- /// <returns>
- /// Metaweblog MediaObject Struct Obejct
- /// </returns>
- private static MWAMediaObject GetMediaObject(XmlNode node)
- {
- var name = node.SelectSingleNode("value/struct/member[name='name']");
- var type = node.SelectSingleNode("value/struct/member[name='type']");
- var bits = node.SelectSingleNode("value/struct/member[name='bits']");
- var temp = new MWAMediaObject
- {
- name = name == null ? string.Empty : name.LastChild.InnerText,
- type = type == null ? "notsent" : type.LastChild.InnerText,
- bits = Convert.FromBase64String(bits == null ? string.Empty : bits.LastChild.InnerText)
- };
-
- return temp;
- }
-
- /// <summary>
- /// Creates a Metaweblog Page object from the XML struct
- /// </summary>
- /// <param name="node">
- /// XML contains a Metaweblog Page Struct
- /// </param>
- /// <returns>
- /// Metaweblog Page Struct Obejct
- /// </returns>
- private static MWAPage GetPage(XmlNode node)
- {
- var temp = new MWAPage();
-
- // Require Title and Description
- var title = node.SelectSingleNode("value/struct/member[name='title']");
- if (title == null)
- {
- throw new MetaWeblogException("06", "Page Struct Element, Title, not Sent.");
- }
-
- temp.title = title.LastChild.InnerText;
-
- var description = node.SelectSingleNode("value/struct/member[name='description']");
- if (description == null)
- {
- throw new MetaWeblogException("06", "Page Struct Element, Description, not Sent.");
- }
-
- temp.description = description.LastChild.InnerText;
-
- var link = node.SelectSingleNode("value/struct/member[name='link']");
- if (link != null)
- {
- temp.link = node.SelectSingleNode("value/struct/member[name='link']") == null ? null : link.LastChild.InnerText;
- }
-
- var dateCreated = node.SelectSingleNode("value/struct/member[name='dateCreated']");
- if (dateCreated != null)
- {
- try
- {
- var tempDate = dateCreated.LastChild.InnerText;
- temp.pageDate = DateTime.ParseExact(
- tempDate,
- "yyyyMMdd'T'HH':'mm':'ss",
- CultureInfo.InvariantCulture,
- DateTimeStyles.AssumeUniversal);
- }
- catch (Exception ex)
- {
- // Ignore PubDate Error
- Debug.WriteLine(ex.Message);
- }
- }
-
- // Keywords
- var keywords = node.SelectSingleNode("value/struct/member[name='mt_keywords']");
- temp.mt_keywords = keywords == null ? string.Empty : keywords.LastChild.InnerText;
-
- var pageParentId = node.SelectSingleNode("value/struct/member[name='wp_page_parent_id']");
- temp.pageParentID = pageParentId == null ? null : pageParentId.LastChild.InnerText;
-
- return temp;
- }
-
- /// <summary>
- /// Creates a Metaweblog Post object from the XML struct
- /// </summary>
- /// <param name="node">
- /// XML contains a Metaweblog Post Struct
- /// </param>
- /// <returns>
- /// Metaweblog Post Struct Obejct
- /// </returns>
- private static MWAPost GetPost(XmlNode node)
- {
- var temp = new MWAPost();
-
- // Require Title and Description
- var title = node.SelectSingleNode("value/struct/member[name='title']");
- if (title == null)
- {
- throw new MetaWeblogException("05", "Page Struct Element, Title, not Sent.");
- }
-
- temp.title = title.LastChild.InnerText;
-
- var description = node.SelectSingleNode("value/struct/member[name='description']");
- if (description == null)
- {
- throw new MetaWeblogException("05", "Page Struct Element, Description, not Sent.");
- }
-
- temp.description = description.LastChild.InnerText;
-
- var link = node.SelectSingleNode("value/struct/member[name='link']");
- temp.link = link == null ? string.Empty : link.LastChild.InnerText;
-
- var allowComments = node.SelectSingleNode("value/struct/member[name='mt_allow_comments']");
- temp.commentPolicy = allowComments == null ? string.Empty : allowComments.LastChild.InnerText;
-
- var excerpt = node.SelectSingleNode("value/struct/member[name='mt_excerpt']");
- temp.excerpt = excerpt == null ? string.Empty : excerpt.LastChild.InnerText;
-
- var slug = node.SelectSingleNode("value/struct/member[name='wp_slug']");
- temp.slug = slug == null ? string.Empty : slug.LastChild.InnerText;
-
- var authorId = node.SelectSingleNode("value/struct/member[name='wp_author_id']");
- temp.author = authorId == null ? string.Empty : authorId.LastChild.InnerText;
-
- var cats = new List<string>();
- var categories = node.SelectSingleNode("value/struct/member[name='categories']");
- if (categories != null)
- {
- var categoryArray = categories.LastChild;
- var categoryArrayNodes = categoryArray.SelectNodes("array/data/value/string");
- if (categoryArrayNodes != null)
- {
- cats.AddRange(categoryArrayNodes.Cast<XmlNode>().Select(
- catnode => catnode.InnerText));
- }
- }
-
- temp.categories = cats;
-
- // postDate has a few different names to worry about
- var dateCreated = node.SelectSingleNode("value/struct/member[name='dateCreated']");
- var pubDate = node.SelectSingleNode("value/struct/member[name='pubDate']");
- if (dateCreated != null)
- {
- try
- {
- var tempDate = dateCreated.LastChild.InnerText;
- temp.postDate = DateTime.ParseExact(
- tempDate,
- "yyyyMMdd'T'HH':'mm':'ss",
- CultureInfo.InvariantCulture,
- DateTimeStyles.AssumeUniversal);
- }
- catch (Exception ex)
- {
- // Ignore PubDate Error
- Debug.WriteLine(ex.Message);
- }
- }
- else if (pubDate != null)
- {
- try
- {
- var tempPubDate = pubDate.LastChild.InnerText;
- temp.postDate = DateTime.ParseExact(
- tempPubDate,
- "yyyyMMdd'T'HH':'mm':'ss",
- CultureInfo.InvariantCulture,
- DateTimeStyles.AssumeUniversal);
- }
- catch (Exception ex)
- {
- // Ignore PubDate Error
- Debug.WriteLine(ex.Message);
- }
- }
-
- // WLW tags implementation using mt_keywords
- var tags = new List<string>();
- var keywords = node.SelectSingleNode("value/struct/member[name='mt_keywords']");
- if (keywords != null)
- {
- var tagsList = keywords.LastChild.InnerText;
- foreach (var item in
- tagsList.Split(',').Where(item => string.IsNullOrEmpty(tags.Find(t => t.Equals(item.Trim(), StringComparison.OrdinalIgnoreCase)))))
- {
- tags.Add(item.Trim());
- }
- }
-
- temp.tags = tags;
-
- return temp;
- }
-
- /// <summary>
- /// Loads object properties with contents of passed xml
- /// </summary>
- /// <param name="xml">
- /// xml doc with methodname and parameters
- /// </param>
- private void LoadXmlRequest(string xml)
- {
- var request = new XmlDocument();
- try
- {
- if (!(xml.StartsWith("<?xml") || xml.StartsWith("<method")))
- {
- xml = xml.Substring(xml.IndexOf("<?xml"));
- }
-
- request.LoadXml(xml);
- }
- catch (Exception ex)
- {
- throw new MetaWeblogException("01", string.Format("Invalid XMLRPC Request. ({0})", ex.Message));
- }
-
- // Method name is always first
- if (request.DocumentElement != null)
- {
- this.MethodName = request.DocumentElement.ChildNodes[0].InnerText;
- }
-
- // Parameters are next (and last)
- var xmlParams = request.SelectNodes("/methodCall/params/param");
- if (xmlParams != null)
- {
- this.inputParams = xmlParams.Cast<XmlNode>().ToList();
- }
-
- // Determine what params are what by method name
- switch (this.MethodName)
- {
- case "metaWeblog.newPost":
- this.BlogID = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- this.Post = GetPost(this.inputParams[3]);
- this.Publish = this.inputParams[4].InnerText != "0" && this.inputParams[4].InnerText != "false";
-
- break;
- case "metaWeblog.editPost":
- this.PostID = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- this.Post = GetPost(this.inputParams[3]);
- this.Publish = this.inputParams[4].InnerText != "0" && this.inputParams[4].InnerText != "false";
-
- break;
- case "metaWeblog.getPost":
- this.PostID = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- break;
- case "metaWeblog.newMediaObject":
- this.BlogID = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- this.MediaObject = GetMediaObject(this.inputParams[3]);
- break;
- case "metaWeblog.getCategories":
- case "wp.getAuthors":
- case "wp.getPageList":
- case "wp.getPages":
- case "wp.getTags":
- this.BlogID = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- break;
- case "metaWeblog.getRecentPosts":
- this.BlogID = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- this.NumberOfPosts = Int32.Parse(this.inputParams[3].InnerText, CultureInfo.InvariantCulture);
- break;
- case "blogger.getUsersBlogs":
- case "metaWeblog.getUsersBlogs":
- this.AppKey = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- break;
- case "blogger.deletePost":
- this.AppKey = this.inputParams[0].InnerText;
- this.PostID = this.inputParams[1].InnerText;
- this.UserName = this.inputParams[2].InnerText;
- this.Password = this.inputParams[3].InnerText;
- this.Publish = this.inputParams[4].InnerText != "0" && this.inputParams[4].InnerText != "false";
-
- break;
- case "blogger.getUserInfo":
- this.AppKey = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- break;
- case "wp.newPage":
- this.BlogID = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- this.Page = GetPage(this.inputParams[3]);
- this.Publish = this.inputParams[4].InnerText != "0" && this.inputParams[4].InnerText != "false";
-
- break;
- case "wp.getPage":
- this.BlogID = this.inputParams[0].InnerText;
- this.PageID = this.inputParams[1].InnerText;
- this.UserName = this.inputParams[2].InnerText;
- this.Password = this.inputParams[3].InnerText;
- break;
- case "wp.editPage":
- this.BlogID = this.inputParams[0].InnerText;
- this.PageID = this.inputParams[1].InnerText;
- this.UserName = this.inputParams[2].InnerText;
- this.Password = this.inputParams[3].InnerText;
- this.Page = GetPage(this.inputParams[4]);
- this.Publish = this.inputParams[5].InnerText != "0" && this.inputParams[5].InnerText != "false";
-
- break;
- case "wp.deletePage":
- this.BlogID = this.inputParams[0].InnerText;
- this.UserName = this.inputParams[1].InnerText;
- this.Password = this.inputParams[2].InnerText;
- this.PageID = this.inputParams[3].InnerText;
- break;
- default:
- throw new MetaWeblogException("02", string.Format("Unknown Method. ({0})", this.MethodName));
- }
- }
-
- /*
- /// <summary>
- /// The log meta weblog call.
- /// </summary>
- /// <param name="message">
- /// The message.
- /// </param>
- private void LogMetaWeblogCall(string message)
- {
- var saveFolder = HttpContext.Current.Server.MapPath(BlogSettings.Instance.StorageLocation);
- var saveFile = Path.Combine(saveFolder, "lastmetaweblogcall.txt");
-
- try
- {
- // Save message to file
- using (var fileWrtr = new FileStream(saveFile, FileMode.OpenOrCreate, FileAccess.Write))
- {
- using (var streamWrtr = new StreamWriter(fileWrtr))
- {
- streamWrtr.WriteLine(message);
- }
- }
- }
- catch
- {
- // Ignore all errors
- }
- }
- */
-
- /// <summary>
- /// Retrieves the content of the input stream
- /// and return it as plain text.
- /// </summary>
- /// <param name="context">
- /// The context.
- /// </param>
- /// <returns>
- /// The parse request.
- /// </returns>
- private static string ParseRequest(HttpContext context)
- {
- var buffer = new byte[context.Request.InputStream.Length];
-
- context.Request.InputStream.Position = 0;
- context.Request.InputStream.Read(buffer, 0, buffer.Length);
-
- return Encoding.UTF8.GetString(buffer);
- }
-
- #endregion
- }
- }