Historic Weather Update

Feb 12th, 2010 | Posted by brendan | Filed under Interesting

Welcome to DC!

Welcome to DC!

Rock Creek from P St.

Rock Creek from P St.

The Capital Weather Gang has (re)posted some really incredible snow statistics for the Mid-Atlantic region here; an excerpt:

“This winter’s snowfall amounts are similar to what Anchorage, Alaska and Portland Maine typically receive (about 70″). Incredibly, Baltimore has received more snow than any other city in the U.S. this winter…”

Needless to say, many longly-held seasonal and storm snow records were broken, and the season is not even over yet!  In fact, Washington is forecast to receive another “light dusting” this coming Monday.  I know this is generally not a weather blog, but this has been one crazy winter so far.

Crazy Weather in Washington!

Feb 5th, 2010 | Posted by brendan | Filed under Interesting

We interrupt this blog for a special announcement!  The weather forecast for the Washington, DC and surrounding region is primed for historic snowfall (“Snowmageddon” or “Snowpocalypse II,” to some).  Snow has been falling since 10am EST today (Friday) and is forecasted to extend through 10pm EST Saturday, with overnight rates of 2-3″/hour possible.  This is possibly a once-in-a-lifetime event, especially for people from this area.  It is both exciting and somewhat alarming to know just how quickly even marginal local travel can become impossible without a sled and team of dogs.

This picture is a representation of forecasted snow accumulations based on the NAM, a popular short-range prediction model.  Washington is clearly smack in the middle of this huge thing:

I am including some links so you can follow along as this storm unfolds.  These are links that I have frequented through the week leading up to this event:

Capital Weather Gang (CWG) storm coverage and blog is a Washington Post-hosted resource written and maintained by a collection of meteorologists and weather enthusiasts in the Greater Washington area.  They have provided excellent and relatively un-hyped coverage of all winter storms this season, along with commentary and travel analysis.

The Haven, long-time friend and winter-weather-obsessed casual blogger Puneet who has followed these events closely, and has provided regional estimates for totals and timing.

Earl Barker’s Models page contains links to the up-to-date model images for various outputs from GFS and NAM variants, along with others.  A pretty exhaustive site (and the source of the image above)!  This is just the page for regional snowfall predictions.

National Weather Service (NWS) forecast and tracking information is our local NWS station (Sterling, VA) which provides radar and issues watches and warnings.  This is the closest station to DC, and has steadily increased predictions for the storm all the way up to 20-30+” at present.  This is for sure the highest total I have seen for a single storm living in the area for almost 30 years.

NWS National Radar links to the newest experimental radar overlay.  It is on top of the Google Maps engine and is pretty self-explanatory.

Maintaining Office 2003 Programmability with Side-by-Side Office Install

Feb 5th, 2010 | Posted by brendan | Filed under .Net

In order to build for Office 2003 interop/automation while having Office 2007 installed in a side-by-side installation, you need to remove the .NET programmability support from each 2007 product. This ensures that the latest version available in the GAC is version 11 (2003), since most of the time .NET builds will pull from there instead of a local reference.

To do this, go to add/remove programs and call up the change features window for Office 2007, find the item called “.NET Programmability Support” under each product you have installed, and remove it. There are also items under Office Tools for Graph and Smart Tags:

Then, your GAC will include only version 11 assemblies for each product rather than 11 and 12. You should be able to build as you did before under 2003 alone.

Firefox 3.6 (final) is out!

Oct 31st, 2009 | Posted by brendan | Filed under Interesting

The final version of Firefox 3.6 is available now! (http://www.mozilla.com/en-US/firefox/firefox.html?from=getfirefox)

One-way Hashing for C# and Java

Oct 29th, 2009 | Posted by brendan | Filed under .Net, Java

I was recently faced with the need to create some sort of verification measure for URLs.  Basically, public users would be able to access an internal system using a generated URL, and I needed to make sure that these links were very difficult to guess or even reverse-engineer.

I decided to use an SHA1 hash, which creates a reproducible series of bytes that can then be authenticated by comparison at a later time.  This is a pretty common way of checking to make sure your message has not been tampered with and, while it can be hacked, it is very, very difficult (and time-consuming) to do so.  For my use, it is a reasonable solution.

The trick here is that I needed to generate the hash in Java and then check it in C#.  This sounds easy (and it is), but I did spend some time tracking down how to get the same output from these two algorithms when converting back to a string.  Unfortunately,  you can’t just pass the bytes around in a URL.

Let’s take a look at the Java version:

	public static String generateSHA1Hash(String input) throws Exception {

		MessageDigest messagedigest = MessageDigest.getInstance("SHA");
		messagedigest.update(input.getBytes("UTF-8"));
		byte digest[] = messagedigest.digest();

		StringBuffer s = new StringBuffer(digest.length * 2);
		int length = digest.length;
		for (int n = 0; n < length; n++) {
			int number = digest[n];
			number = (number < 0) ? (number + 256) : number;
			s.append(Integer.toString(number, 16));
		}

		return s.toString();
	}

The input is an ID string plus a salt (another, static string).  You need the salt in order to prevent someone from guessing how the hash  is generated.  The key is that second part which is taking each byte and converting it into a character (so it can be easily displayed and passed around).  This is where the difficulty presented itself.  I could get the same output in byte form, but the character conversion was funky.  I feel like I am probably doing something wrong, because I had to actually just drop any space ” ” characters in the C# version:

        private bool checkHash(message) {            

            SHA1 sha = new SHA1Managed();
            UTF8Encoding ue = new UTF8Encoding();
            byte[] data = ue.GetBytes(message);
            byte[] digest = sha.ComputeHash(data);

            StringBuilder newHash = new StringBuilder();
            int length = digest.Length;
            for (int n = 0; n < length; n++) {
                //remove spaces to match java
                newHash.Append(String.Format("{0,2:x}", digest[n]).Replace(" ", String.Empty));
            }

            return (docReq.Hash.Equals(newHash.ToString()))
        }

In this example, message is the incoming text to hash (in this case, the ID string along with the same salt used in generating the original), and docReq.Hash is the existing hash to compare against.  As you can see, the code is not quite the same (but very similar).  Can anyone point out the mistake I made and tell me why the C# version produces ” ” characters, but the Java version does not?

Either way, these do produce the same comparable result.  Just remember to salt your inputs!

Simple WebDAV Part 2

Oct 15th, 2009 | Posted by brendan | Filed under .Net

Part 2 of this series is about the client-side extension used to open the remote file locally.  Normally, clicking a link to a file causes the browser to prompt the user or OS for what to do with it, and then pull it down as a stream.  This behavior can sometimes be modified depending on the HTTP headers sent along with the server response (attachment specification, MIME type, etc.), and browser plugins, but in nearly all cases it is still the browser interacting with the file as a stream and opening it directly.  Since the browser is not a WebDAV client, it doesn’t implement the protocols we need.

What we need to do is open the file directly using a WebDAV client, such as Microsoft Word.   We can accomplish this one of several ways:

1) Write our own COM component which we can instantiate from browser javascript.
2) Use the the SharePoint library which is built-in to Office 2000-2007.
3) Provide only the link and have the user open Word and the file location interactively.

Write our own COM Component:
This is the initial approach I took, and it can be a good one for several reasons.  First, it allows you to control how the file is opened in the client application.  You can have full access to the application using Office Automation, which can be powerful if you need to set things up a certain way for the user.  I wrote my implementation using a combination of C# and VB.NET, but I am confident it could be accomplished using other 4GLs.

For my component, I created the interface and implementation in C# and wrote the client interaction in VB.NET.  This was more personal preference than anything else because I prefer C#, but have had better luck doing Office Automation using VB.  The key here is to also implement the IObjectSafety interface in order to avoid an annoying security popup every time a user clicks on your links.  This is easy and I have included a copy in the project download.

You can see how simple this is (remember to create new GUIDs for yourself!):

WebEditCS.cs:

namespace WebEdit.ActiveX.CS {

    [
        Guid("B6E9F230-F7C6-4686-9DB1-6C0E8C33FBA2"),
        InterfaceType(ComInterfaceType.InterfaceIsDual),
        ComVisible(true)
    ]
    public interface IWebEditCS {
        [DispId(1)]
        bool DoWebEdit(int app, string url);
    };

    [
        Guid("01453349-18FB-434f-AB73-BFA3F73D9967"),

        // This is basically the programmer friendly name
        // for the guid above. We define this because it will
        // be used to instantiate this class. I think this can be
        // whatever you want. Generally it is
        // [assemblyname].[classname]
        ProgId("WebEdit.ActiveX"),

        // No class interface is generated for this class and
        // no interface is marked as the default.
        // Users are expected to expose functionality through
        // interfaces that will be explicitly exposed by the object
        // This means the object can only expose interfaces we define
        ClassInterface(ClassInterfaceType.None),

        // Set the default COM interface that will be used for
        // Automation. Languages like: C#, C++ and VB
        // allow to query for interface's we're interested in
        // but Automation only aware languages like javascript do
        // not allow to query interface(s) and create only the
        // default one
        ComDefaultInterface(typeof(IWebEditCS)),
        ComVisible(true)
    ]
    public class WebEditCS : IObjectSafetyImpl, IWebEditCS {

        public bool DoWebEdit(int app, string url) {
            return WebEditVB.DoWebEditVB(app, url);
        }
    };
}

This is just an example, and could be modified a lot to open different applications with different settings.   This particular version also uses a single copy of each application by getting a reference to the running object (if it exists).  While this is probably the safest way to do Office Automation, it isn’t the only one (you can certainly open a new copy every time a link is opened…).   Experiment and find what works best for your situation.

WebEditVB.vb:

Namespace WebEdit.ActiveX.VB
    Public Class WebEditVB

        Private Shared Function GetInstance(ByVal appName As String) As Object
            Dim application As Object = Nothing

            Try
                application = Marshal.GetActiveObject(appName)
                If application Is Nothing Then
                    application = CreateObject(appName)
                End If
            Catch ex As Exception
                application = CreateObject(appName)
            End Try

            Return application
        End Function

        Public Shared Function DoWebEditVB(ByVal app As Integer, ByVal url As String) As Boolean

            Dim application As Object = Nothing
            Dim document As Object = Nothing

            Try
                If app = 0 Then
                    application = GetInstance("Word.Application")
                    application.Visible = True
                    document = application.Documents.Open(url)
                    document.Activate()

                ElseIf app = 1 Then
                    application = GetInstance("PowerPoint.Application")
                    application.Visible = True
                    document = application.Presentations.Open(url)

                ElseIf app = 2 Then
                    'user cannot have an open spreadsheet with a cell currently being edited!
                    application = GetInstance("Excel.Application")
                    application.Visible = True
                    document = application.Workbooks.Open(url)
                    document.Activate()
                End If

            Catch ex As Exception
                Try
                    Dim logName As String = "C:\Program Files\NLRB\QuickEdit-ErrorLog.txt"
                    Dim fs As FileStream = New FileStream(logName, FileMode.Append, FileAccess.Write)
                    Dim sw As StreamWriter = New StreamWriter(fs)
                    sw.WriteLine(DateTime.Now.ToString())
                    sw.WriteLine(ex.ToString())
                    sw.Close()
                    fs.Close()
                Catch
                End Try

                Return False
            End Try

            Return True
        End Function

    End Class
End Namespace

Use the SharePoint Library:
After developing my own control, I discovered that there was an even easier way to accomplish the same thing.  I found out that Microsoft ships a (probably similar) control as part of each Office installation starting with Office 2000.  This control seems to work pretty much the same as my version, except it doesn’t implement IObjectSafety.   The advantage is that you do not have to deploy any kind of client-side control because it is already on every machine with Office!  In many cases, even though it is not as nice for your users (who will have to click ‘Yes’ on a dialog every time), it is often the only viable option in an enterprise (which often won’t allow you to push ActiveX/COM controls out to users).

As you can see above, I don’t have any specialized logic for opening these applications or files, so using the library that ships with Office is great for me.  I implemented this so that it tries to use each version of the library (there is a different version for each Office version…) in turn.

function webedit(id) {
        if (window.ActiveXObject) {
            var ed;
            try {
                //Office 2003
				ed = new ActiveXObject('SharePoint.OpenDocuments.2');
            } catch (err1) {
                try {
                	//Office 2000/XP
    				ed = new ActiveXObject('SharePoint.OpenDocuments.1');
                } catch (err2) {
                    try {
                    	//Office 2007
        				ed = new ActiveXObject('SharePoint.OpenDocuments.3');
                    } catch (err3) {
						window.alert('Unable to create an ActiveX object to open the document. This is most likely because of the security settings for your browser.');
						return false;
            		}
                }
            }
            if (ed) {
				ed.EditDocument('<%=webdavPath%>/webdav/<%=user%>--'+id);
				return false;
            } else {
				window.alert('Cannot instantiate the required ActiveX control to open the document. This is most likely because you do not have Office installed or you have an older version of Office.');
				return false;
            }
		} else {
            window.alert('Internet Explorer is required to use this feature.');
		}
		return false;
	}

Provide only the Link:
As a last resort, you can always provide/display a link for the user to open manually.  While this sounds silly, users still gain the benefit of WebDAV actions from within their local apps, meaning they still save directly against the repository.  This can be helpful for people who work on a few files a day for a longer period of time rather than those who open lots and lots of documents daily.

i_attachment WebEdit (VS2008 project)

Simple WebDAV Part 1

Sep 21st, 2009 | Posted by brendan | Filed under Documentum, Java

This is part 1 of a 2-part series detailing how I implemented WebDAV support for a Documentum repository.  It is very basic and does not implement all of the methods that WebDAV supports, but it gets the job done.  The end result is a type of “Web Edit” functionality that allows single-click checkout, edit, and checkin for Microsoft Office files (but the idea isn’t restricted in any way to MS Office types).

The first goal is the actual WebDAV server, which was actually much easier to put together than I expected.  Some of you may already know, but I was surprised to learn that Apache Tomcat 5.5+ has WebDAV support built in as a standalone servlet.  I simply copied this “WebdavServlet” and stuck my code in where it made sense.  WebdavServlet uses the filesystem as its repository, which is a common and flexible way to handle opening and editing files.  This works fine for us, since we are working with physical files as well (they just don’t happen to be in this particular location…yet).  Our second goal is to get those files to behave as if they are local.

Let’s take a look at WebdavServlet.java (obtained via Subversion @ http://svn.apache.org/repos/asf/tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java).  In addition to the DefaultServlet’s GET and PUT methods, it implements two methods specific to the WebDAV protocol that we are interested in: LOCK and UNLOCK.  We can drop our custom code into these methods to push and pull files from Documentum (or any other system, really):

LOCK: Interestingly, there are two steps to perform here.  First, you must get the file from Documentum and move it to a local path (I am just moving it to the root of the application context).  You should do this right after the path is retrieved from the request object (look for this line in doLock():

String path = getRelativePath(req);

...

Content contentObj = d.getContents().get(0);
// Get the Content of this file
if (contentObj.canGetAsFile()) {
	File f = contentObj.getAsFile();
	File to = new File(getServletContext().getRealPath("/")+ path);
	if (f.renameTo(to))
		log("get successful.");
	else {
		if (f.exists() && f.canWrite())
			f.delete();
		log("file move failed.");
	}
} else {
	log("get unsuccessful.");
}

The second step is to checkout the document in Documentum.  You can do this pretty much wherever you want in the method, but I prefer to wait until the very end of doLock() to make sure that the file was downloaded successfully.  Now you have the local file for Tomcat to serve with GET (which is called after LOCK), and it is locked for editing in your repository.

GET: This one is the easiest!  We actually don’t have to modify this at all.  This will serve our files from the filesystem like it normally would.

PUT: As you can probably guess, we will use this method to save the file back to Documentum.  Just place your logic at the end of the method, and do as you normally would when saving files to the repository from disk.  A slight catch is that you should also checkout the file again, because you can’t be sure that the user is finished editing.  Keep in mind that any save operation will fire a PUT, so the user should maintain the lock.  Once the WebDAV client is ready to release the lock, it will call UNLOCK.

UNLOCK: All you do here is cancel the checkout in the repository.  That’s it.  Well, I also delete it from the filesystem just to be sure it doesn’t get stepped on later:

    		//remove the file from the filesystem
    		File f = new File(getServletContext().getRealPath("/")+ path);
    		if (f.exists() && f.canWrite()) {
    			f.delete();
    			log("file deleted.");
    		}

Now, you may be wondering “hey, what about security?”  This is a very good question and is something that, fortunate for me, I did not have to worry about since this is not a public system.  Tomcat’s WebDAV default web.xml does allow for the normal Tomcat authentication methods (using conf/tomcat-users.xml and the like) so this is still a possibility.  I pass the username in the URL to the file, so I know who to perform repository operations as, in the form “http://<domain>/<application context>/<username>–i_chronicle_id.<file extension>”.

Your WebDAV server implementation should now be complete!  But how will you provide the single-click “Web Edit” capability that many organizations ask for, and many other products integrate?  In part 2, I’ll show you how to create a COM component using .Net which can start an application and load WebDAV URLs.

Cheers!