<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Extensible Development &#187; Software Engineering</title>
	<atom:link href="http://blog.itwarlocks.com/category/software-engineering/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.itwarlocks.com</link>
	<description>Profession blog about Software Engineering, Web, *nix, Processes, Tools and more.</description>
	<lastBuildDate>Mon, 29 Mar 2010 12:20:30 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>RTFM is dead, long live STFG</title>
		<link>http://blog.itwarlocks.com/2009/10/06/rtfm-is-dead-long-live-stfg/</link>
		<comments>http://blog.itwarlocks.com/2009/10/06/rtfm-is-dead-long-live-stfg/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 14:17:32 +0000</pubDate>
		<dc:creator><span property="dc:creator" resource="http://blog.itwarlocks.com/2009/10/06/rtfm-is-dead-long-live-stfg/">Jeffrey Ridout</span></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[knowledge]]></category>
		<category><![CDATA[power]]></category>
		<category><![CDATA[RTFM]]></category>
		<category><![CDATA[STFG]]></category>

		<guid isPermaLink="false">http://blog.itwarlocks.com/?p=238</guid>
		<description><![CDATA[Knowledge is power, or for developers it&#8217;s skill. Or is it?
Before the time of Google developers were required to learn, remember and never forget the knowledge they needed to perform their work. I might be a bit of a dinosaur in that way, since I&#8217;d rather simply know than rely too much on Google. The [...]]]></description>
			<content:encoded><![CDATA[<p>Knowledge is power, or for developers it&#8217;s skill. Or is it?</p>
<p>Before the time of Google developers were required to learn, remember and never forget the knowledge they needed to perform their work. I might be a bit of a dinosaur in that way, since I&#8217;d rather simply know than rely too much on Google. The media has reported cases of student relying more and more on Google (or Bing or anyother web search.) No longer is anyone required to know everything, the web answers all questions.</p>
<p>A fun example is something that actually happens around me sometimes. Since I live and work in Sweden many Operating Systems are in Swedish. Everything is in Swedish, even the error messages. That&#8217;s a great feat of the developers to successfully implement <abbr title="Internationalisation">I18n</abbr>, but sometimes other developers can&#8217;t find the solution to their problems because they don&#8217;t know the English version.</p>
<p>A well known expression in the programming world is <abbr title="Read The Fucking Manual">RTFM</abbr>, but this is becoming a relic of an older age, these days a new expression is more valid, <abbr title="Search The Friendly Google">STFG</abbr>.</p>
<p>Unfortunately the expression &#8220;Knowledge is power&#8221; is still very true. Search engines hold more and more knowledge and thus power. Since it&#8217;s all free and open, there is absolutely no problem with that, in fact it&#8217;s great. It means everyone can share the knowledge. The real problem is that the people who are supposed to have the knowledge in their brains are become reliant on web search. What happens if the web is not accessible when they need it, or &#8211; god forbid &#8211; companies like Google and Microsoft start putting a price on that knowledge?</p>
<p>Yes, web search can solve many problems and provide a wealth of knowledge. But don&#8217;t just remember the URL to the knowledge you require, remember the actual knowledge instead. Reading news feeds about new techniques in HTML, CSS, JAVA, .NET, Ruby, etc. is great. But you should remember it, quite easy if you experiment with what you&#8217;ve read. Doing it stores more in the mind than reading about it.</p>
<p>Go ahead, <abbr title="Search The Friendly Google">STFG</abbr>. Experiment, do, develop, extend and <strong>Remember</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.itwarlocks.com/2009/10/06/rtfm-is-dead-long-live-stfg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Float overflow can be useful too</title>
		<link>http://blog.itwarlocks.com/2009/05/08/float-overflow-can-be-useful-too/</link>
		<comments>http://blog.itwarlocks.com/2009/05/08/float-overflow-can-be-useful-too/#comments</comments>
		<pubDate>Fri, 08 May 2009 21:13:03 +0000</pubDate>
		<dc:creator><span property="dc:creator" resource="http://blog.itwarlocks.com/2009/05/08/float-overflow-can-be-useful-too/">Jeffrey Ridout</span></dc:creator>
				<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css sprites]]></category>
		<category><![CDATA[icons]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[style]]></category>

		<guid isPermaLink="false">http://blog.itwarlocks.com/?p=140</guid>
		<description><![CDATA[Introduction
Looking at the list of tags at the bottom of my posts, I noticed that when the amount of tags gets bigger, strange things happen to the style. When the text width gets too big to fit next to the category tags, it&#8217;s naetly moved down. But when it gets even bigger the text gets [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<div id="attachment_143" class="wp-caption alignright" style="width: 426px"><a title="Image 1, Common tag line without any style problems." rel="lightbox-140" href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/single-line-short.png"><img class="size-full wp-image-143" title="single-line-short" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/single-line-short.png" alt="Common tag line without any style problems." width="416" height="23" /></a><p class="wp-caption-text">Image 1, Common tag line without any style problems.</p></div>
<p>Looking at the list of tags at the bottom of my posts, I noticed that when the amount of tags gets bigger, strange things happen to the style. When the text width gets too big to fit next to the category tags, it&#8217;s naetly moved down. But when it gets even bigger the text gets clipped. Changing the style so the text fits easily solved that problem.</p>
<div id="attachment_142" class="wp-caption alignnone" style="width: 621px"><a title="Image 2, Wide tag line without any style problems." rel="lightbox-140" href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-short.png"><img class="size-full wp-image-142" title="multi-line-short" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-short.png" alt="Image 2, Wide tag line without any style problems." width="611" height="51" /></a><p class="wp-caption-text">Image 2, Wide tag line without any style problems.</p></div>
<pre class="brush: css">.post .content .under span {
float:    left;
/* Make the span change height to prevent the text from being clipped. */
height:    auto;
margin-right:    15px;
/* Add padding to the left for the image. */
padding-left:    22px;
}</pre>
<div id="attachment_141" class="wp-caption alignnone" style="width: 612px"><a title="Image 3, Long tag line with wrong background." rel="lightbox-140" href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-long-wrong.png"><img class="size-full wp-image-141" title="multi-line-long-wrong" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-long-wrong.png" alt="Image 3, Long tag line with wrong background." width="602" height="55" /></a><p class="wp-caption-text">Image 3, Long tag line with wrong background.</p></div>
<p>But whoops, what&#8217;s with the background image? Using CSS Sprites and fluid/elastic layout doesn&#8217;t quite seem to work together&#8230;<br />
Im my efforts to make this website&#8217;s themes more &#8220;elastic&#8221; I had to find a solution.<br />
<span id="more-140"></span></p>
<h3>Experiments</h3>
<p>I first tried to find CSS properties that could be applied directly to the containing SPAN.<br />
Setting float to &#8216;none&#8217; and display to &#8216;inline&#8217; will make the text &#8220;hanging&#8221;. This actually means that each line will receive it&#8217;s own &#8220;box&#8221; with only the first box having a padding and background.</p>
<pre class="brush: css">.post .content .under span {
display:    inline;
float:    none;
height:    auto;
margin-right:    15px;
padding-left:    22px;
}</pre>
<div id="attachment_152" class="wp-caption alignnone" style="width: 418px"><a title="Image 4, Tag line with hanging text." rel="lightbox-140" href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-inline.png"><img class="size-full wp-image-152" title="multi-line-inline" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-inline.png" alt="Image 4, Tag line with hanging text." width="408" height="167" /></a><p class="wp-caption-text">Image 4, Tag line with hanging text.</p></div>
<p>Unfortunately not floating is not optional and hanging text is not what we want either.<br />
So&#8230; how can I get a floating box with a background that ignores the content and stays 16px high?<br />
What property do floats have that can be used and that&#8217;s been a thorn in many eyes?</p>
<h3>Solution</h3>
<p>Overflow! Floats tend to reach outside the containing box making their parent unaware of their size. (The containing box is actually secretly aware of the float&#8217;s size, check this by turning on &#8216;outline&#8217;.)</p>
<div id="attachment_157" class="wp-caption alignnone" style="width: 415px"><a title="Image 5, Float overflow." rel="lightbox-140" href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/float-left-outside.png"><img class="size-full wp-image-157" title="float-left-outside" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/float-left-outside.png" alt="Image 5, Float overflow." width="405" height="211" /></a><p class="wp-caption-text">Image 5, Float overflow.</p></div>
<p>If we create a containing span and make the content a floating block, then the container can contain the background image and won&#8217;t be affected by the content&#8217;s size.<br />
The content block used to have a background and padding to show an &#8220;icon&#8221;, so we start by adding a container.</p>
<div id="attachment_156" class="wp-caption alignnone" style="width: 412px"><a href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-float-img-wrong.png"><img class="size-full wp-image-156" title="multi-line-float-img-wrong" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-float-img-wrong.png" alt="Image 6, Content block with background." width="402" height="221" /></a><p class="wp-caption-text">Image 6, Content block with background.</p></div>
<p>We can then move the background to the container and lock it&#8217;s height.</p>
<div id="attachment_154" class="wp-caption alignnone" style="width: 415px"><a href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-float-img-container.png"><img class="size-full wp-image-154" title="multi-line-float-img-container" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-float-img-container.png" alt="Image 7, Container with background." width="405" height="264" /></a><p class="wp-caption-text">Image 7, Container with background.</p></div>
<p>Great, this is what we wanted all along! But there&#8217;s one final step left.<br />
Since the container doesn&#8217;t &#8220;contain&#8221; the actual content, but the content flows out, we need one more container around the whole. This outer container can be &#8220;floating-content-aware&#8221;.</p>
<div id="attachment_155" class="wp-caption alignnone" style="width: 411px"><a href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-float-img-right.png"><img class="size-full wp-image-155" title="multi-line-float-img-right" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-float-img-right.png" alt="Image 8, Final result." width="401" height="217" /></a><p class="wp-caption-text">Image 8, Final result.</p></div>
<div class="wp-caption">Listing 1: Final HTML</div>
<pre class="brush: html">&lt;span class=&quot;outer-container&quot;&gt;
    &lt;span class=&quot;icon-container&quot;&gt;
        &lt;div class=&quot;content&quot;&gt;Lorem impsum, dolor&lt;/div&gt;
    &lt;/span&gt;
&lt;/span&gt;</pre>
<div class="wp-caption">Listing 2: Final CSS</div>
<pre class="brush: css">
.outer-container {
    float:    left;
    height:    auto;
    margin:    0;
    overflow:    auto;
    padding:    0;
}
.icon-container {
    background-image:    url(css-sprite.png);
    background-position:    0 16px;
    background-repeat:    no-repeat;
    float:    none;
    height:    16px;
    margin-right:    15px;
    overflow:    visible;
    padding-left:    22px;
}
.content {
    display:    block;
    float:    left;
    padding:    0;
    margin:    0;
}
</pre>
<div id="attachment_162" class="wp-caption alignnone" style="width: 609px"><a title="Image 9, Tag line with correct style." rel="lightbox-140" href="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-long-right.png"><img class="size-full wp-image-162" title="multi-line-long-right" src="http://blog.itwarlocks.com/wp-content/uploads/2009/05/multi-line-long-right.png" alt="Image 9, Tag line with correct style." width="599" height="54" /></a><p class="wp-caption-text">Image 9, Tag line with correct style.</p></div>
<h3>Conclusion</h3>
<p>A better solution would have been to use clipping on the background image, but that&#8217;s not present in CSS 2.1, CSS 3 or Mozilla&#8217;s specifications. Mozilla has an isue on this (<a title="Bugzilla: -moz-background-image-region" href="https://bugzilla.mozilla.org/show_bug.cgi?id=113577" target="_blank">113577</a>, please vote!), so I&#8217;m hoping this will make it to Firefox 3.5. W3C has nothing on it, so I contacted the &#8220;CSS 3, Background and Border&#8221; WorkGroup. Let&#8217;s hope for the best.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.itwarlocks.com/2009/05/08/float-overflow-can-be-useful-too/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Accessing WebDAV in Microsoft Word Visual Basic</title>
		<link>http://blog.itwarlocks.com/2009/04/28/accessing-webdav-in-microsoft-word-visual-basic/</link>
		<comments>http://blog.itwarlocks.com/2009/04/28/accessing-webdav-in-microsoft-word-visual-basic/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 14:10:11 +0000</pubDate>
		<dc:creator><span property="dc:creator" resource="http://blog.itwarlocks.com/2009/04/28/accessing-webdav-in-microsoft-word-visual-basic/">Jeffrey Ridout</span></dc:creator>
				<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[office]]></category>
		<category><![CDATA[vba]]></category>
		<category><![CDATA[visualbasic]]></category>
		<category><![CDATA[WebDAV]]></category>
		<category><![CDATA[word]]></category>

		<guid isPermaLink="false">http://blog.itwarlocks.com/?p=45</guid>
		<description><![CDATA[Introduction
In &#8220;&#8221; I explained why I needed to connect Microsoft Word to a WebDAV repository and in &#8220;&#8221; I explained how to set up authorisation for mod_dav using a PHP script. What&#8217;s left is accessing the WebDAV repository using Word&#8217;s Visual Basic.
Requirements

Open documents from the remote location.
Save documents to the remote location.

Save new documents to [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>In &#8220;<a href="http://blog.itwarlocks.com/2009/04/24/document-management-system-in-word-using-webdav/" target="_self">Document Management System in Word using WebDAV</a>&#8221; I explained why I needed to connect Microsoft Word to a WebDAV repository and in &#8220;<a href="http://blog.itwarlocks.com/2009/04/27/php-based-authentication-for-mod_dav/" target="_self">PHP based authentication for mod_dav</a>&#8221; I explained how to set up authorisation for mod_dav using a PHP script. What&#8217;s left is accessing the WebDAV repository using Word&#8217;s Visual Basic.<span id="more-45"></span></p>
<h3>Requirements</h3>
<ul>
<li>Open documents from the remote location.</li>
<li>Save documents to the remote location.
<ul>
<li>Save new documents to the remote location.</li>
<li>Overwrite existing documents on the remote location.</li>
</ul>
</li>
<li>List documents available for specified MemberID&#8217;s.</li>
<li>Add meta-data to stored documents. (Optional)</li>
</ul>
<h3>Solution</h3>
<p>Starting from Office 2000, support for WebDAV is included natively. Although Windows XP and never also have their own support for WebDAV, it&#8217;s always better to use Office&#8217;s own methods. The only downside to this is that these methods are not available in Word&#8217;s Visual Basic.<sup>1</sup></p>
<h4>Word Visual Basic WebDAV interface</h4>
<p>Accessing WebDAV resources in Word&#8217;s Visual Basic can be done by using an ADODB object. Starting from ADODB 2.5 support for WebDAV is available. ADODB might need to be enabled for Word first.</p>
<h4>Activate ADODB in Word</h4>
<div>
<div id="attachment_114" class="wp-caption alignright" style="width: 310px"><a title="Visual Basic Editor (Word 2003)" rel="lightbox-45" href="http://blog.itwarlocks.com/wp-content/uploads/2009/04/visual_basic_editor-2003.png"><img class="size-medium wp-image-114" title="Visual Basic Editor (Word 2003)" src="http://blog.itwarlocks.com/wp-content/uploads/2009/04/visual_basic_editor-2003-300x152.png" alt="Visual Basic Editor (Word 2003)" width="300" height="152" /></a><p class="wp-caption-text">Visual Basic Editor (Word 2003)</p></div>
<p>To activate (or check if it is available) ADODB in Word, you need to start the Visual Basic Editor. The VBE can be found in <code>Tools\Macro</code> (Word XP &amp; 2003<sup>2</sup>)</p>
<p>Access to ADODB is determined by the project&#8217;s references and those are specific for each Word document, so make sure to start your WebDAV macro projekt first (Done by creating a new Macro from Word).</p></div>
<div class="floatcontainer">
<div id="attachment_115" class="wp-caption alignleft" style="width: 310px"><a title="VBE Rreferences (Word 2003)" rel="lightbox-45" href="http://blog.itwarlocks.com/wp-content/uploads/2009/04/vbe_references-2003.png"><img class="size-medium wp-image-115" title="VBE Rreferences (Word 2003)" src="http://blog.itwarlocks.com/wp-content/uploads/2009/04/vbe_references-2003-300x241.png" alt="VBE Rreferences (Word 2003)" width="300" height="241" /></a><p class="wp-caption-text">VBE Rreferences (Word 2003)</p></div>
<p>Open the References from Tools\References and make sure a &#8220;Microsoft ActiveX Data Objects 2.x Library&#8221; is selected. Versions 2.5 and newer support WebDAV, but make sure the production environment you will be delivering to has the same version.</p>
<p>As soon as the ADODB library is activated the Visual Basic Editor will recognise the ADODB references in the code.</p></div>
<h4>Opening a document from WebDAV</h4>
<p>To open a document from WebDAV the ADODB object is not needed, Word uses it&#8217;s internal WebDAV library instead.</p>
<pre class="brush: vb">Documents.Open &quot;http://example.org/dav/document.doc&quot;, False, False</pre>
<p>Sometime the opened document becomes read-only, this is can have several causes:</p>
<ul>
<li>WebDAV supports locks and the file has been locked. Just like normal local access Word puts a lock on the file if opened for writing. Unlike local access the lock on WebDAV can easily be removed by an administrator (or another Word Macro! See &#8220;<a href="http://blog.itwarlocks.com/2009/04/27/php-based-authentication-for-mod_dav/" target="_self">PHP based authentication for mod_dav</a>&#8221; to know how even this can be moderated with a PHP script.)</li>
<li>Word erronously identified the WebDAV as an Exhange or SharePoint resource. Both <a title="MSDN: Exchange Store webDAV Protocol" href="http://msdn.microsoft.com/en-us/library/aa143161(EXCHG.65).aspx" target="_blank">Microsoft Exchange</a> and Microsoft SharePoint use WebDAV to share documents with Office. The problem is caused by the extra meta-data that is expected.</li>
</ul>
<h4>Save a new document to WebDAV</h4>
<p>Documents opened from a WebDAV resource are automatically saved back to their original WebDAV location, unless they are opened as read-only. To save a newly created document to a WebDAV repository, just pass the URL to the normal SaveAs function.</p>
<pre class="brush: vb">ActiveDocument.SaveAs (&quot;http://example.org/dav/test.doc&quot;)</pre>
<h4>Getting a directory listing from WebDAV</h4>
<p>Other actions that interact with the WebDAV repository require the ADODB object. Using ADODB creates an interface for WebDAV that acts like a database, with recordsets and records.</p>
<div>
<div class="wp-caption" style="text-align: left">Listing 1:</div>
<pre class="brush: vb">
&#039;
&#039; Microsoft Office Visual Basic
&#039; WebDAV Access example
&#039;
&#039; @author Jeffrey Ridout
&#039; @date 2009-04-23
&#039; @version 0.0.1
&#039;

Sub AccessWebDAV()
    Dim files() As String                  &#039; String array to hold friendly filenames.
    Dim davDir As New ADODB.Record         &#039; Record for the directory
    Dim davFile As New ADODB.Record        &#039; Record for the file
    Dim davFiles As New ADODB.Recordset    &#039; Recordset for the directory&#039;s filelist
    Dim isDir As Boolean
    Dim index As Integer

    &#039; For debugging purposes jump to the error display on any error
    On Error GoTo showErr

    &#039; Open the root folder as a ADODB.Record to retrieve a list of it&#039;s contents.
    &#039; To open a folder, pass an empty string as the filename and the full URL as the path.
    &#039; URL= tells ADODB to use the WebDAV interface.
    &#039; adModeReadWrite: This could be adModeReadOnly, it might matter in a multi-threaded environment
    &#039; adDelayFetchStream: ADODB sometimes pre-fetches the content of files, this is not needed.
    davDir.Open &quot;&quot;, _
                &quot;URL=http://example.org/dav&quot;, _
                adModeReadWrite, _
                adFailIfNotExists, _
                adDelayFetchStream, _
                &quot;username&quot;, _
                &quot;password&quot;
    Set davFiles = davDir.GetChildren()          &#039; Get the list of files as a ADODB.Recordset

    index = 0
    &#039; The WebDAV directory Recordset uses a &#039;current&#039; index and has no counter,
    &#039; so use EOF to check if there are more files.
    Do While Not davFiles.EOF
        davFile.Open davFiles, , adModeReadWrite
        &#039; File properties are Record.Fields, all standard DAV fields are called &quot;Dav:&lt;property&gt;&quot;.
        &#039; ADODB adds it&#039;s own fields that supply the same information, called &quot;RESOURCE_&lt;property&gt;&quot;.
        isDir = davFile.Fields(&quot;RESOURCE_ISCOLLECTION&quot;).Value                     &#039; RESOURCE_ISCOLLECTION is a boolean specifiying if the file is a directory.

        If Not isDir Then &#039; If the file is not a directory it&#039;s a normal file and we can add it to the list.
            ReDim Preserve files(0 To 1, 0 To index)                              &#039; The number of files is unknown, so &quot;ReDim Preserve&quot; resizes the array without losing the data.
            files(0, index) = davFile.Fields(&quot;RESOURCE_PARSENAME&quot;).Value          &#039; RESOURCE_PARSENAME contains the filename.
            files(1, index) = davFile.Fields(&quot;RESOURCE_ABSOLUTEPARSENAME&quot;).Value  &#039; RESOURCE_ABSOLUTEPARSENAME contains the full URL.
            index = index + 1
        End If

        davFile.Close       &#039; Always remember to Close the file!
        davFiles.MoveNext   &#039; Move the index to the next Record.
    Loop
    Set davFiles = Nothing  &#039; Always unset the object pointer!
    davDir.Close            &#039; Close the Record for the directory, not closing it can leak memory and could also lock the directory.
    Set davDir = Nothing

    &#039; Do something with files here...

    GoTo noErr
showErr:
    Call MsgBox(Err.Number &amp; &quot;: &quot; &amp; Err.Description, vbOKOnly, &quot;Error&quot;)

noErr:
    &#039; No errors
End Sub
</pre>
</div>
<h4>Getting and setting meta-data</h4>
<p>Exchange and SharePoint use custom properties to perform extra actions and change file attributes. Custom properties in WebDAV normally have their own namespace, but I haven&#8217;t figured out how to specify those with ADODB yet.<sup>3</sup> Some examples contain the namespace as part of the property, so I&#8217;ve adopted this.</p>
<p>Adding properties for the document&#8217;s title, subject, author, etc. makes it possible to display those properties without having to open the document. Whenever the document is saved to WebDAV a Macro function should be triggered to update these properties.</p>
<div>
<div class="wp-caption" style="text-align: left">Listing 2:</div>
<pre class="brush: vb">
&#039;...
&#039; Define some constants containing property namespaces in the head of the Macro.

&#039; Constants
Public Const OFFICE_URN  As String = &quot;urn:schemas-microsoft-com:office:office&quot;
Public Const EXAMPLE_URN As String = &quot;http://example.org/dav/props/&quot;

&#039; Inside the function, the custom properties can be retrieved and added quite easy.
&#039;...
    &#039; Get custom properties.
    prop1 = davFile.Fields(OFFICE_URN &amp; &quot;author&quot;).Value
    prop2 = davFile.Fields(EXAMPLE_URN &amp; &quot;doc_title&quot;).Value
    prop3 = davFile.Fields(EXAMPLE_URN &amp; &quot;doc_subject&quot;).Value
    prop4 = davFile.Fields(&quot;non-existing-property&quot;).Value      &#039; Non existing properties return an empty string.

    &#039; Set custom properties.
    davFile.Fields(OFFICE_URN &amp; &quot;author&quot;) = &quot;user&quot;
    davFile.Fields(EXAMPLE_URN &amp; &quot;doc_title&quot;) = &quot;Document title&quot;
    davFile.Fields(EXAMPLE_URN &amp; &quot;doc_subject&quot;) = &quot;Document subject&quot;
    davFile.Fields.Update  &#039; Fields.Update commits the changes to Fields to WebDAV.
&#039;...
</pre>
</div>
<h4>Putting it all together</h4>
<p>Here is the code where all previous techniques are put together. Normally opening, saving and listing would be done in different functions preferably triggered by events, put this will serve as an example.</p>
<div>
<div class="wp-caption" style="text-align: left">Listing 3:</div>
<pre class="brush: vb">
&#039;
&#039; Microsoft Office Visual Basic
&#039; WebDAV Access example
&#039;
&#039; @author Jeffrey Ridout
&#039; @date 2009-04-23
&#039; @version 0.0.2
&#039;

&#039; Constants
Public Const OFFICE_URN As String = &quot;urn:schemas-microsoft-com:office:office/&quot;
Public Const SPK_URN As String = &quot;http://schemas.spk.no/dav/props/&quot;

&#039; Module variables
Public isCancelled As Boolean  &#039; Used by dlgOpenFileDAV
Public fileURL As String       &#039; Used by dlgOpenFileDAV

Sub OpenWebDAVFile()
    Dim files() As String                  &#039; Dynamic Multidimensional String array to hold file properties.
    Dim davDir As New ADODB.Record         &#039; Record for the directory
    Dim davFile As New ADODB.Record        &#039; Record for the file
    Dim davFiles As New ADODB.Recordset    &#039; Recordset for the directory&#039;s filelist
    Dim isDir As Boolean
    Dim index As Integer
    Dim dlg As Object

    &#039; For debugging purposes jump to the error display on any error
    On Error GoTo showErr

    &#039; Open the root folder as a ADODB.Record to retrieve a list of it&#039;s contents.
    &#039; To open a folder, pass an empty string as the filename and the full URL as the path.
    &#039; URL= tells ADODB to use the WebDAV interface.
    &#039; adModeReadWrite: This could be adModeReadOnly, it might matter in a multi-threaded environment
    &#039; adDelayFetchStream: ADODB sometimes pre-fetches the content of files, this is not needed.
    davDir.Open &quot;&quot;, _
                &quot;URL=http://example.org/dav&quot;, _
                adModeReadWrite, _
                adFailIfNotExists, _
                adDelayFetchStream, _
                &quot;username&quot;, _
                &quot;password&quot;
    Set davFiles = davDir.GetChildren()          &#039; Get the list of files as a ADODB.Recordset

    index = 0
    &#039; The WebDAV directory Recordset uses a &#039;current&#039; index and has no counter,
    &#039; so use EOF to check if there are more files.
    Do While Not davFiles.EOF
        davFile.Open davFiles, , adModeReadWrite
        &#039; File properties are Record.Fields, all standard DAV fields are called &quot;Dav:&lt;property&gt;&quot;.
        &#039; ADODB adds it&#039;s own fields that supply the same information, called &quot;RESOURCE_&lt;property&gt;&quot;.
        isDir = davFile.Fields(&quot;RESOURCE_ISCOLLECTION&quot;).Value                     &#039; RESOURCE_ISCOLLECTION is a boolean specifiying if the file is a directory.

        If Not isDir Then &#039; If the file is not a directory it&#039;s a normal file and we can add it to the list.
            ReDim Preserve files(0 To 4, 0 To index)                              &#039; The number of files is unknown, so &quot;ReDim Preserve&quot; resizes the array without losing the data.
            files(0, index) = davFile.Fields(&quot;RESOURCE_PARSENAME&quot;).Value          &#039; RESOURCE_PARSENAME contains the filename.
            files(1, index) = davFile.Fields(&quot;RESOURCE_ABSOLUTEPARSENAME&quot;).Value  &#039; RESOURCE_ABSOLUTEPARSENAME contains the full URL.
            files(2, index) = davFile.Fields(SPK_URN &amp; &quot;doc-title&quot;).Value         &#039; Custom property: title
            files(3, index) = davFile.Fields(SPK_URN &amp; &quot;doc-subject&quot;).Value       &#039; Custom property: subject
            files(4, index) = davFile.Fields(OFFICE_URN &amp; &quot;author&quot;).Value         &#039; Custom property: author
            index = index + 1
        End If
        davFile.Close       &#039; Always remember to Close the file!
        davFiles.MoveNext   &#039; Move the index to the next Record.
    Loop
    Set davFiles = Nothing  &#039; Always unset the object pointer!
    davDir.Close            &#039; Close the Record for the directory, not closing it can leak memory and could also lock the directory.
    Set davDir = Nothing

    &#039; See Image 3 and Listing 4 for the OpenFileDAV dialog.
    dlgOpenFileDAV.listDocuments.Clear     &#039; Clear the ListBox since dlgOpenFileDAV is reusable.
    For I = 0 To index - 1
        With dlgOpenFileDAV.listDocuments
            .AddItem files(0, I), I        &#039; Add a new row to the ListBox.
            .List(I, 1) = files(1, I)      &#039; The ListBox has 4 columns, 2nd column is hidden and contains the full URL.
            .List(I, 2) = files(2, I)      &#039; 3d column contains the title.
            .List(I, 3) = files(3, I)      &#039; 4th column contains the subject.
            .List(I, 4) = files(4, I)      &#039; 5th column contains the author.
        End With
    Next I

    isCancelled = True
    fileURL = &quot;&quot;
    dlgOpenFileDAV.Show
    If (isCancelled = False) Then
        If (fileURL &lt;&gt; &quot;&quot;) Then
            Documents.Open fileURL, False, False  &#039; To open the file from the WebDAV repository, simple pass the URL.
        End If
    End If

    GoTo noErr
showErr:
    Call MsgBox(Err.Number &amp; &quot;: &quot; &amp; Err.Description, vbOKOnly, &quot;Error&quot;)

noErr:
    &#039; No errors
End Sub
</pre>
</div>
<p>Image 3 shows the UserForm used as the custom &#8220;Open File&#8221; dialog. Image 4 shows the ListBox properties. The ListBox currently only should support selecting 1 file, has 5 columns. Note that the 2nd column has a width of &#8220;0 pt&#8221; in order to hide it. BoundColunm is set to 2, which results in the Value of the ListBox being the value of the hidden column of the selected row (The file&#8217;s full URL).</p>
<div class="floatcontainer">
<div id="attachment_121" class="wp-caption alignleft" style="width: 310px"><a title="Open WebDAV File dialog" rel="lightbox-45" href="http://blog.itwarlocks.com/wp-content/uploads/2009/04/dlg_openfile.png"><img class="size-medium wp-image-121" title="Open WebDAV File dialog" src="http://blog.itwarlocks.com/wp-content/uploads/2009/04/dlg_openfile-300x156.png" alt="Image 2: Open WebDAV File dialog" width="300" height="156" /></a><p class="wp-caption-text">Image 2: Open WebDAV File dialog</p></div>
<div id="attachment_122" class="wp-caption alignleft" style="width: 160px"><a title="ListBox properties" rel="lightbox-45" href="http://blog.itwarlocks.com/wp-content/uploads/2009/04/listbox_properties.png"><img class="size-thumbnail wp-image-122" title="ListBox properties" src="http://blog.itwarlocks.com/wp-content/uploads/2009/04/listbox_properties-150x150.png" alt="Image 5: ListBox properties" width="150" height="150" /></a><p class="wp-caption-text">Image 5: ListBox properties</p></div>
</div>
<div>
<div class="wp-caption" style="text-align: left">Listing 4:</div>
<pre class="brush: vb">
Private Sub btnCancel_Click()
    davTest.isCancelled = True
    Hide
End Sub

Private Sub btnOk_Click()
    davTest.isCancelled = False
    davTest.fileURL = listDocuments.Value
    Hide
End Sub

Private Sub listDocuments_Change()
    If listDocuments.Value &gt;= 0 Then
        btnOk.Enabled = True
    End If
End Sub

Private Sub UserForm_Initialize()
    If (listDocuments.ListCount &gt; 0) Then
        listDocuments.Clear
    End If
    btnOk.Enabled = False
    davTest.isCancelled = True
End Sub
</pre>
</div>
<h3>Conclusion</h3>
<p>Creating your own WebDAV based repository access in Microsoft Word is possible and after some research and experimenting quite easy. Combine this with a PHP CMS and mod_dav with PHP authentication and authorisation and you&#8217;ve got a fully functional Document Management System.</p>
<h3>Example</h3>
<ul>
<li>Download: <a href="/lab/webdav/VBA-WebDAV.doc" title="VBA WebDAV example" class="aptureNoEnhance">VBA-WebDAV.doc</a></li>
</ul>
<p><a href="/license/#cc-by-sa"><img class="size-full wp-image-95 alignleft" style="margin-right: 1.5em" title="Creative Commons: Attribution Share Alike" src="http://blog.itwarlocks.com/wp-content/uploads/2009/04/cc-by-sa_88x31.png" alt="Creative Commons: Attribution Share Alike" width="88" height="31" /></a>All code in this post is licensed under Creative Commons Attribution Share Alike.</p>
<ol class="footnotes"><li id="footnote_0_45" class="footnote">Office&#8217;s own WebDAV support might be available in VBA, but I have not found any documentation on it.</li><li id="footnote_1_45" class="footnote">Office 2007 might have hidden it better but <code>ALT+F11</code> still works.</li><li id="footnote_2_45" class="footnote">If you find out, let me know!</li></ol>]]></content:encoded>
			<wfw:commentRss>http://blog.itwarlocks.com/2009/04/28/accessing-webdav-in-microsoft-word-visual-basic/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>PHP based authentication for mod_dav</title>
		<link>http://blog.itwarlocks.com/2009/04/27/php-based-authentication-for-mod_dav/</link>
		<comments>http://blog.itwarlocks.com/2009/04/27/php-based-authentication-for-mod_dav/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 12:24:41 +0000</pubDate>
		<dc:creator><span property="dc:creator" resource="http://blog.itwarlocks.com/2009/04/27/php-based-authentication-for-mod_dav/">Jeffrey Ridout</span></dc:creator>
				<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[mod_auth]]></category>
		<category><![CDATA[mod_auth_script]]></category>
		<category><![CDATA[mod_dav]]></category>
		<category><![CDATA[mod_dav_fs]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[WebDAV]]></category>

		<guid isPermaLink="false">http://blog.itwarlocks.com/?p=43</guid>
		<description><![CDATA[To be able to create a Document Management System in Word using WebDAV on Apache webserver, I did some research on mod_dav, an Apache module to provide WebDAV support. It appears that the authaurisation part of mod_dav is limited to "allow all" / "deny all", which did not quite suite my needs. The solution needed more fine-grained authorisation on a per-directory level. Another problem was that the authentication and authorisation data was in a database.]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>To be able to create a <a href="http://blog.itwarlocks.com/2009/04/24/document-management-system-in-word-using-webdav/" target="_self">Document Management System in Word using WebDAV</a> on <a title="Apache webserver official website." href="http://httpd.apache.org/" target="_blank">Apache webserver</a>, I did some research on <a title="Mod_dav's official website." href="http://www.webdav.org/mod_dav/" target="_blank">mod_dav</a>, an Apache <a title="Official Apache webserver module registry." href="http://modules.apache.org/" target="_blank">module</a> to provide <a id="aptureLink_vPPLLegkod" title="Information on WebDAV on Wikipedia.org" href="http://en.wikipedia.org/wiki/WebDAV">WebDAV</a> support. It appears that the authaurisation part of mod_dav is limited to &#8220;allow all&#8221; / &#8220;deny all&#8221;, which did not quite suite my needs. The solution needed more fine-grained authorisation on a per-directory level. Another problem was that the authentication and authorisation data was in a database.<span id="more-43"></span></p>
<h3>Issues</h3>
<ol>
<li>Mod_dav does not have a fine-grained authorisation system on a per-directory level.</li>
<li>Directory structure is known but unstable.</li>
<li>Authorisation data is held in a database and requires complex SQL.</li>
</ol>
<h3>Solution</h3>
<h4>Fine-grained authorisation</h4>
<p>I started by looking at <a title="Mod_auth's official website." href="http://httpd.apache.org/docs/2.0/mod/mod_auth.html" target="_blank">mod_auth</a> and <a title="Mod_auth_dbd's official website." href="http://httpd.apache.org/docs/2.2/mod/mod_authn_dbd.html" target="_blank">mod_auth_dbd</a> (in combination with <a title="Mod_dbd's official website." href="http://httpd.apache.org/docs/2.2/mod/mod_dbd.html" target="_blank">mod_dbd</a>), but the SQL useable by mod_dbd only received the username and password as parameters, not the requested <a id="aptureLink_c3qbx5wU5Q" title="Information on URI on Wikipedia.org" href="http://en.wikipedia.org/wiki/Uniform%20Resource%20Identifier">URI</a>. What mod_auth module could possibly be used? The solution to this was quite unexpected: <a title="Mod_auth_script's official website." href="http://mod-auth-script.sourceforge.net/" target="_blank">mod_auth_script</a>.</p>
<p>Mod_auth_script allows CGI or <a title="PHP's official website." href="http://www.php.net" target="_blank">PHP</a> scripts to handle the authorisation. By looking at the <a title="PHP.net official documentation on $_SERVER predefined variables." href="http://www.php.net/manual/en/reserved.variables.server.php" target="_blank">REQUEST_URI</a> the script can easily decide to simulate authorisation by invalidating the authorisation.</p>
<p>I created a PHP script that at first would log the REQUEST_URI and allow access for any username and password. All that is left now is to handle authorisation based on the directory structure and fetch the real authorisation from the database.</p>
<div>
<div class="wp-caption" style="text-align: left">Listing 1: Apache config</div>
<pre class="brush: xml">
&lt;Location /dav&gt;
	Options			+Indexes
	Dav				On
	AuthType		Basic
	AuthName		&quot;PHP based authentication for mod_dav&quot;
	AuthScriptFile	/any_full_path_your_apache_can_get_to/.auth.php
	Require			valid-user
&lt;/Location&gt;
</pre>
</div>
<div>
<div class="wp-caption" style="text-align: left">Listing 2: .auth.php (version 0.0.1)</div>
<pre class="brush: php">
&lt;?php
/**
 * PHP based authentication for mod_dav
 * @author Jeffrey Ridout
 * @link http://blog.itwarlocks.com
 * @license http://creativecommons.org/licenses/by-sa/3.0
 * @date 2009-04-27
 * @version 0.0.1
 */

/**
 * $_SERVER[&#039;REQUEST_URI&#039;] contains the location accessed by the WebDAV client.
 * Using parse_url enables easy access to all URL parts.
 */
$requestURI = parse_url($_SERVER[&#039;REQUEST_URI&#039;]);

/**
 * Accessing some pages directly, like a page containing phpinfo(), will result in several
 * calls to .auth.php. These do not need to be logged.
 */
if ($requestURI[&#039;path&#039;] != $_SERVER[&#039;SCRIPT_NAME&#039;]) {
	$logFile = fopen(&#039;auth.log&#039;, &#039;a&#039;);
	fwrite($logFile, &quot;${_SERVER[&#039;PHP_AUTH_USER&#039;]}:${_SERVER[&#039;PHP_AUTH_PW&#039;]}@${requestURI[&#039;path&#039;]}\n&quot;);
	fclose($logFile);
}

/**
 * At this stage we always allow access.
 * mod_auth_script catches custom headers to define the result to mod_auth.
 * auth-script:allow|deny|prompt Defines the authentication result.
 */
header(&#039;auth-script:allow&#039;);

/* EOF */
?&gt;
</pre>
</div>
<h4>Directory structure</h4>
<p>The sub-directories are named according to a strict rule, but they are unknown to exist at design-time. Therefore the script needs to analyse the destination location and extract the key to be used for authorisation.<sup>1</sup></p>
<div>
<div class="wp-caption" style="text-align: left">Listing 3: Directory structure</div>
<pre class="brush: text">
/&lt;Day&gt;/&lt;Month&gt;/&lt;Year&gt;/&lt;MemberID&gt;
	&lt;Day&gt;:		00 - 31
	&lt;Month&gt;:		00 - 12
	&lt;Year&gt;:		00 - 99
	&lt;MemberID&gt;:	DDMMYY#####
</pre>
</div>
<div id="attachment_77" class="wp-caption alignnone" style="width: 118px"><a title="Directory structure" rel="lightbox-43" href="http://blog.itwarlocks.com/wp-content/uploads/2009/04/directory_structure.png"><img class="size-medium wp-image-77" title="Directory structure" src="http://blog.itwarlocks.com/wp-content/uploads/2009/04/directory_structure-108x300.png" alt="Directory structure" width="108" height="300" /></a><p class="wp-caption-text">Directory structure</p></div>
<p>This directory structure allows for a quite straight forward check to get the MemberID.<sup>2</sup></p>
<div>
<div class="wp-caption" style="text-align: left">Listing 3: .auth.php (version 0.0.2)</div>
<pre class="brush: php">
&lt;?php
/**
 * PHP based authentication for mod_dav
 * @author Jeffrey Ridout
 * @link http://blog.itwarlocks.com
 * @license http://creativecommons.org/licenses/by-sa/3.0
 * @date 2009-04-27
 * @version 0.0.2
 */

/**
 * $_SERVER[&#039;REQUEST_URI&#039;] contains the location accessed by the WebDAV client.
 * Using parse_url enables easy access to all URL parts.
 */
$requestURI = parse_url($_SERVER[&#039;REQUEST_URI&#039;]);

/**
 * Accessing some pages directly, like a page containing phpinfo(), will result in several
 * calls to .auth.php. These do not need to be logged.
 */
if ($requestURI[&#039;path&#039;] != $_SERVER[&#039;SCRIPT_NAME&#039;]) {
	$logFile = fopen(&#039;auth.log&#039;, &#039;a&#039;);
	fwrite($logFile, &quot;${_SERVER[&#039;PHP_AUTH_USER&#039;]}:${_SERVER[&#039;PHP_AUTH_PW&#039;]}@${requestURI[&#039;path&#039;]}\n&quot;);
	fclose($logFile);
}

/**
 * At stage 2 we can simulate a real authorisation lookup by using a simple array.
 * mod_auth_script catches custom headers to define the result to mod_auth.
 * auth-script:allow|deny|prompt Defines the authentication result.
 */
$blocked = array (
	&#039;01010154321&#039;,
	&#039;31037912345&#039;
);

/**
 * The directory name to search for might be in the path or destination filename.
 * .../blocked-dir
 * or
 * .../blocked-dir/
 * or
 * .../blocked-dir/...
 */
$path = dirname($requestURI[&#039;path&#039;]);
$dir = basename($path);
$match = basename($rURL[&#039;path&#039;]);
if (preg_match(&#039;#$\d{11}^#&#039;, $dir)) {
	$match = $dir;
}
if (!in_array($match, $blocked)) {
	header(&#039;auth-script:allow&#039;);
} else {
	/* Simulate authorisation by denying access.
	 * Normal authentication would return auth-script:prompt
	 */
	header(&#039;auth-script:deny&#039;);
}

/* EOF */
?&gt;
</pre>
</div>
<h4>Authorisation data</h4>
<p>The data that determines the authorisation can come from different sources; files, LDAP, RADIUS, database, &#8230;</p>
<p>In my case the authorisation result was retrieved from complex SQL using a stored procedure in a Sybase Database.</p>
<p>Whatever you use as your source of authentication/authorisation, remember that request can be asynchrounous and parallel. For a file base method that means never locking the file and opening it as &#8220;read-only&#8221;, for an external connection based method, it means using persistent connections.</p>
<h3>Conclusion</h3>
<p>Just because mod-dav and mod_auth don&#8217;t support your exact needs, doesn&#8217;t mean there is no solution. Using mod_auth_script to create your own tailored flexible solution works perfectly. As an added bonus this adds a new processing layer to PHP by allowing PHP to be executed at a much earlier stage. Using a PHP script to authorise also allows authorisation of non-existing destination URLs or destinations which access is based on complex business logic.</p>
<p><a href="/license/#cc-by-sa"><img class="size-full wp-image-95 alignleft" style="margin-right: 1.5em" title="Creative Commons: Attribution Share Alike" src="http://blog.itwarlocks.com/wp-content/uploads/2009/04/cc-by-sa_88x31.png" alt="Creative Commons: Attribution Share Alike" width="88" height="31" /></a>All code in this post is licensed under Creative Commons Attribution Share Alike.</p>
<ol class="footnotes"><li id="footnote_0_43" class="footnote">You may notice that year only has 2 digits. so no, it&#8217;s not Y2K safe&#8230;</li><li id="footnote_1_43" class="footnote">MemberID in this case is the Norwegian version of a social security number.</li></ol>]]></content:encoded>
			<wfw:commentRss>http://blog.itwarlocks.com/2009/04/27/php-based-authentication-for-mod_dav/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Document Management System in Word using WebDAV</title>
		<link>http://blog.itwarlocks.com/2009/04/24/document-management-system-in-word-using-webdav/</link>
		<comments>http://blog.itwarlocks.com/2009/04/24/document-management-system-in-word-using-webdav/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 08:46:03 +0000</pubDate>
		<dc:creator><span property="dc:creator" resource="http://blog.itwarlocks.com/2009/04/24/document-management-system-in-word-using-webdav/">Jeffrey Ridout</span></dc:creator>
				<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[authorisation]]></category>
		<category><![CDATA[mod_auth]]></category>
		<category><![CDATA[mod_auth_script]]></category>
		<category><![CDATA[mod_dav]]></category>
		<category><![CDATA[office]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[vba]]></category>
		<category><![CDATA[visualbasic]]></category>
		<category><![CDATA[WebDAV]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[word]]></category>

		<guid isPermaLink="false">http://blog.itwarlocks.com/?p=64</guid>
		<description><![CDATA[Introduction
A customer I&#8217;m currently doing maintenance on their major application for, had an issue come up a couple of weeks ago where not all employees were to access all data any longer. The company deals with other companies and their employees, called members. The issue that came up caused a company wide policy to come [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>A customer I&#8217;m currently doing maintenance on their major application for, had an issue come up a couple of weeks ago where not all employees were to access all data any longer. The company deals with other companies and their employees, called members. The issue that came up caused a company wide policy to come in effect that meant that only specific users were to allow members or family of members to be accessed for a certain client company.</p>
<p>The application in question was easily modified since it already had support for authentication, so only authorisation for that specific company had to be added. (No we weren&#8217;t allowed to create a generic solution that would allow a reusable authorisation for multiple client companies. But discussing their policies is a whole different matter.)<span id="more-64"></span></p>
<h3>Case definition</h3>
<p>The users use the main application to create letters to be sent to client companies and members using Word. the application sends information about the specific company or member to Word using DDE and macros in the used templates fill in most of that information into the prewritten text. Another macro allows the user to save the document in a predefined location on a Windows Active Directory share. Yet another macro allows the user to get a list of all the documents stored for a specific company or member.</p>
<p>The problem was that everyone had full access to the shared location. So even though the information was protected through authentication and authorisation in the main application, the resulting letters containing vital information were still completely open.</p>
<h3>Solution</h3>
<p>There are actually several solutions, but I&#8217;m only going to blog about my favourite solution, since it involved quite some interesting techniques. This solution uses WebDAV instead of an Active Directory share.</p>
<h4>Requirements</h4>
<ol>
<li>Access to the documents needs to be authenticated</li>
<li>Access to the documents needs to be authorised</li>
<li>Authentication and authorisation data needs to be retrieved from a database (Sybase in this case)</li>
<li>The location needs to be accessible from Word</li>
<li>The location needs to be accessible from MainApp (pseudo name for the customer&#8217;s main application)</li>
</ol>
<h4>Implementation</h4>
<p>The MainApp already happened to be multi-tiered using an Apache webserver to provide services to the client. Since Exchange and SharePoint use the WebDAV protocol and mod_dav is available for Apache, I decided to try WebDAV. Since Office 2000, support for WebDAV (or &#8220;Web Folders&#8221;) has been present in Word, so there should be a way to access it through Word&#8217;s Visual Basic.</p>
<p>Implemenation articles:</p>
<ul>
<li><a href="http://blog.itwarlocks.com/2009/04/27/php-based-authentication-for-mod_dav/" target="_self">PHP based authentication for mod_dav</a></li>
<li><a href="http://blog.itwarlocks.com/2009/04/28/accessing-webdav-in-microsoft-word-visual-basic/" target="_self">Accessing WebDAV in Microsoft Word Visual Basic</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.itwarlocks.com/2009/04/24/document-management-system-in-word-using-webdav/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thinking ahead without planning the future</title>
		<link>http://blog.itwarlocks.com/2009/04/02/thinking-ahead-without-planning-the-future/</link>
		<comments>http://blog.itwarlocks.com/2009/04/02/thinking-ahead-without-planning-the-future/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 10:21:38 +0000</pubDate>
		<dc:creator><span property="dc:creator" resource="http://blog.itwarlocks.com/2009/04/02/thinking-ahead-without-planning-the-future/">Jeffrey Ridout</span></dc:creator>
				<category><![CDATA[.this]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[extensibility]]></category>
		<category><![CDATA[Principles]]></category>

		<guid isPermaLink="false">http://blog.itwarlocks.com/?p=19</guid>
		<description><![CDATA[I started writing my About page, but what I wrote started to feel like an article more than a short summary, so here is the full text:
What is &#8220;Extensible&#8221;?
Extensible is defined in Wikipedia as:
In software engineering, extensibility (sometimes confused with forward compatibility) is a system design principle where the implementation takes into consideration future growth. [...]]]></description>
			<content:encoded><![CDATA[<p>I started writing my <a title="Extensible Development - About" href="/about" target="_self">About</a> page, but what I wrote started to feel like an article more than a short summary, so here is the full text:</p>
<h3>What is &#8220;Extensible&#8221;?</h3>
<p>Extensible is defined in <a title="Extensibility - Wikipedia" href="http://en.wikipedia.org/wiki/Extensibility" target="_blank">Wikipedia</a> as:</p>
<blockquote><p>In <a title="Software engineering" href="http://en.wikipedia.org/wiki/Software_engineering">software engineering</a>, <strong>extensibility</strong> (sometimes confused with <a title="Forward compatibility" href="http://en.wikipedia.org/wiki/Forward_compatibility">forward compatibility</a>) is a <a class="mw-redirect" title="System design" href="http://en.wikipedia.org/wiki/System_design">system design</a> principle where the implementation takes into consideration future growth. It is a systemic measure of the ability to extend a <a title="System" href="http://en.wikipedia.org/wiki/System">system</a> and the level of effort required to implement the extension. Extensions can be through the addition of new functionality or through modification of existing functionality. The central theme is to provide for change while minimizing impact to existing system functions.</p>
<p>Although forward compatibility and extensibility are similar, they are not the same. A forward compatible system can accept data from a future version of itself and pick out the &#8220;known&#8221; part of the data. An example is a text-only word processor ignoring picture data from a future version. An extensible system is one that can be upgraded to fully handle the new data in the newer input format. An example is the above mentioned word processor that can be upgraded to handle picture data.</p>
<p>In <a title="Systems architecture" href="http://en.wikipedia.org/wiki/Systems_architecture">systems architecture</a>, <strong>extensibility</strong> means the system is designed to include hooks and mechanisms for expanding/enhancing the system with new capabilities without having to make major changes to the system infrastructure. A good architecture provides the design principles to ensure this—a roadmap for that portion of the road yet to be built. Note that this usually means that capabilities and mechanisms must be built into the final delivery which will not be used in that delivery and, indeed, may never be used. These excess capabilities are <em>not frills,</em> but are necessary for <a title="Maintainability" href="http://en.wikipedia.org/wiki/Maintainability">maintainability</a> and for avoiding early <a title="Obsolescence" href="http://en.wikipedia.org/wiki/Obsolescence">obsolescence</a>.</p>
<p><strong>Extensibility</strong> can also mean that a software system&#8217;s behavior is modifiable at runtime, without recompiling or changing the original source code. For example, a software system may have a public <a class="mw-redirect" title="Application Programming Interface" href="http://en.wikipedia.org/wiki/Application_Programming_Interface">Application Programming Interface</a> that allows its behavior to be extended or modified by people who don&#8217;t have access to the original source code.</p>
<p>Although usually applied to engineered <a class="mw-redirect" title="Systems" href="http://en.wikipedia.org/wiki/Systems">systems</a> involving <a class="mw-redirect" title="Software" href="http://en.wikipedia.org/wiki/Software">software</a>, it can be applied to any type of engineering. Houses can be built with future extensions in mind. The <a title="Prince Edward Viaduct" href="http://en.wikipedia.org/wiki/Prince_Edward_Viaduct">Prince Edward Viaduct</a> located in <a title="Toronto" href="http://en.wikipedia.org/wiki/Toronto">Toronto</a>, <a title="Ontario" href="http://en.wikipedia.org/wiki/Ontario">Ontario</a>, <a title="Canada" href="http://en.wikipedia.org/wiki/Canada">Canada</a> was built to accommodate a future subway line.</p>
<p>Though the application to software is relatively new, the word has been a rare but valid part of English for a long time. The <em><a title="Oxford English Dictionary" href="http://en.wikipedia.org/wiki/Oxford_English_Dictionary">Oxford English Dictionary</a></em> cites examples going back to the 17th century.</p></blockquote>
<p>For me extensibility means, thinking ahead without planning the future. In the classic waterfall model, this would mean analysing all possible future feature enhancements and adapting the architecture to be extendable. This method always misses the target though and causes more problems and frustration along the road. My philosophy is that using development principles like Agile, Scrum, RUP etc. will not make the actual software extensible, but it will make the code much more flexible. Agile is used to be able to quickly adapt to changing needs (required feature priority, etc.) during development, but one thing that&#8217;s normally not mentioned is the timeframe.</p>
<p>If the development process is based around being agile, adapting to change and delivering production quality parts, does it matter if these changes come tomorrow, next week or next year? Of course not. The biggest issue with creating software that is future-proof is often not the actual architecture, but the code and the organisation around it. If code is well documented and the project around it is fine-tuned for quick change, then the code will become easier to maintain and adapt, thus becoming extensible. Often when we&#8217;re asked to make changes in (older) system the biggest problem is understanding the architecture and code in order to be able to make the changes. I&#8217;ve often heard of and seen systems that were extremely hard to maintain, so badly even that noone was allowed to touch the code and a complete new product was being developed instead. If those nightmare systems had been made using Agile/Scrum/RUP, then this probably would not have been the case. I say &#8220;probably&#8221; since there are people out there that implement Agile just for the sake of it without truly understanding it, this delivering even worse maintainable products.</p>
<p>What it comes down to is this: It&#8217;s not the code that makes a product extensible, it&#8217;s the process that creates it that does.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.itwarlocks.com/2009/04/02/thinking-ahead-without-planning-the-future/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk
Page Caching using disk (enhanced) (user agent is rejected)

Served from: blog.itwarlocks.com @ 2010-07-29 14:40:08 -->