Support free software
Do what you can to support the free software you are using.
I estimate the user base of my free software to about 1000, but over the years I have only been in contact with a hand full of them. It would help me a lot with the future development if I got to know what the users want to have and what they don’t like about it right now. A friendly note or a feature request means a lot to me and I’m quite sure other developers feels like that too.
We, free software developers, spend a lot of time developing our software and some hard earned money to keep our websites and internet connections running.
If you like a product and want to support it go to it’s home page and check out it’s sponsors. That way the developer will get some money and the advertiser will get some traffic. It will benefit a lot of people. You don’t have to donate ‘real’ money but the developer will still get some monetary support and it’ll build your karma.
So the next time you use your favorite freeware; take minute and figure out how you can contribute to it.
I just released jsiPodFetch 8.05
I use an overridden button for the flat buttons in jsiPodFetch and I had forgotten to call InitializeComponent in the constructor that gets called by the designer. This has the nasty side effect of making the control disappear from the form.
The underlying error was corrected before I released 8.04 but I missed one form when I checked for missing buttons; The form to confirm a new feed.
Old users probably never noticed since they have their feeds configured already, but new users got a modal form without button or control box. Doh!
It is taken care of now and I hope I haven’t scared to many users away from it.
jsiPodFetch 7.44 released today
I just uploaded a new release of jsiPodFetch.
CHANGE LOG
7.44
- Enabled two simultaneous downloads. Might be more in the future.
- Made it possible to stop copying files to the player while syncing.
- Feed URL is now emptied after a click on add.
- Fixed a bug that prevented some feeds to be verified.
- All actions should have a wait cursor now.
- A copy of the settings file will now be made when loaded successfully.
Broken settings in jsiPodFetch, revisited
In my last post I wrote about my corrupted settings file in jsiPodFetch.
In the long term I intend to save the state in a different way from what I am doing now. To minimize the discomfort if/when the current solution fails I started to make a copy of the settings file if it loads successfully on application start. So the worst case scenario of failing settings is now that the last session is lost. Previously there was a big chance of losing all state assembled since the application was installed.
Broken settings in jsiPodFetch
The settings file for my installed jsiPodFetch was corrupted today. I probably turned of my computer while it was still saving the file. Since I know the inner workings of the application there wasn’t much of a hassle for me, but since application didn’t start at all I thing other users will just stop using it if this happens.
At the moment I store my settings in a serialized class. One of the properties of the settings class is a typed DataSet. This makes the XML file bot big and vulnerable. I think a should move the per media data to something else than a DataSet and store that in another file. I should also try to use previously downloaded files to recreate state data if the file get corrupted again.
The solution I am thinking about right now will use a standard OPML-file for the feeds and a per feed file for media item state. I might just skip the OPML-file and search for the per feed files in the library structure.
Doh! Nasty bug in jsiPodFetch
The last release wasn’t thoroughly tested and this morning I found a nasty bug that prevents the application to start on its first run.
That is a god way to get rid of users, isn’t it?
I added code in the last release to check for the device name of the player. That way the application can find the player even if the drive letter is changed. If that happens I replace the last drive letter with the current drive letter in the player path setting. The problem is that there is no player path on the first run so I get an ‘index out of range’ exception early in the application.
It is fixed now so I will do a new release tonight or tomorrow. It will probably not be tested enough either, but at least it should not piss of new users.
Yet another podcast: lugradio
Today I added the Linux radio show lugradio to my ever growing feed list in jsiPodFetch. Since I am very close to filling all available time now I think it will take quite long for me to catch up, but I’ll give it a try.
One more podcast
Today I added Rubiverse, a podcast about Ruby, to my jsiPodFetch feed list.
I’ve recently learned some Ruby and I like it a lot. I will definitively install IronRuby when it is properly released. Currently I’m using ‘real’ Ruby for my jsiPodFetch build scripts and for aggregating data from my weblogs. It feels a bit awkward to install something like Ruby just to do some scripting in Windows though, maybe I should look at Powershell instead. That is a bit more classic shell scripting. I think the things I’m using it for is more like programming. I’m not sure when something is to be called a program and when it should be called a script.
The best thing to do is probably to learn lots of languages and frameworks so that one can make educated decisions when it comes to solving new problems.
Shareware license key
This article will describe how I have implemented license keys in jsiPodFetch. I hope it will help someone else trying to do this. It would also be nice if someone reading this gave me feedback if this solution doesn’t work in practice since I haven’t analyzed this solution thoroughly enough to swear by it, but I think it will work.
Through out this code there are places that are open for variation. Most important if you reuse my code here is that you use your own unique strings.
Most payment processors (SWReg, Plimus, and so on) will be able to query a URL of your choice to create a license key. This solution uses a PHP-script to create a license key that can be validated by code written in any .NET-language. I will use C# for my examples.
The solution uses a multi part license key so that you can change the application code that checks the license when/if it gets cracked or keygened.
Let’s start with the PHP-code that creates the license key.
I start by creating three unique strings. Let’s use ‘AAA’, ‘BBB’, ‘CCC’. (I use more than three, but it will be enough to make my point.)
$g1 = 'AAA';
$g2 = 'BBB';
$g3 = 'CCC';
…then I create a hash from the unique string concatenated with the e-mail address used for registering the application.
By the way; I am constantly truncating the values at five characters to make the key a bit smaller. It will make the hash values weaker, but I think it will OK anyway.
$key1 = substr(md5($g1 . $_GET["email"]), 1, 5);
$key2 = substr(md5($g2 . $_GET["email"]), 1, 5);
$key3 = substr(md5($g3 . $_GET["email"]), 1, 5);
… and that’s about it. Now I can concatenate the individual hashes and the e-mail address.
$license = $_GET["email"] . "-" . $key1 . "-" . $key2 . "-" . $key3;
…then I create a hash of the license and concatenate that with the license.
$hash = substr(md5($license), 1, 5);
$license = $license . "-" . $hash;
Finally I return the license key:
echo ($license);
The result is this:
foo@foo.com-fb821-90d34-8b8c6-ca6ab
Now it’s time for some C# code. The main obstacle was getting a PHP compatible hash value out of strings in .NET. I googled a bit and found this (I’m not sure where it came from though so I can’t give proper credit.):
public static string Md5Hash (string pass)
{
MD5 md5 = MD5CryptoServiceProvider.Create ();
byte[] dataMd5 = md5.ComputeHash (Encoding.Default.GetBytes (pass));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dataMd5.Length; i++)
sb.AppendFormat("{0:x2}", dataMd5[i]);
return sb.ToString().Substring(1, 5);
}
This method will return the same string as the PHP md5() method given the same input.
Since I hashed all concatenated sub keys I can now validate a given license key with this:
public static bool LicenseIsValid(string license)
{
int lastHyphen = license.LastIndexOf("-");
if(lastHyphen < 4 )
{
return false;
}
string l = license.Substring(0, lastHyphen);
string hash = Md5Hash(l);
string[] lines = license.Split('-');
return (hash == lines[lines.Length -1]);
}
I could include a fourth secret string when I do the hash of the full key, but at this stage I only want to validate that it is a license key for my program. I don't want to check its authenticity yet.
To authenticate a key I get one of the hashed sub keys. With this function:
public static string GetKey(int n, string license)
{
string[] lines = license.Split('-');
return lines[n];
}
I then hash the secret string I used for the n'th value together with the email and compare the result with the sub key from the license.
string email = GetKey(0);
string validHash = Md5Hash ("AAA" + email);
if(validHash == GetKey(1))
{
//Allow registered stuff
}
else
{
//Inform user that thy have to pay.
}
To make it a little bit harder to crack this, make sure to write this code in several places. If you encapsulate it in a method there is only one place to bypass.
When someone has created valid keys you can recompile the application and use your second secret key so that the key maker has to restart his work. You could also move the checking code around a bit so the cracker has to redo his work.
That's all there is to it.
One thing I miss with this solution is the ability to encode data, like a date, into the key.
New podcasts
While taking the survey on Software Engineering Radio I got noticed of a couple of other technical podcast so I have added IT Conversations and ARCast to my jsiPodFetch feed list.
