Simon Fell > Its just code

Monday, June 7, 2004

A popular question recently, you have 2 choices, (1) go grab the WSDL Wizard and have it generate all the code for you or (2) follow this example.

This quick demo will call a method from the SOAPBuilders Interop tests called echoStructArray, this method takes an array of structures (aka ComplexTypes) as input and echos the array back as output (see the WSDL for the details. By default, an array of complex types is going to be represented in PocketSOAP as an array of CoSoapNode objects, each Node object will have child nodes in the Nodes property containing the child elements. So to create an array of complex types, we need to declare the array, then populate each array item with a CoSoapNode object, e.g.

    Dim arr(2) As Object
    Set arr(0) = makeSoapStruct("String one", 1, 1.1)
    Set arr(1) = makeSoapStruct("String two", 2, 2.2)
    Set arr(2) = makeSoapStruct("String three", 3, 3.3)

Where makeSoapStruct is defined as

' helper function to create a SOAPStruct complex type
Private Function makeSoapStruct(varString As String, varInt As Long, varFloat As Single) As CoSoapNode
    Dim ct As New CoSoapNode
    ct.Nodes.Create "varString", varString
    ct.Nodes.Create "varInt", varInt
    ct.Nodes.Create "varFloat", varFloat
    Set makeSoapStruct = ct
End Function

To handle the response, its just the reverse, grab the parameter, its value will be an array of variants, each variant will contain a CoSoapNode object, e.g.

    'get the returned array
    Dim res()
    res = e.Parameters.Item(0).Value
    ' iterate over it
    Dim idx As Integer
    Dim n As CoSoapNode
    For idx = LBound(res) To UBound(res)
        ' each item in the array is a soapnode, with child nodes for varString, varInt, varFloat
        Set n = res(idx)
        List1.AddItem n.Nodes.ItemByName("varString").Value & " " & n.Nodes.ItemByName("varInt").Value & " " & n.Nodes.ItemByName("varFloat").Value
    Next

That's all there is to it!. The full VB code is available for download (2k), for reference, these are the generated request and response messages from this code.

POST http://soap.4s4c.com/ilab/soap.asp HTTP/1.1
Host: soap.4s4c.com
Accept-Charset: UTF-8, UTF-16;q=0.8, iso-8859-1;q=0.8
Accept-Encoding: deflate, gzip
Content-Type: text/xml; charset=UTF-8
SOAPAction: "http://soapinterop.org/"
User-Agent: PocketSOAP/1.5.b1/PocketHTTP/1.2
Content-Length: 1209

<S:Envelope
	xmlns:Enc="http://schemas.xmlsoap.org/soap/encoding/"
	xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:a="http://soapinterop.org/"
	xmlns:XS="http://www.w3.org/2001/XMLSchema"
	xmlns:XI="http://www.w3.org/2001/XMLSchema-instance">
 <S:Body>
  <a:echoStructArray S:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <inputStructArray XI:type="Enc:Array" Enc:arrayType="XS:anyType[3]">
      <x href="#3dd43e4"/>
      <x href="#3ddd48c"/>
      <x href="#3dd42bc"/>
    </inputStructArray>
   </a:echoStructArray>
   <x S:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" Enc:root="0" id="3dd42bc">
    <varString XI:type="XS:string">String three</varString>
    <varInt XI:type="XS:int">3</varInt>
    <varFloat XI:type="XS:float">3.3</varFloat>
   </x>
   <x S:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" Enc:root="0" id="3ddd48c">
    <varString XI:type="XS:string">String two</varString>
    <varInt XI:type="XS:int">2</varInt>
    <varFloat XI:type="XS:float">2.2</varFloat>
   </x>
   <x S:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" Enc:root="0" id="3dd43e4">
    <varString XI:type="XS:string">String one</varString>
    <varInt XI:type="XS:int">1</varInt>
    <varFloat XI:type="XS:float">1.1</varFloat>
   </x>
 </S:Body>
</S:Envelope>
HTTP/1.1 200 OK
Date: Tue, 08 Jun 2004 03:23:52 GMT
Server: Microsoft-IIS/5.0
Content-Length: 1175
Content-Type: text/xml; charset=UTF-8
Expires: Tue, 08 Jun 2004 03:23:52 GMT
Cache-control: private
X-Cache: MISS from mayhem.pocketsoap.com

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
 <SOAP-ENV:Body>
  <m:echoStructArrayResponse xmlns:m="http://soapinterop.org/">
   <outputStructArray xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="ns1:SOAPStruct[3]" xmlns:ns1="http://soapinterop.org/xsd">
    <SOAPStruct xsi:type="ns1:SOAPStruct">
     <varString xsi:type="xsd:string">String one</varString>
     <varInt xsi:type="xsd:int">1</varInt>
     <varFloat xsi:type="xsd:float">1.1</varFloat>
    </SOAPStruct>
    <SOAPStruct xsi:type="ns1:SOAPStruct">
     <varString xsi:type="xsd:string">String two</varString>
     <varInt xsi:type="xsd:int">2</varInt>
     <varFloat xsi:type="xsd:float">2.2</varFloat>
    </SOAPStruct>
    <SOAPStruct xsi:type="ns1:SOAPStruct">
     <varString xsi:type="xsd:string">String three</varString>
     <varInt xsi:type="xsd:int">3</varInt>
     <varFloat xsi:type="xsd:float">3.3</varFloat>
    </SOAPStruct>
   </outputStructArray>
  </m:echoStructArrayResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Sunday, May 9, 2004

This tutorial shows how to use PocketSOAP to access SForce, the Salesforce.com Web Services API.

  • First off, if you don't have a salesforce.com account, head over to sforce.com and sign up for the free developers edition account
  • Next, make sure you've got PocketSOAP and the PocketSOAP WSDL Wizard (v2.3 or greater) installed.
  • Now we need to grab the WSDL for your account, login to salesforce.com, click the setup link at the top right, then from the left menu under studio select WSDL Generator. Finally, right click on the Download Enterprise WSDL link and select save link to disk, and save the WSDL somewhere on your machine.
  • Now we can run it through the WSDL Wizard to get an easy to use object model generated for us. Start the WSDL Wizard, enter the path and filename of the WSDL in the top box, and the second line select a directory for it to generate the VB6 files to, and enter sforce as the name of the project in the bottom box.
  • Hit next, you'll be presented with the list of bindings, of which there's only one, so hit next again, now you can see the list of methods, leave them all selected and hit next again. The Wizard will now generate the code, then say its finished. Click OK to close the wizard.
  • If everything went according to plan, you now have a ton of generated VB code (~200 classes!), open the sforce.vbp project and compile it.
  • Now start a new VB standard EXE project, and do add reference, scroll down the list and pick "SForce Proxy class....". The main entry point into the generated proxy code is the Soap class (this is named from the WSDL), if you look at this in the object browser, you'll see a bunch of methods, one for each one listed in the WSDL.

Now, in order to access the data we need to login, so drop a button on your form, and add this code

    ' create the proxy object and the login message
    Dim svc As New Soap
    Dim lr As loginResponse
    Dim lo As New login
    lo.Username = "<your login>"
    lo.password = "<your password>"
    ' login
    Set lr = svc.login(lo)

SForce uses a document/literal style service, so the programming model exposed by the generated proxy has a method for each operation in the WSDL where each method takes an object that represents the request message, and returns an object that represents the response message. In addition any SOAP headers that may apply to the operation are also passed as parameters to the method (this is likely different to the programming model generated by other tools, I'll save why I think this is better for another day)

Now, going back to our login code, you can see that we create an instance of the login message, populate its data (username & password in this case), and call the login method, this returns a loginResponse message.

The loginResponse message contains a single loginResult stucture that contains a few pieces of useful information, the 2 important ones are the serverUrl and the sessionId. In the SForce world, once you're authenticated you communicate with a different server (as indicated by the serverUrl value), and you tell it your authentication info by passing the sessionId back to the server in a SOAP Header. So what we'll do next is create the SOAP header object, and populate it with the sessionId, and point the proxy object at the new Url.

    ' create the session header, and update the server Url that we connect to
    Dim sh As New SessionHeader
    sh.sessionId = lr.result.sessionId
    svc.Url = lr.result.serverUrl

Now, we'll create a couple of new Accounts, we do this via the create operation, here's how the object browser shows the create method.

The create_ parameter is the create message, and there's 2 headers we can send, the SessionHeader which we've already discussed and the SaveOptions header, this header lets use control how lead assignment is handled, which we don't care about for Accounts, so we can just pass nothing for that in this case.

The create message contains an array of sObjects, everything in Salesforce.com is based on an sObject, the Account object inherits (or extends in XSD speak) from sObject. So, we need to create an array of sObjects, where each item in the array is an account. One wrinkle is that VB won't let you pass a statically sized array to a property call, so you need to ensure that your array is dynamically sized (i.e. use redim)

    ' create 2 new accounts, note that the create call uses an object hierarchy    
    ' but in VB we need to pass sObject() to the create call, so declare the array
    ' as that, but populate it with account objects
    Dim acc() As sObject
    ReDim acc(1)
    Dim na As New Account
    na.Name = "Simon's Test Account"
    na.AccountNumber = "42424242"
    na.AnnualRevenue = 10000
    Set acc(0) = na
    Set na = New Account
    na.Name = "Simon's other test account"
    na.AccountNumber = "24242424"
    na.AnnualRevenue = 11111
    Set acc(1) = na

Now we've got the 2 accounts we want to create, we can create the Create message, and make the call to the create operation.

    ' do the create call
    Dim cr As New Create
    cr.sObjects = acc
    Dim cres As createResponse
    Set cres = svc.Create(cr, sh, Nothing)

All that's left is to check the response, to see if there are any errors (as there might be an error with only a single object, there's a separate error indication for each Account we tried to create).

    ' check the results
    Dim idx As Long
    For idx = LBound(cres.result) To UBound(cres.result)
        If Not cres.result()(idx).success Then
            debug.print "failed creating account: " & cres.result()(idx).errors()(0).message
        Else
            debug.print "created account with Id " + cres.result()(idx).id
        End If
    Next

That's it!, you can now login through the web interface and see the new accounts you've created, the rest of the functions all work in the same manner, finally the describeSObject call exposes a lot of information about the fields on each of the sObjects derived types in the system (including any custom fields or custom objects you may of created yourself through studio), making it easy to do grid views and similar that are completely driven by the meta data.

Sunday, May 25, 2003

I read a lot of technical books, here are a few of my recent reads that I liked. (in no particular order)

  • Programming the Microsoft Windows Driver Model (Walter Oney)
  • Windows Forms Programming in C# (Chris Sells)
  • Beyond Fear (Bruce Schneier)
  • Loosely Coupled (Doug Kay)
  • Essential ASP.NET (Fritz Onion)
  • Essential .NET volume 1 (Don Box)
  • .NET Web Services: Architecture and Implementation with .NET (Keith Ballinger)
  • More Exceptional C++ (Herb Sutter)
  • Advanced .NET Remoting (Ingo Rammer)
  • Definitive XML Schema (Priscilla Walmsley)
  • Effective STL (Scott Meyers)
  • Transactional COM+ (Tim Ewald)
  • C# Essentials (Peter Drayton & co)
  • Essential IDL (Martin Gudgen)
  • ASP Internals (John Flanders)
  • Secrets & Lies (Bruce Schneier)
  • Planning Extreme Programming (Kent Beck, Martin Fowler)
  • Network Security Private communication in a public world (Charlie Kaufman, Radia Perlman & Mike Speciner)
  • The Pragmatic Progammer (Andrew Hunt & David Thomas), I liked this so much, i brought copies for everyone on my team.
  • Programming Windows Security (Keith Brown)
  • Essential XML (Don Box, Aaron Skonnard & John Lam)
  • Exceptional C++ (Herb Sutter)
  • Debugging Applications (John Robbins)
I'm currently reading
  • Windows Forms Programming in C#
  • Mac OSX for Unix Geeks
  • Applied .NET Framework Programming (Jeffrey Richter)

Saturday, May 17, 2003

Syndirella is an RSS aggregator written in C# by Dmitry Jemerov released under the GPL license. This page details a fork of the code base that I've been adding new features to.

Latest drop is 20030509-BT (released May 16, 2003) and is based on Dmitry's drop of May 9, and adds the following features

  • Plugin support. Supports both IBlogThis and IBlogExtension based plugins. Multiple plugs in are supported, just drop them in a plugins directory under the main Synderilla executable.
  • Support for displaying xhtml:body based item content.
  • Support for gzip/deflate compression when retrieving RSS feeds over HTTP.

Grab the binaries or source.

An earlier drop is detailed here

Tuesday, April 8, 2003

Being able to post to a weblog from within an RSS aggregator is a really useful feature that not many tools currently have. The proliferation of blogging API compounds the problem. Given the number of .NET based aggregators now around, I had a vision for a simple extensibility point within the aggregator to be able to hook in 3rd party blogging tools. This page documents my thoughts, ideas, and code to date.

IBlogExtension

Greg, Luke, Matt, and I discussed a new version of the interface that resulted in IBlogExtension.

A signed version of the assembly containing the IBlogExtension definition is available.

Aggregators

Plug-Ins


Previous version

IBlogThis enabled Aggregators

BlogThis plug-ins

BlogIT extension to BlogThis

IBlogThis history

Tuesday, April 8, 2003

In progress - A RESTLog client application.

relaxer in action

Version 0.6 (October 18, 2005)

binaries and/or source
  • Support for uploading "media" files (images, zips etc, supporting files for a blog post), just drop the file on the Media Upload Zone. (requires the latest RESTLog.NET server code)

Version 0.5 (May 16, 2003)

binaries and/or source.
  • Support for IBlogExtension added.
  • Improvements to the trackback/pingback client.

Version 0.4 (April 27, 2003)

binairies and/or source.
  • Pingback and Trackback client support added.
  • Support for getting the now playing info from Windows Media Player (requires the WMP blogging plugin)

Version 0.3 (April 15, 2003)

binairies and/or source.
  • BlogThis integration updated to current spec.
  • Spell Checker now behaves in a more expected manner (closing the dialog, cancels the spell check, and cancels the post)
  • code button added for turning the selected part of the post into a <pre> wrapped section, it also entity encodes the selection, make its easy to cut'n'paste exsiting code/xml etc into a post.
  • xml-rpc pings are now sent asynchronously
  • dropping a link on the form will select the best match weblog from all those configured, rather than requiring you to pick the right one first.

Version 0.2 (April 9, 2003)

Sunday, April 6, 2003

Installation
This assumes you're familar with configuring IIS & ASP.NET.

  • Make sure you have ASP.NET installed and running correctly first.
  • unzip the file, preserving directories somewhere convienient ( e.g. c:\inetpub\wwwroot\blog )
  • if you need to, goto IIS admin and create a virtual directory that maps to the directory with the index.config file in. Note that this is entirely optional, but makes things slightly easier.
  • If you didn't create a virtual dir, then move the dll's out of the bin directory to the parent app's bin directory ( e.g. c:\inetpub\wwwroot\bin )
  • Using IIS admin add an application mapping for .html to the ASP.NET Isapi extension. make sure that "check that file exists" is NOT checked. If you choose the limit verbs option, you need to allow GET, POST, PUT, DELETE.
Configuration

Configuration settings for the weblog are stored in the web.config file, open it up in notead, emac, vi, or whatever your particular text editor posion is.

  • <configSections> - this registers the handler for the <restlog.net> section.
  • <httpHandlers> - this maps .html requests onto the weblog engine.
  • <restlog.net> - this houses all the weblog configuration, this is what you'll want to edit.
    • <title> - the title of your weblog, this appears on the web pages, as well as being included in the generated RSS file.
    • <description> - the tagline/description for your weblog, this also appears on the web pages and the RSS file.
    • <author> - enter the name of the weblog's author
    • <indexMaxPosts> - controls the number of entries that appear on the main page, the default is to show the most recent 15 posts, wind this up or down as the mood takes you.
    • <rssMaxPosts> - controls the number of entries that appear in the RSS file, the default is to show the most recent 15 posts, wind this up or down as the mood takes you.
    • <doPingbacks> - If enabled (by setting the value to true), each time you make a new post, it will automatically check the post for links, and send pingbacks to those servers that support it.
    • <rss> - the name of the generated rss file.
    • <basepath> - Important set this to the external path to the root of the blog, i.e., if you installed to c:\inetpub\wwwroot\blog\, then it would be /blog/ if you created a virtual directory call weblog in the root of the web server then it would be /weblog/
    • <templates> - the names of the 3 templates used. by default these are mapped to .config files, as these won't be served to external clients.
      • <main> - this is the main index page, that shows the most recent posts.
      • <monthly> - this is the monthly archive page, by default it uses the same template as the main index, but it doesn't have to, if you want your monthly archive pages to do something different.
      • <item> - this is the template for a single post page.
Templates

The template files index.config and item.config are standard ASPX files, but with a .config file extension. They use ASP.NET's code behind feature so that the weblog engine can provide the relevant information to be rendered. The main and monthly index pages should inherit from the class PocketSoap.RestLog.IndexPage and the item page should inherit from PocketSoap.RestLog.ItemPage.

Both classes expose the information from the web.config file via an instance of the WeblogSettings class available via the Weblog property. The WeblogSettings class has the following properties Title, Description, Author, IndexMaxPosts, RssMaxPosts, DoPingbacks, RssFile, BasePath, MainTemplate, MonthlyTemplate, ItemTemplate.

The Item template exposes the details of the post via an item object, accessed via the Item property, this has the following properties title, description, date, tune, postId, Link, permaLink

The index pages expose a collection (ArrayList) of items to be rendered via the Items property. In addition it has an additional property called ArchiveDate that contains the date of the monthly archived being rendered or the value DateTime.MinValue if its the main index page.

Sunday, April 6, 2003

This weblog is based on an implementation of the RESTLog API that I wrote in .NET. The source code is available under the MIT license, for those who are interesting in running / examining / extending this themselves

Sever (RESTLog.NET v0.1)

The server is implemented as a number of custom HttpHandlers that are compiled to a DLL, and has the following features

  • Any number of weblog instances can be run on a single ASP.NET install.
  • configuration for a particular instance of a weblog is handled entirely in the web.config file.
  • template files (ordinary aspx format pages) are used to control the look & feel / rending of the pages.
  • A static RSS (1.0) file is generated each time there's a change.
  • Support for automatic pingbacks.
  • main index page show recent entries, there are also monthly archive pages and individual post pages.
  • posts are stored as simple XML files, easy to migrate to/from other blogging tools.

You can download the binaries and source for v0.1, then take a gander at the installation and configurations notes. The latest code is available on SourceForge

Client (relaxer.NET v0.6)

A .NET Winforms application for adding/updating/deleting posts for any RESTLog compliant server

  • Simple interface, supports multiple weblogs
  • Spell checker (requires MS Word)
  • Winamp integration (requires WS-Amp) & WMP9 integration (requires the Blog Plugin)
  • Drag'n'drop from the browser to edit.
  • Can ping weblogs.com plus any other servers that implement the weblogs.com ping interface.
  • Includes a pingback & trackback client.

Still in progress, v0.6 is now available.

Client (relaXer v0.1)

A Cocoa application for Mac OS X for adding/updating/deleting posts for any RESTLog compliant server

  • Native Cocoa application
  • Spell Checker
  • iTunes integration
  • Drag'n'drop from the browser to edit

Still in progress, here a screen shot, to keep you going.

Saturday, February 8, 2003

This tool allows you to automatically notify blo.gs (or any number of services that implements the weblogs.com xml-rpc interface) when you update your weblog

Download the blogping.root file and drop it in your Radio Userland\\tools directory and re-start Radio, you should be up and running.

Version History

v0.2 - 3/17/2003

Can now ping any number of servers, defaults to blo.gs and blogrolling.com.

v0.1 - 2/8/2003

Initial Release

Wednesday, January 1, 2003

Pingback provide for a more connected weblogging experience. This tool is a pingback client tool for Radio, it will automatically send pingback's to those servers that support them when you post entries in your weblog.

Download the pingback.root file and drop it in your Radio Userland\tools directory and re-start radio, you should be up and running.

Version History

v0.4 - 1/11/2003

Fixed a bug where the first link in a post wouldn't get pingback checked if there was more than one link in the post. 

v0.3 - 1/8/2003

The <link rel="pingback" ..> tag is now searched for if it can't find a X-Pingback HTTP header as per the auto discovery part of the specification.

The bulk of the pingback work is now spawned off onto a separate thread, so as not to adversly affect upstreaming performance.

Fixed a problem where links with fragment Ids didn't get the fragment Id stripped off the HTTP request.

Verbose logged is turned off [it was on in v0.2 by accident]

v0.2 - 1/1/2003

The pingback url sent now includes the fragmentID of the particular post

v0.1 - 1/1/2003

Initial Release

Saturday, September 28, 2002

An investigation into the current state of namespace awareness in RSS aggregators.

Tests
I defined a set of test RSS feeds, both RSS 1.0 and RSS 2.0, these use a mix of modules, differing namespace usage styles, and clashing localnames, this should give a good indication as to how well current aggregators cope with RSS 1.0 & 2.0's ability to be extended with namespaced modules.
  1. rss1.0withModules.xml
  2. rss1.0withModulesNoDefNS.xml
  3. rss1.0withModulesNoDefNSLocalNameClash.xml
  4. rss2.0noNSwithModules.xml
  5. rss2.0noNSwithModulesLocalNameClash.xml
  6. rss2.0NSwithModules.xml
  7. rss2.0NSwithModulesNoDefNS.xml
  8. rss2.0NSwithModulesNoDefNSLocalNameClash.xml

My own personal suspicion before running any tests is that the aggregators that haven't needed any changes to work with RSS2.0 aren't handling namespaces properly, and the localName clash tests will trip them up.

Results
Aggie RC4 on XP

  1. Fails to show entries
  2. Fails to show entries
  3. Shows entries from wrong namespace (shows the last szf:description item, probably just looking at the last element it finds with a description localname)
  4. Entry appears
  5. Shows entries from wrong namespace (shows the last szf:description item, probably just looking at the last element it finds with a description localname)
  6. Entry appears
  7. Entry appears
  8. Shows entries from wrong namespace (shows the last szf:description item, probably just looking at the last element it finds with a description localname)

It appears that Aggie doesn't really like RSS 1.0, i don't understand yet why test 6&7 (rss2 with NS) work, yet tests 1&2 (rss1) fail. It looks like aggie is ingoring element namespaces, and just looking for localname matches.

Aggie (built from CVS 9/28) on XP

  1. Entry appears
  2. Entry appears
  3. Entry appears
  4. Entry appears
  5. Entry appears
  6. Entry appears
  7. Entry appears
  8. Entry appears
Woo Hoo, 100% pass.

Radio 8.0.5 on XP with radio.root updated 9/28
  1. Entry appears
  2. Entry appears
  3. shows entry from wrong namespace, appears to show the first element with a localname of description
  4. Entry appears
  5. shows entry from wrong namespace, appears to show the first element with a localname of description
  6. Entry appears
  7. Entry appears
  8. shows entry from wrong namespace, appears to show the first element with a localname of description
Radio appears to look at the first element it finds with the localname of description.

NetNewsWire Lite 1.0 on Mac OS 10.2.1
  1. Entry appears
  2. Entry appears
  3. Entry appears
  4. Entry appears
  5. Entry appears
  6. Entry appears
  7. Can't display this subscription because the RSS feed could not be found.
  8. Can't display this subscription because the RSS feed could not be found.
don't know why test 6 works when 7 doesn't is a little strange.

Amphetadesk 0.93 on XP
  1. Entry appears
  2. won't subscribe to channel. "AmphetaDesk could not determine the format of http://www.pocketsoap.com/rssTests/rss1.0withModulesNoDefNS.xml."
  3. won't subscribe to channel. "AmphetaDesk could not determine the format of http://www.pocketsoap.com/rssTests/ rss1.0withModulesNoDefNSLocalNameClash.xml."
  4. Entry appears
  5. Entry appears
  6. Entry appears
  7. won't subscribe to channel. "AmphetaDesk could not determine the format of http://www.pocketsoap.com/rssTests/rss2.0NSwithModulesNoDefNS.xml."
  8. won't subscribe to channel. "AmphetaDesk could not determine the format of http://www.pocketsoap.com/rssTests/ rss2.0NSwithModulesNoDefNSLocalNameClash.xml."

It appears that Amphetadesk incorrectly keys of the default namespace of the root element to determine the RSS version. Update, Morbus says Amphetadesk just looks for elements in the default namespace.

Conclusions
If you're writing RSS aggregator apps that support RSS 1.0 or RSS 2.0, run, don't walk, and go read the XML Namespaces rec.

 

Saturday, June 1, 2002

I boiled the IIS authentication and persistent connections issue down to a simple test, and have seen this behavour on IIS 5.0 on W2K server w/SP2 and IIS 5.1 on XP Pro.

Create a simple HTML file foo.htm and drop it in the wwwroot\\inetpub directory, start IIS admin, expand the tree to so that you can see foo.htm, right click properties pick file security, click authentication methods, turn off everything except basic authentication and select a default domain. You will need an account called bang with a password of bang

Telnet to the server and send

GET /foo.htm HTTP/1.1
Host: localhost

you should get back a 401 response, this proves that IIS is configured for authentication only

HTTP/1.1 401 Access Denied
Server: Microsoft-IIS/5.1
Date: Sun, 02 Jun 2002 05:46:39 GMT
WWW-Authenticate: Basic realm="simonathome.com"
Connection: close
Content-Length: 4431
Content-Type: text/html

Now, telnet again, and send

GET /foo.htm HTTP/1.1
Host: localhost
Authorization: Basic YmFuZzpiYW5n

You should get a 200 response, with the contents of your file,

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Sun, 02 Jun 2002 05:56:24 GMT
Content-Type: text/html
Accept-Ranges: bytes
Last-Modified: Sun, 02 Jun 2002 05:45:22 GMT
ETag: "c98679aff89c21:9ed"
Content-Length: 54

<html>
<head>
</head>
<body>
foo
</body>
</html>

 the connection should still be open, now send

GET /foo.htm HTTP/1.1
Host: localhost

Rather than the expected 401 authorization error, you get a 200 again, with the file contents.

Sunday, May 19, 2002

Simon wrote: "Here's a suggestion for people writing RSS aggregators, use the HTTP/1.1 Etag and If-None-Match headers so that you only fetch the feed if its changed."

I understand the goal, but not how the implementation would work. Maybe Simon's willing to post some sample header values to shed some light on the idea... [Jake's Radio 'Blog]

Sure, the server response may contain an ETag header, you save this away ascociated with the URL, then on subsequent requests for that url, you include a If-None-Match header with the etag value. If the contents haven't changed, then the server will reply with a 304 Not Modified.

here's an initial request where we don't have a previously obtained etag

GET /weblog/rss.xml HTTP/1.1
Host:
www.pocketsoap.com

And the response

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Mon, 20 May 2002 03:08:54 GMT
Content-Type: text/xml
Accept-Ranges: bytes
Last-Modified: Mon, 20 May 2002 00:20:54 GMT
ETag: "e8d8993494ffc11:b8e"
Content-Length: 9548

<?xml version="1.0"?>
<!-- RSS generated by Radio UserLand v8.0.5 ....

Extract the ETag value, then next time you want that URL, you add the If-None-Match header,

GET /weblog/rss.xml HTTP/1.1
If-None-Match: "e8d8993494ffc11:b8e"
Host:
www.pocketsoap.com

If the file hasn't changed, then it'll still have the same ETag, which matches, so there's no response, just a 304

HTTP/1.1 304 Not Modified
Server: Microsoft-IIS/5.0
Date: Mon, 20 May 2002 03:08:39 GMT
ETag: "e8d8993494ffc11:b8e"
Content-Length: 0

If however the resource has changed, the server assigns it a different Etag, so it no long matches the etag in the request, the server will send the new version

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Mon, 20 May 2002 03:09:54 GMT
Content-Type: text/xml
Accept-Ranges: bytes
Last-Modified: Mon, 20 May 2002 03:09:51 GMT
ETag: "1238993494ffc11:b8f"
Content-Length: 9548

<?xml version="1.0"?>
<!-- RSS generated by Radio UserLand v8.0.5 ....

Wednesday, May 15, 2002

A while back I posted details of how to use PocketSOAP with Word to post new blog entries to Radio.

Here's a new version of that code that now uses PocketXML-RPC this brings a number of advantages

  • Works with other tools besides Radio, the XML-RPC version of the BloggerAPI is implemented by numerous blogging tools.
  • The XML-RPC version of the BloggerAPI can be enabled from the prefs page in Radio, no need to run the script that enables the SOAP version.

In additon it also handles paragraphs better, based on a suggestion from Omar Shahine [who by the way did a Mac port of the SOAP version]

First off, make sure you've got PocketXML-RPC installed, and for the Radio folks goto the prefs page and make sure that XML-RPC & SOAP are enabled, and that the Blogger API is enabled. Now you can make XML-RPC calls to manage your blog.

The code is just a few simple Word macros that use PocketXML-RPC to make the XML-RPC calls to the BloggerAPI. Download this VBA module. Now fire up Word and select Tools -> Macro -> Visual Basic Editor. Now import the module into your document, or if you want the macro's always available, import them into your template (expand the tree Normal -> Microsoft Word Objects and right click and select Import File).

Look at the top of the code, there are some settings you'll need to tweak. First you'll need to enter your username & password, these are configured in the Remote Access & Security prefs page. If you want to use Word on a different machine to the machine running Radio, you'll need to tweak the RADIO_URL setting. Finally if you need to connect via a HTTP proxy, you can alter the PROXY_SERVER and PROXY_PORT settings.

Now switch back to the main word document window, enter your post and hit Tools -> Macro -> Macros -> select PostNewBlogEntry and hit run. This will send the document as a new post to Radio. Now change the entry and run the UpdateBlogEntry macro, this will prompt you for a postID which will default to the just created post. This will now post the revised text as an edit to the original post. Hey presto you're blogging from Word!

The post takes some simple HTML formatting from the document, link, italics & bold are all carried over.

You can use the Tools -> Customize options to assign the macro's to buttons on the toolbar and/or keyboard shortcuts.

 

Thursday, April 11, 2002

Tomorrow marks the one year anniversary of this piece of code, which allowed you to post new blog entries to a Manila hosted blog directly from Word (using PocketSOAP of course). The lack of a spell checker in Radio, combined with my terrible spelling ability prompted me to re-visit this now that I'm in Radio land. The results, a little Word module that allows you to post & update posts from Word to a Radio blog.

Radio implements the Blogger API which is a pure XML-RPC API, however Radio supports both XML-RPC and SOAP, it's a trivial task to enable a SOAP version of the Blogger API. Fire up Radio, open a quick script window and run

    user.soap.rpcHandlers.blogger = @radio.weblog.bloggerApi.rpcHandlers

In additional you'll want to goto the prefs page and make sure that XML-RPC & SOAP are enabled, and that the Blogger API is enabled. Now you can make SOAP calls to manage your blog.

The code is just a few simple Word macros that use PocketSOAP to make the SOAP calls to Radio. Make sure you've got PocketSOAP installed, then download this VBA module. Now fire up Word and select Tools -> Macro -> Visual Basic Editor. Now import the module into your document, or if you want the macro's always available, import them into your template (expand the tree Normal -> Microsoft Word Objects and right click and select Import File).

Look at the top of the code, there are some settings you'll need to tweak. First you'll need to enter your username & password, these are configured in the Remote Access & Security prefs page. If you want to use Word on a different machine to the machine running Radio, you'll need to tweak the RADIO_URL setting. Finally if you need to connect via a HTTP proxy, you can alter the PROXY_SERVER and PROXY_PORT settings.

Now switch back to the main word document window, enter your post and hit Tools -> Macro -> Macros -> select PostNewBlogEntry and hit run. This will send the document as a new post to Radio. Now change the entry and run the UpdateBlogEntry macro, this will prompt you for a postID which will default to the just created post. This will now post the revised text as an edit to the original post. Hey presto you're blogging from Word!

The post takes some simple HTML formatting from the document, link, italics & bold are all carried over.

You can use the Tools -> Customize options to assign the macro's to buttons on the toolbar and/or keyboard shortcuts.

Bing!