There are literally for sending your image files to your account. This post is not really about sending images to Flickr, it's not even about sending e-mails from .NET code by using GMail as an SMTP server (I chose that approach over mastering the vast Flickr API - or using a .NET wrapper of some description, however here is a good one if you're interested).
What I really want to explore with this post and the sample application are two things:
- How to create a settings window the WPF way, e.g. by using data binding to the Settings class and successfully handling the Cancel scenario, and
- Storing secrets, like your GMail password, in plain sight e.g. by using a settings configuration file, also this must be in a WPF friendly way.
Given my previous experience with tools that help me with my Flickr account, and my simple requirements, I'm sure you'll forgive me for writing my own Flickr uploader, which forms the basis for the sample application.
Simply, the WPF application has three very basic windows:
The Help window, the Configuration window and the Sending window. The Help window is simply a FlowDocumentViewer with an inline FlowDocument. The Sending window is the one that sends an email by using the settings information. Finally, the Settings window for capturing the necessary settings information.
The application works by you placing a shortcut to the assembly in your Send To folder (the path on Vista will be:
%APPDATA%\Microsoft\Windows\SendTo), right-click the target image, and then click Send to Flickr (or whatever you called your shortcut).
Providing you've populated your settings information, that process will send an email to your Flickr account with the selected image as an attachment.
Data Binding to Settings
The diagram above provides a visual explanation of how the settings works for this application (click the image to see a larger version). The goal with this design is to only use WPF data binding, in order to remove any of the tedious right-hand/left-hand code; this type of code, as described by Scott Hanselman, is:
[the code] where you've got an object on the left and some other object/bag/pileOdata on the right and you spend a lot of lines just going "left side = right side, left side = right side."
Basically property field mapping; really boring, time consuming and error prone code. This design makes all that go away.
However, the usual downside with this approach is something I like to call "The Cancel Problem". This is where the user has updated a value in the dialog, but then changes their mind and clicks the Cancel button. The behaviour you want is to ignore the update, but because your UI and the backing store are bound together updates are dynamic. This means when the user tabs off the control, or presses ENTER, an update is immediately sent to the underlying data store.
Solutions to this problem tend to involve using intermediate objects to remember the old settings or store the new, and then when the user saves you write some left-hand/right-hand code to persist the values, booooh!
The simple solution I have chosen for this problem is shown in the diagram; basically in the OK button click you call Save on the Settings class, and on a Cancel button click you call Reload. This appears to be a little known technique, but solves the Cancel problem completely and removes any need for intermediate objects, and therefore any right-hand/left-hand code, yay! The Reload method simply reads the values again from the backing store, in effect cancelling the operation, and due to the data binding update the in memory view of all the values too.
Next we tackle the more prickly problem of storing sensitive information in your configuration files.
Storing Secrets
With the myriad of tools out there to help you with this social service and the other social service, be it: , , del.icio.us or what-have-you, all asking for your password and potentially a mountain of other personal or sensitive information, all to do things on your behalf making your life easier - what confidence do you have:
-
A) assuming that you trust the installed software not to do anything naughty, and
-
B) that the developers involved were security conscious
that your secrets will not be easily discoverable by third parties by simply spelunking through the plain text files on your machine?
Here's an experiment:
Go to your favourite command line tool (mine's PowerShell), navigate to your AppData folder, in Vista that's: :\Users\YOU\AppData, and then type:
Get-ChildItem -r * | Select-String [your password]
(or the equivalent for your command line tool)
Then do the same for :\Program Files and :\Windows, and then, finally, search the registry for the same information.
The question I have for you is: How confident are you that you won't find any instances of your password?
I'm not saying that you will come up with anything, but what I am asking you is how confident do you feel that you won't, on a scale of 1 to 10 - I bet it's not 10!
With this sample application I wanted to explore a good way to store your email password in the Settings plain-text XML file, which was also a good fit for WPF applications, whilst not adding to your potential security woes.
My search was a pretty short one to find the answer I needed: Data Protection API, provided natively by Windows. Keith Brown explains this all very well in his free book The .NET Developer's Guide to Windows Security. What it boils down to for this application is the use of the ProtectedData class, provided by the .NET Framework since version 2.0, which simply has two methods: Protect and Unprotect. To protect a value you would write code like:
byte[] buffer = Encoding.UTF8.GetBytes(targetValue);
byte[] encryptedData = ProtectedData.Protect(
buffer,
this.entropy,
DataProtectionScope.CurrentUser);
To make this all WPF friendly I wrapped the ProtectedData calls into value converter - so when data binding you can store and retrieve secure information by using my ProtectedDataConverter class as the Converter on the binding.
For passwords where you want to use the WPF PasswordBox control however, you cannot data bind to the Password property, it's not a dependency property - for obvious security reasons, therefore in this application I create an instance of the converter in code and use it that way:
this.PasswordBox.Password = DataCoverter.Convert(
Settings.Default.Password,
typeof(string),
null,
CultureInfo.CurrentUICulture) as string;
To convert the string value back to plain text (decrypt) is shown above, and to convert back in to a secure value (encrypt):
Settings.Default.Password = DataCoverter.ConvertBack(
this.PasswordBox.Password,
typeof(string),
null,
CultureInfo.CurrentUICulture) as string;
The converter returns the cipher text in a Base64 encoded string for easy plain-text storage.
Conclusion
I think I achieved my goals with this software; you, dear Reader, are the real judge of my assertion; to that end the code available for your review and use:
PaulJ.Windows.SendToFlickr
Obviously if you have an problems with the code then let me know. Your comments and personal conclusions are also very much welcome. I would love to know where you use this code, or indeed any of the code I publish, so all I ask is if you intend to use the code please drop me a line to let me know.
Enjoy!