MetaWeblog API Mk.1
This is the first stab at building a MetaWeblog API service endpoint. It was mostly successful, though ultimately unwieldy as I had to munge around too much text after a while.
<%@ WebHandler Language="VB" Class="MetaWeblogAPI" %>
Imports System.IO
Imports System.Data
Imports CookComputing.XmlRpc
Imports System.Data.SqlClient
Public Class MetaWeblogAPI
Inherits XmlRpcService : Implements IHttpHandler
Private Shared Sub Authenticate(ByVal username As String, ByVal password As String)
' Check the login and password in the database.
If username = "ukdavidw" And password = "qwko-812" Then
' Authentication ok
Else
Throw New System.Security.Authentication.InvalidCredentialException("Incorrect Password, please try again.")
End If
End Sub
<XmlRpcMethod("blogger.getUsersBlogs")> _
Public Function getUsersBlogs(ByVal appKey As String, ByVal username As String, ByVal password As String) As XmlRpcStruct()
' This is hardcoded to return only the ID of LPC. As its the only blog on this server,
' it makes sense to do it this way instead of accessing the database.
Authenticate(username, password)
Dim rpcstruct As XmlRpcStruct = New XmlRpcStruct
rpcstruct.Add("blogid", "2")
rpcstruct.Add("blogName", "LPC")
rpcstruct.Add("url", "http://davewhite.net")
Dim datarpcstruct As XmlRpcStruct() = New XmlRpcStruct() {rpcstruct}
Return datarpcstruct
End Function
<XmlRpcMethod("metaWeblog.setTemplate")> _
Public Function setTemplate(ByVal appKey As String, ByVal blogid As String, ByVal username As String, ByVal password As String, ByVal template As String, ByVal templateType As String) As Boolean
' Unused - there's only one template
Authenticate(username, password)
Throw New System.NotImplementedException("SetTemplate is not implemented")
End Function
<XmlRpcMethod("metaWeblog.getCategories")> _
Public Function getCategories(ByVal blogid As String, ByVal username As String, ByVal password As String) As XmlRpcStruct()
' This returns a list of categories. Although you don't see them on the front page, they are
' actually there. They're fairly limited and I don't have any real use for them, but I may one day
' expand their use. In looking through this I just found a huge error caused by writing this and then
' re-using some of it without re-writing. Bad Dave, BAD. To be fixed.
Authenticate(username, password)
Dim sqlConn As ConnectionStringSettings
sqlConn = ConfigurationManager.ConnectionStrings("SQLServer")
Dim objConnection As SqlConnection
Dim objRecords As SqlDataReader
Dim strSQL2 As String = "select count(iID) from Categories"
objConnection = New SqlConnection(sqlConn.ConnectionString)
objConnection.Open()
Dim strSQL As String = "select * from Categories"
Dim i As Integer = 0
Dim iRecCount As Integer
Dim objcommand2 As New SqlCommand(strSQL2, objConnection)
iRecCount = objcommand2.ExecuteScalar
Dim categories(iRecCount - 1) As XmlRpcStruct
Dim objCommand As SqlCommand
objCommand = New SqlCommand(strSQL, objConnection)
objRecords = objCommand.ExecuteReader()
Try
If Not objRecords.HasRows Then
Throw New Exception("Oh oh... no categories!")
Exit Try
End If
While objRecords.HasRows AndAlso i < iRecCount
objRecords.Read()
Dim rpcstruct As New XmlRpcStruct
rpcstruct.Add("categoryid", objRecords("iID"))
rpcstruct.Add("title", objRecords("strCategory"))
rpcstruct.Add("description", objRecords("strDescription"))
categories(i) = rpcstruct
System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
End While
Catch ex As Exception
If Not ex.Message = "Invalid attempt to read when no data is present." Then
Throw New Exception("Error : " & ex.Message)
End If
Finally
objRecords.Close()
objConnection.Close()
End Try
Return categories
End Function
<XmlRpcMethod("metaWeblog.getRecentPosts")> _
Public Function getRecentPosts(ByVal blogid As String, ByVal username As String, ByVal password As String, ByVal numberOfPosts As Integer) As XmlRpcStruct()
' This is the routine that is called when WLW opens the Recent Posts from the blog. Firstly we need
' to authenticate that the username and password are indeed authorised...
Authenticate(username, password)
' Then open the database and get the last numberOfPosts entries from the table.
Dim sqlConn As ConnectionStringSettings
sqlConn = ConfigurationManager.ConnectionStrings("SQLServer")
Dim objConn As New SqlConnection(sqlConn.ConnectionString)
objConn.Open()
Dim objRecords As SqlDataReader
' Here we need posts of type 0 and 1, which are Drafts and Published Posts. There's a type 2 which
' is deleted posts, but you never get to see that.
Dim objCommand As New SqlCommand("select top " & numberOfPosts & " * from Blog where PostType in (0,1) order by ID desc")
objCommand.Connection = objConn
objRecords = objCommand.ExecuteReader()
Dim posts(numberOfPosts - 1) As XmlRpcStruct
Dim i As Integer = 0
Try
While objRecords.Read AndAlso i < numberOfPosts
' Loop and build out the XML structure
Dim rpcstruct As XmlRpcStruct = New XmlRpcStruct
rpcstruct.Add("title", objRecords("Title"))
rpcstruct.Add("link", "http://davewhite.net/default.aspx?id=" & objRecords("ID"))
rpcstruct.Add("description", LPC.Functions.TextFromDBToLiveWriter(objRecords("Text")))
rpcstruct.Add("dateCreated", LPC.Functions.GetDateTimeforBlogs(objRecords("DateAdded")))
If objRecords("Guid") Is DBNull.Value Then
rpcstruct.Add("guid", Guid.NewGuid.ToString)
Else
rpcstruct.Add("guid", objRecords("Guid").ToString)
End If
rpcstruct.Add("postid", objRecords("ID"))
rpcstruct.Add("author", "Dave White")
posts(i) = rpcstruct
System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
End While
Catch ex As Exception
Throw New Exception("oh oh..." & ex.Message)
Finally
objRecords.Close()
objConn.Close()
End Try
Return posts
End Function
<XmlRpcMethod("metaWeblog.getTemplate")> _
Public Function getTemplate(ByVal appKey As String, ByVal blogid As String, ByVal username As String, ByVal password As String, ByVal templateType As String) As String
' Returns the template to whatever needs it. You know, I actually have no idea what purpose this
' routine server for a WLW implementation. I have to check that.
Authenticate(username, password)
Dim template As String = "<HTML>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <HEAD>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <TITLE><$BlogTitle$>: <$BlogDescription$></TITLE>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " </HEAD>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <BODY >" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <h1><$BlogTitle$></h1>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <!-- Blogger code begins here -->" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <BLOGGER>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <BlogDateHeader>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <b><h4><$BlogDateHeaderDate$>:</h4></b>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " </BlogDateHeader>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " " & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <a name='<$BlogItemNumber$>'><$BlogItemBody$></a>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <br>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <small><$BlogItemAuthor$> " & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <br>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <center>______________________</center>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " <br>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " </p>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " </BLOGGER>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " '" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " </BODY>" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & " </HTML>"
Return template
End Function