Firefox 3 And Colour Management

I recently came across an article by Datacolor (the company who make the Spyder range of monitor/printer calibrators) which explains how to enable ICC profiles in Firefox 3. It is a very simple boolean (true/false) property which you need to change in the ‘hidden’ Firefox configuration.

In Firefox enter about:config into the address bar and press Enter. A warning message will show up saying “This might void your warranty!” ignore this and click “I’ll be careful, I promise” (don’t worry you don’t have any warranty anyway ;-). Next, in the filter bar type in gfx.color_management.enabled. There should now only be one option in the list of configuration options, and it should be set to false by default. Simply double click this option to change it to true (it should now be bold, indicating it is no longer the default value). Restart Firefox and you should be up and running with ICC profiles.

Check out the original post by Datacolor for more information and for two images which will indicate if your browser supports ICC profiles.

InfoPath Roles And Views

One useful feature of InfoPath is its built in support for user Roles. While it is not an overly powerful (and it should not be used for security purposes as all data can be viewed and edited in XML format via notepad or a similar) it can be handy for automatically switching views based on AD users or groups.

To add a role simply go to Tools -> User Roles (alt + t + e) and click Add (alt + a). You can then specify which users, groups or user names from the form should belong to the new role.

One thing to note is that when you are designing an InfoPath form and click “Preview Form” it shows the form based on the default role. If you wish to preview the form under a different role you need to go to File -> Preview Form -> With User Role… (alt + f + r + r). The form will then be launched in preview mode under the select role.

There is also the option to set a role as either the default role or the initiator role (only one role can occupy either or both of these options). The default setting specifies that this role is the default role for all users, should they not meet the requirements of another role. The initiator setting is the role assigned to a user when they open the InfoPath form for the first time.

Another point of interest is that roles are assessed on a top-down approach, however, you can not change the ordering of roles from within the InfoPath IDE. In order to change the ordering of roles, should you be required to, you must open the manifest.xsf and manually reorder the <xsf:role /> elements.

Creating A Simple SharePoint Workflow In SharePoint Designer

This one is a quick and easy one but is the basis for creating some very useful workflows in for use in SharePoint lists. Firstly you will need a SharePoint website and a copy of SharePoint Designer (a 60-day trial version is available from Microsoft) and a list in SharePoint which you can apply the workflow to – for this example, I am using a fairly simple Travel Requisition list which is a document library which contains InfoPath documents.

To create the workflow open SharePoint Designer and connect to your SharePoint website. Once connected, go to File -> New and select the SharePoint Content tab and select Workflow (blank workflow). You should now be presented with a form similar to the following. Here you can specify a name for your workflow (each workflow in a site must have a unique name) which list the workflow is attached (associated) to and when the workflow should be triggered. In this case, we want to trigger the workflow whenever a list item is added or updated.

Continue reading “Creating A Simple SharePoint Workflow In SharePoint Designer”

Fort Lytton

Fort Lytton, Brisbane, Australia
Fort Lytton, Brisbane, Australia

Fort Lytton is a pentagonal fortress, built near the mouth of the Brisbane River, erected in 1881 to aid the controlled river mines in defending the Port of Brisbane until the end of the Second World War. It was Brisbane’s front line of defence and is regarded as the birthplace of Queensland military history. The fort is surrounded by a water-filled moat and connected by underground passages (although these underground passages do not appear to be visible anymore). After the Second World War, the fort was no longer deemed ‘useful’ and as such fell into a state of disrepair until Ampol took over the site in 1963 and later became a national park in 1988.

By the turn of the century, the Fort consisted of six gun pits and two machine gun posts. The arsenal included (Most of which can be seen at the Fort either in their original placing or in the historical museum – some of the larger fixed emplacements are replicas now):

  • 2x 6 inch BL 5 tonne Armstrong guns
  • 2x 6 pounder QF Hotchkiss guns
  • 1x 4 barrel 1-inch Nordenfelt machine gun
  • 1x 10 barrel 0.45inch Nordenfelt machine gun
  • 2x 64 pounder RML guns

The Fort is open every Sunday and on public holidays from 10am until 4pm. Entry fee is $4.50 for adults (includes a tour or self-exploration if you wish) but is a small price to pay for a good afternoon of historical exploration. Additionally (unconfirmed if this is every Sunday or only during certain times throughout the year) they fire one of the cannons three times during the day. When I visit the site the times posted were 11am, 1pm and 3pm. If you’re a budding photographer I would suggest arriving just prior to 11 am to catch the first cannon firing and then after spending the next two hours wandering around and having a bite to eat (great spot for a picnic lunch – portable bbq’s are welcome) it will be time for the second firing. You might be surprised how quick the firing happens, I certainly was!

See additional photos from Fort Lytton.

Update: I’ve been told that they fire the cannons the first Sunday of every month.

Historical information from: http://www.epa.qld.gov.au/parks_and_forests/find_a_park_or_forest/fort_lytton_national_park Continue reading “Fort Lytton”

Must Do: Lamington National Park

Lamington National Park

Lamington National Park is approximately two hours drive South / South-West of Brisbane, next to Springbrook. Like Springbrook Lamington National Park is covered in luscious green fields and mountains, long, windy roads, and plenty of natural beauty to experience up close and personal. Although the national park occupies a large area and boasts over 160 km of walking trails, one of the more popular areas to visit is O’Reilly’s .

Situated 930 metres above sea level, in the heart of Lamington National Park, O’Reilly’s is a great starting point for discovering the surrounding area. Accessible only via a two way, single lane, road up a windy mountain it would be wise to take your time and enjoy the scenery – ensuring you watch out for the Kangaroos around dusk, as they pop out from the foliage. One thing you will notice while ascending the mountain is the rapid change from bushland to rainforest; suddenly less light is able to penetrate to the road and there is a distinct drop in temperature. Although it can still get fairly hot, I would suggest packing an extra set of warm clothes, just in case, as it does typically tend to be cooler in the rainforest areas.

Although O’Reilly’s has been able to – with marvellous engineering – provide a canopy walk of the rainforest, it is not very long or overly fascinating. Throw in some time feeding the birds at the resort and you may have been able to occupy yourself for an hour or two, but the real rewards await on some of the trail walks. With walks ranging from between 1 km to over 20km, you’re sure to find one to suit you.

One particularly enjoyable track is the Moran’s Falls’ track, which takes you on a leisurely 4.6km (return) through a sub-tropical rainforest to the top of Moran’s Falls’. Although the Moran’s Falls’ track takes you across the waterfall, to a picnic area with spectacular views (see image above), those more daring (ensuring all safety precautions are taken) can follow the stream a bit to the edge of the waterfall. Please do be warned though – this is a very high cliff face and any slip could lead to serious or fatal injuries or death.

Note: Prior to visiting Lamington National Park, as with all National Parks, it is important to check the EPA website for any warnings or closures.

See additional photos from Lamington National Park.

It Was Only A Matter Of Time

Internet filtering plan may extend to peer-to-peer traffic, says Stephen Conroy.

The Federal Government’s controversial internet censorship scheme may extend to filter more online traffic than was first thought, Broadband Minister Stephen Conroy revealed today.

In a post on his department’s blog, Senator Conroy today said technology that could filter data sent directly between computers would be tested as part of the upcoming live filtering trial.

Update 24/12/08Internet filter ‘technically impossible’… let’s hope so 🙂

Getting SharePoint Users In InfoPath 2003

Recently I have been doing some work with SharePoint and InfoPath 2003 and one of my tasks was to get a list of SharePoint users into a drop-down list box in an InfoPath form – sound simple right? Wrong! What should be an easy task is made more complicated due to that fact that the SharePoint web services which return user information do not provide complete definitions of their return types, so InfoPath does not know what it can do with the result.

User / Group information can be retrieved from SharePoint via the UserGroup web service located at http://yourserver/_vti_bin/UserGroup.asmx – the web method I am going to be using is GetUserCollectionFromSite, but of course you can use whichever method you require.

In order to be able to get the information and use it in InfoPath 2003 we are going to need to create a new InfoPath Form Template in Visual Studio 2005. Before we can do this we need to install the Office InfoPath 2003 Toolkit For Visual Studio 2005, which can be found in your MSDN subscription – or alternatively you can download the InfoPath 2003 Toolkit For Visual Studio .NET (2003) although I have not tested this. Once you have installed the toolkit and created a new project you will be presented with a wizard which will guide you through the processes of setting up the project and you can either base the project an existing InfoPath form or create a new one, either is OK.

The first thing to do now is to set up our reference to the SharePoint web service; In InfoPath go to Tools -> Data Connections and click Add. Select Receive data, on the next page select Web Service, and on the following page enter in the URI to your UserGroup web service (E.G. http://yourserver/_vti_bin/UserGroup.asmx). On the next page you should be able to select your desired web methods, in this case we want GetUserCollectionFromSite. You can now enter a name for the data connection, I am just going leave it as the default name “GetUserCollectionFromSite“. Underneath the textbox where you can enter in the name there is a checkbox option “Automatically retrieve data when form is opened“, ensure this is ticked (if you do not tick this you can retrieve the manually retrieve the data later by calling the Query() method on the data connection).

Now that we have a connection the SharePoint we need to create a data connection which we can easily use in SharePoint, which will allow us to bind default values or in this example populate a drop-down list box. To do this we are going to create an XML file containing the same format as the return type of the SharePoint web service. In notepad, or your preferred text editor, enter the following:

<?xml version="1.0" encoding="utf-8" ?>
<SiteUsersAndGroups>
  <Users xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/">
    <User ID="" Sid="" Name="" LoginName="" Email="" Notes="" IsSiteAdmin="" IsDomainGroup=""/>
    <User ID="" Sid="" Name="" LoginName="" Email="" Notes="" IsSiteAdmin="" IsDomainGroup=""/>
  </Users>
</SiteUsersAndGroups>

Save the file as SiteUsersAndGroups.xml. Back in InfoPath create a new receiving data connection, but this time instead selecting Web service select XML document. On the next page click Resource Files… and click Add… -> select theSiteUsersAndGroups.xml file we just saved earlier and click OK twice. On the next page, once again we are going to leave the data connection name as the default “SiteUsersAndGroups“.

To populate the drop-down list box all we have to do now is double-click on the drop-down list box we want to populate and under List box entreis select the option “Look up values in a data connection to a database, Web service, file or SharePoint library or list“. In the Data Connection drop-down select SiteUsersAndGroups. Next to the Entries textbox click the Select XPath button and select the User node. You can now select the attributes we want to display in the Value and Display name fields (the Display name attribute will be the text presented to the user – typically this should be @Name to display the users name). After saving the form we now need to switch back to Visual Studio in order to transfer the data from the web service data connection to the xml data connection.

In Visual Studio open FormCode.cs – by default there should be two methods and two properties: _Startup(…)_Shutdown()thisXDocument and thisApplication. Although we will not need to use the startup or shutdown methods we will need to use the thisXDocument property.

The first thing we need to do is capture the load event of the InfoPath form. In order to handle InfoPath events methods need to have the InfoPathEventHandler attribute specified. For example our OnLoad event handler is going to look like the following:

[InfoPathEventHandler(EventType = InfoPathEventType.OnLoad)]
public void OnLoad(DocReturnEvent e)
{
  // ... code goes here ...
}

To test if the method is being executed a dialog prompt can be triggered by calling thisXDocument.UI.Alert(”Hello World”);. When the InfoPath form loads a standard dialog box should be displayed saying “Hello World“.

Now that we have an entry point for our code we need to read the data returned from the SharePoint web service, stored in the GetUserCollectionFromSite data connection, and copy it into our SiteUsersAndGroups data connection which we are binding to the drop-down list. As all of the data is returned in XML format, as is the case with all InfoPath data sources, we are going to need to use XPath to retrieve the data. The first step is to get an XPathNavigator we can use to perform out XPath query, in order to do this we first need to take the DataObject from thisXDocument and place it into an XmlDocument and from the XmlDocument create a navigator.

XmlDocument userCollectionFromSite = new XmlDocument();
userCollectionFromSite.LoadXml(_thisXDocument.DataObjects["GetUserCollectionFromSite"].DOM.xml);
XPathNavigator siteUsers = userCollectionFromSite.CreateNavigator();

If you look back at the xml file we created earlier you will notice that the Users node is under the http://schemas.microsoft.com/sharepoint/soap/directory/ namespace. Along with this namespace InfoPath data connections are placed under thehttp://schemas.microsoft.com/office/infopath/2003/dataFormSolution namespace. In order to access these namespaces in our XPath query we need to create an XmlNamespaceManager.

XmlNamespaceManager manager = new XmlNamespaceManager(siteUsers.NameTable);
manager.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
manager.AddNamespace("tns", "http://schemas.microsoft.com/sharepoint/soap/directory/");

Our actual XPath query, to get the nodes we are interested in, is going to look similar to the follow:

XPathNavigator allUsers = siteUsers.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetUserCollectionFromSiteResponse/tns:GetUserCollectionFromSiteResult/tns:GetUserCollectionFromSite/tns:Users", manager);

Now that we have the all of the users (and groups) returned from the SharePoint web service we simply need to load the xml in to the SiteUsersAndGroups data connection as follows:

thisXDocument.DataObjects["SiteUsersAndGroups"].DOM.loadXML("<SiteUsersAndGroups>" + allUsers.OuterXml + "</SiteUsersAndGroups>");

That’s it! When the form is opened the drop-down list should not be populated with the users and groups from SharePoint. The final class should look similar to the following:

#region Using Statement
using System;
using System.Xml;
using System.Xml.XPath;
using Microsoft.Office.Interop.InfoPath.SemiTrust;
#endregion

[assembly: System.ComponentModel.DescriptionAttribute("InfoPathStartupClass, Version=1.0, Class=TravelRequisitionForm.TravelRequisitionForm")]
namespace TravelRequisitionForm
{
    [InfoPathNamespace("xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xsf="http://schemas.microsoft.com/office/infopath/2003/solutionDefinition" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tr="http://schemas.microsoft.com/office/infopath/2003/sample/TravelRequest" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD" xmlns:xdUtil="http://schemas.microsoft.com/office/infopath/2003/xslt/Util" xmlns:xdXDocument="http://schemas.microsoft.com/office/infopath/2003/xslt/xDocument" xmlns:xdMath="http://schemas.microsoft.com/office/infopath/2003/xslt/Math" xmlns:xdDate="http://schemas.microsoft.com/office/infopath/2003/xslt/Date" xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:tns="http://www.tarongenergy.com.au/activedirectory" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://schemas.microsoft.com/sharepoint/soap/" xmlns:s1="http://microsoft.com/wsdl/types/" xmlns:ns2="http://www.tarongenergy.com.au/SharePoint" xmlns:ns3="http://schemas.microsoft.com/sharepoint/soap/directory/" xmlns:ns4="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"")]
    public class TravelRequisitionForm
    {
        #region Member Variables
        private XDocument thisXDocument;
        private Application thisXApplication;
        #endregion

        #region StartUp / ShutDown

        /// <summary>
        /// Handles the startup procedure.
        /// </summary>
        /// <param name="app">The application.</param>
        /// <param name="doc">The Document.</param>
        public void _Startup(Application app, XDocument doc)
        {
            thisXDocument = doc;
            thisXApplication = app;
        }

        /// <summary>
        /// Handles the shut down procedure.
        /// </summary>
        public void _Shutdown()
        {
            // Do nothing
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handles the Load event.
        /// </summary>
        /// <param name="e">Event Arguments.</param>
        [InfoPathEventHandler(EventType = InfoPathEventType.OnLoad)]
        public void OnLoad(DocReturnEvent e)
        {
            // Get all of the Users and Groups from the SharePoint web service connection.
            XmlDocument userCollectionFromSite = new XmlDocument();
            userCollectionFromSite.LoadXml(thisXDocument.DataObjects["GetUserCollectionFromSite"].DOM.xml);
            XPathNavigator siteUsers = userCollectionFromSite.CreateNavigator();

            // Add support for the required namespaces
            XmlNamespaceManager manager = new XmlNamespaceManager(siteUsers.NameTable);
            manager.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
            manager.AddNamespace("tns", "http://schemas.microsoft.com/sharepoint/soap/directory/");

            // Query the user nodes
            XPathNavigator allUsers = siteUsers.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetUserCollectionFromSiteResponse/tns:GetUserCollectionFromSiteResult/tns:GetUserCollectionFromSite/tns:Users", manager);

            // Load the users into the SiteUsersAndGroups connection
            thisXDocument.DataObjects["SiteUsersAndGroups"].DOM.loadXML("<SiteUsersAndGroups>" + allUsers.OuterXml + "</SiteUsersAndGroups>");
        }

        #endregion
    }
}

Note: Instead of writing managed code behind the InfoPath form you could write a proxy web service which contains a complete return type in the WSDL, which InfoPath can then use directly; However, note that the SharePoint web services require windows authentication so you will either need to set up a service account to access the web services, or more preferably set up Kerberos to allow authentication to be delegated to your proxy web service.