Wednesday, November 24, 2010

To Inhabit the Solar System by Anthony Zuppero

This book is different from the books I usually read because it is an autobiography. However it has enough science in it to be great, enough fantasy in it to be totally inspirational and also it is one of the most real (and thus sad) books I have ever read. What is even nicer is that the book is free online on Anthony Zuppero's site. I can't recommend it enough. Go there, download it, read it: To Inhabit the Solar System

The plot itself is about this physicist guy, diagnosed with Asperger's syndrome, who gets into his head that we could build rockets to go to other star systems. It all starts in 1968, when he reads about the Dyson nuclear bomb propulsion, an outrageous scheme to detonate nuclear bombs to push a rocket. From then on, he embarks into jobs that are closer and closer to this purpose, always finding solutions to problems that appear along the way. In the end, he finds a way to cheaply get the water from comets, asteorids, moons and use it to propel spaceships around the Solar System. He practically gives us the keys to the universe, the highways that would allow the thorough exploration and utilization of resources in our solar system. It is just amazing.

There are multiple things that I liked about the book. Most of all, I liked the guy. He is what I would call a true hero: he finds a cause and dedicates his life to it, without any desire for personal gain. He doesn't just blab around about the ideas that he has, he finds people, resources, makes calculations and determines the problems that arise and specific concrete solutions for them. Then the style of the book: so bloody honest, so many things to be learned from the way he repeats what is important, the details of all his thoughts, hopes and desires; a great read. And last, but not least, the technical aspects of the book. After reading it, you will be able to understand each step of getting fuel and construction material from space, using it to propel and build stuff, all in a reasonable enough price and without the need for expensive planet-space trips.

Now, there are some issues with the book. First of all, it is not at all polished. It says its story, but it's also filled with personal notes, incomplete chapters and
various information. My guess is that at some time he wanted to publish the book and no one was interested. Or maybe he just didn't want to waste time polishing the book and stop people from getting the ideas in it. Or maybe he just didn't feel the story ended. Either way, for me it added to the charm and realism of the book, rather than take stuff away.

It was heartbreaking to read about the death of Gene Shoemaker. In the book - the author took it hard - but it so happened I was reading the book while they announced the death of Brian Marsden, another proeminent character in the book, and I felt the pain anew.

Bottom line: you should read this. If not for the quality of the book, not for the realistic description of government agency inner workings and personal tricks to get something done, if not for the amazing person that Anthony Zuppero is, read it for the detailed description on how we could today (actually, from about the 1980's) inexpensively inhabit the Solar System.

Tuesday, November 23, 2010

Compute Google Chrome Extension IDs in .NET C#

In order to programmatically load a .crx Chrome extension as an external extension, the ID of the extension is required. The algorithm for computing it is:
  1. make a SHA256 hash of the public key embedded in the .crx file
  2. take the first 128bits (16 bytes) and encode them in base16
  3. use characters a-p instead of the customary 0-9,A-F


For this we need, obviously, the public key. Reading from the CRX Package Format page, we can determine we need a 4 byte (Int32) value of the public key length and the public key itself. The length is found at position 8 in the file, the public key starts at position 16. Here is the code:

private byte[] getPublicKey(FileInfo fi)
{
using (
FileStream stream = File.Open(fi.FullName,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
byte[] arr = new byte[4];
stream.Seek(8, SeekOrigin.Begin);
stream.Read(arr, 0, arr.Length);
var publicKeyLength = BitConverter.ToInt32(arr, 0);
arr = new byte[publicKeyLength];
stream.Seek(16, SeekOrigin.Begin);
stream.Read(arr, 0, arr.Length);
return arr;
}
}


The code to create the id is now simple:

private string getExtensionId(byte[] publicKey)
{
SHA256 sha = SHA256.Create();
publicKey = sha.ComputeHash(publicKey);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 16; i++)
{
byte b = publicKey[i];
char ch = (char)('a' + (b >> 4));
sb.Append(ch);
ch = (char)('a' + (b & 0xF));
sb.Append(ch);
}
return sb.ToString();
}


Just in case you want to get a complete class that handles .crx files, here it is:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web.Script.Serialization;
using SevenZip;

namespace ChromeExtensionInstaller
{
internal class CrxPack
{
#region Instance fields

private byte[] mContent;
private SevenZipExtractor mExtractor;
private dynamic mManifest;
private Uri mUri;
private string mPath;

#endregion

#region Properties

public Exception InvalidReason
{
get;
private set;
}

public bool IsValid
{
get;
private set;
}

private dynamic Manifest
{
get
{
if (mManifest == null)
{
FileInfo fi = new FileInfo(mUri.AbsolutePath);
mManifest = getManifest(fi);
}
return mManifest;
}
}

public string Id
{
get
{
return getExtensionID();
}
}

public string Name
{
get
{
return Manifest.name as string;
}
}

public string Version
{
get
{
return Manifest.version as string;
}
}

public string Path
{
get
{
return mPath;
}
}

#endregion

#region Constructors

public CrxPack(string path)
{
mPath = path;
try
{
checkPath(path);
IsValid = true;
}
catch (Exception ex)
{
IsValid = false;
InvalidReason = ex;
}
}

#endregion

#region Private Methods

private void checkPath(string path)
{
mUri = ExtensionHelper.GetUri(path);
if (mUri == null)
{
throw new Exception(string.Format("Parameter is not a valid URI ({0})", mPath));
}
mPath = mUri.AbsolutePath;
if (!mUri.IsFile && !mUri.IsUnc)
{
throw new Exception(string.Format("Only file and local network paths are acceptable ({0})",
mPath));
}
DirectoryInfo di = new DirectoryInfo(mPath);
if (di.Exists)
{
throw new Exception(string.Format(
"Loading extensions from folders is not implemented ({0})", mPath));
}
FileInfo fi = new FileInfo(mPath);
if (!fi.Exists)
{
throw new Exception(string.Format("The file does not exist ({0})", mPath));
}
if (fi.Extension.ToLower() != ".crx")
{
throw new Exception(string.Format("The file extension must be a .crx file ({0})", mPath));
}
try
{
mExtractor = getExtractor(fi);
if (mExtractor.Check())
{
return;
}
}
catch (Exception ex)
{
throw new Exception(
string.Format("The file could not be read as a valid .crx file ({0})", mPath), ex);
}
throw new Exception(string.Format("The file could not be read as a valid .crx file ({0})",
mPath));
}


private SevenZipExtractor getExtractor(FileInfo fi)
{
byte[] arr;
using (
FileStream stream = File.Open(fi.FullName, FileMode.Open, FileAccess.Read,
FileShare.ReadWrite))
{
arr = new byte[fi.Length];
mContent = arr;
stream.Read(arr, 0, arr.Length);
}
// force PkZip signature
arr[0] = 0x50;
arr[1] = 0x4B;
arr[2] = 0x03;
arr[3] = 0x04;
MemoryStream ms = new MemoryStream(arr);
return new SevenZipExtractor(ms);
}

private string getExtensionID()
{
int length = readInt(8);
byte[] bytes = readBytes(16, length);
SHA256 sha = SHA256.Create();
bytes = sha.ComputeHash(bytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 16; i++)
{
byte b = bytes[i];
char ch = (char) ('a' + (b >> 4));
sb.Append(ch);
ch = (char) ('a' + (b & 0xF));
sb.Append(ch);
}
return sb.ToString();
}

private int readInt(int index)
{
byte[] bytes = readBytes(index, 4);
return BitConverter.ToInt32(bytes, 0);
}

private byte[] readBytes(int index, int length)
{
byte[] bytes = new byte[length];
Array.Copy(mContent, index, bytes, 0, length);
return bytes;
}

private object getManifest(FileInfo fi)
{
SevenZipExtractor extractor = getExtractor(fi);
string json;
using (MemoryStream ms = new MemoryStream())
{
extractor.ExtractFile("manifest.json", ms);
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
json = sr.ReadToEnd();
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] {new DynamicJsonConverter()});
return serializer.Deserialize(json, typeof (object));
}

#endregion
}
}


You need to reference the SevenZipSharp library and place 7z.dll (from the 7-Zip archiver) in the same folder with the application using this class.

Make SHA256CryptoServiceProvider work on Windows XP SP3

I was trying to verify an SHA256 signature (don't ask) and so I had to use the class SHA256CryptoServiceProvider. Alas, the constructor promptly threw an exception telling me the class is not supported on my system. I googled it and found this answer: C# - SHA256CryptoServiceProvider and related possible to use on WinXP?. Whereas the link reports this is a bug in .NET 3.5 I am working with version 4.0 and it is still there.

Apparently, the constructor of SHA256CryptoServiceProvider looks for a certain name in the cryptography providers installed on the machine. It looks for "Microsoft Enhanced RSA and AES Cryptographic Provider" and it gets the XP variant "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)". The solution is to export the key, remove "(Prototype)" and install the resulting reg file. Then it works. Here is the file, as it resulted on my computer:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider\Microsoft Enhanced RSA and AES Cryptographic Provider]
"Image Path"="rsaenh.dll"
"Type"=dword:00000018
"SigInFile"=dword:00000000

Friday, November 19, 2010

Making a Chrome Extension execute Javascript code in the page execution context

Update: in order to execute a script in any open tab inside Chrome, use the executeScript method of the tabs API.

Chrome browser extensions are so cool, that they protect you from accidentally running and adding script to a page that might interfere with the original code of the page. Unfortunately, they don't give you a parameter or option to actually do that, if it is what you actually want. All you can do, by default, is to access the elements in the page document, but not change direct members of window or even document.

I have found the solution on this page: Writing a Google Chrome extension: How to access the global context of the embedding page through a content script.. There is code and explanations for the code, but basically it is a function that injects another function in the real page context and also returns a result.

Wednesday, November 17, 2010

WPF quirks: The case of the exploding MaxWidth Line

I had this control that consisted of a textbox and a squigly red line in case of a required value error. In order to do it, I added the textbox and the line to a Grid, without specifying column or row values, so that the line would come above the textbox. It all worked well until I wanted to make the control align to the left, thus growing with the content entered in it. To my surprise, the control would stretch to the content width when in edit mode and go to 202 pixels outside it. The only things in the template were a textbox and a line inside a grid and a border, so I proceeded on inspecting all of their attributes in search for the culprit. It so happens that the Line was it!

Update: The Microsoft guys responded in a day to my bug report, but they couldn't reproduce it. It seems this behavior can be reproduced only in a Grid column with Width="Auto". Frankly, I was a bit surprised to see that, lacking that grid column, a line with Stretch="Fill" and HorizontalAlignment to "Left" would still expand the container to its maximum size. End update.
The code looked like this:

<Style x:Key="StyleRequiredUnderline" TargetType="{x:Type Line}">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Stretch" Value="Fill"/>
<Setter Property="X1" Value="0"/>
<Setter Property="X2" Value="1"/>
<Setter Property="Y1" Value="0"/>
<Setter Property="Y2" Value="0"/>
<Setter Property="MaxWidth" Value="200"/>
</Style>

<Grid>
<TextBlock x:Name="TextBlock" />
<Line Name="RequiredUnderline" Style="{StaticResource StyleRequiredUnderline}"
/>
</Grid>
As you can see, the line is Left aligned, it has no specified Width, the only giveaway is the Stretch property set to Fill. Now, you think that was the problem, but it was not! See that I have a MaxWidth of 200. That was per request.

It appears that if I remove the MaxWidth setting, the line goes DOWN to the normal size of the parent inner width. MaxWidth, not MinWidth, mind you. Ok, so I've tried some other things. Stretch to None makes the line be 1px long. Setting X2 to 200 makes the line take 200px, same as setting Width. HorizontalAlignment to Stretch makes the line go to the center of the space if it is bigger than the 200 MaxWidth.

The solution? I've bound the Width of the line to the ActualWidth of the TextBlock above. Another option would have been to surround the line with a scrollviewer or some other control that would allow the line to be as long as it wanted without showing a scrollbar or stretching to the size of its content. Either solution seems bad.

Is this a bug? I think so. If the Stretch property should have affected the space the line takes, then it should have done so when MaxWidth was set to Infinity, but it did not. Well, hopes it helps someone. Final code piece for the line:

<Grid>
<TextBlock x:Name="TextBlock" />
<Line Name="RequiredUnderline" Style="{StaticResource StyleRequiredUnderline}"
Width="{Binding ActualWidth,ElementName=TextBlock}" />
</Grid>


Update: The fix I've exemplified above doesn't work when the HorizontalAlignment of the grid is Stretch or has a Width and the TextBox doesn't have a Left HorizontalAlignment. I have tried to replace the Line with a ScrollViewer with hidden scrolling on the horizontal and disabled on the vertical and having a MaxWidth of 200, Inside placing the troublesome Line. I've tried all kinds of panels and combinations of HorizontalAlignment, HorizontalContentAlignment, ClipToBounds, etc. All to no avail.

Finally, the solution was to create a simple control that would ignore the dimensions of the child controls, demanding no space. I named it ClipContainer and here is its source:

public class ClipContainer : ContentControl
{
protected override Size MeasureOverride(Size availableSize)
{
base.MeasureOverride(availableSize);
return new Size(0, 0);
}
}

<Grid>
<TextBlock x:Name="TextBlock" />
<local:ClipContainer>
<Line Name="RequiredUnderline" Style="{StaticResource StyleRequiredUnderline}" />
</local:ClipContainer>
</Grid>
I've put the line in this control, MaxWidth and all, and the control stretched to the size of its container and clipped all of its contents.

Also, like any responsible developer , I went to Microsoft Connect to add this issue as a bug. Here is the bug report. Vote it up if it affects you.

WPF Snoop error: '{0}' type does not have a matching DependencyObjectType

Sometimes, when working with a WPF application, Snoop would crash with the most innovative error messages possible. One of these was 'Object' type does not have a matching DependencyObjectType. Well, of course it doesn't, but where does this come from, why only when I use Snoop and how do I fix it?

I won't bore you with the details, enough said I have traced the problem to an AttachedPropertyBrowsableForTypeAttribute I have used on an attached property. I was using a Resharper Live Template (a snippet) to generate the code for the property and I'd accidentally forgot to set a proper type in the attribute and left the default object.

The thing looked like this:

[AttachedPropertyBrowsableForType(typeof (object))]
Replacing object with my control fixed the Snoop crash.

Thursday, November 11, 2010

The trap of using FrameworkPropertyMetadataOptions.Inherits and a PropertyChangedCallback

I had this container that I wanted to handle any mouse click events. So I proceeded on creating an attached property that has a property changed callback in which I would take the element and add a mouse handler to it. Pretty standard stuff, only it didn't quite work. It also blocked any events in the children. As I knew this should have happened in Preview events, not in normal events, I was stumped.

The problem: the attached property was defined with FrameworkPropertyMetadataOptions.Inherits which meant its value applied to all the children, meaning the value changes on all children when I set it on the parent. That meant the handler for the mouse click events was attached to the container and each of its descendants.

Movie Gravity: Hollywood + Bollywood

Two black holes, merging
Here is an unsettling news: US and Indian filmmakers sign Hollywood-Bollywood deal. In my mind, this means outsourcing to India for movies just as good as the software coming from there, it means working together to control distribution and selection of movie material, coordinating moves so that the huge garbage spewing movie monster we now call Hollywood would have no competitor, ever.

Maybe I am just paranoid, but where are the Internet based movie-hacker studios that should have sprouted everywhere with low budget, but very cool films? Do they all stop at small stuff on YouTube and then get a job in fast-food? Where is the "free market" competition in entertainment?

MySQL Quirks: make sure you use the correct type

I was comparing these two MySQL queries. They looked the same, except for some extra joins and groups, but one was lasting for 5 seconds, the other for 2 minutes. I removed all extra stuff from the long lasting query to get to an almost identical query as the first, only to see it run for two minutes again. The only difference was the type of a WHERE clause. Instead of comparing date with "20101012" (string) I would compare it with 20101012 (integer). Apparently, the type conversion alone was invalidating any use of the index on the date column and made the query last forever. Good to know.

Wednesday, November 10, 2010

WPF Quirks: Image gets resized (badly) even when Stretch is set to None

The scenario is that an Image that has its Stretch property set to None still has a different size from the original image source. You check the Padding, the Margin, the VerticalAlignment and HorizontalAlignment properties, you play with the RenderOptions and SnapsToDevicePixels and nothing seems to work. You specify the Width and Height manually and the image is clipped. The problem here, believe it or not, is that the DPI setting of the image source is different from the system DPI setting.

The solution is an ugly thing:

<Image
Stretch="Fill"
Width="{Binding RelativeSource={RelativeSource Self}, Path=Source.PixelWidth}"
Height="{Binding RelativeSource={RelativeSource Self}, Path=Source.PixelHeight}"/>
So set the Stretch to Fill so that it doesn't fill!

Here is the discussion where I got the solution from: How do I keep an image from being stretched when Stretch="None" doesn't work?.

WPF Quirks: "This freezable can not be frozen" when changing Windows system theme

The scenario is easy enough to create: make a Brush, use a Binding as the Color property, use your brush in your app, then start the application and change the system theme. An error "This freezable can not be frozen" will be triggered. The solution is to set x:Shared="False" for the brushes with color bindings.

An entire Microsoft Connect page is devoted to this issue, so get all the details there: Changing system theme throws "This freezable can not be frozen" exception

Update February 2016: The Microsoft Connect page has disappeared. Maybe it was because the bug was marked as "closed - by design", or some other Microsoft site revamp idiocy.

Monday, November 08, 2010

The Evolutionary Void by Peter F. Hamilton

Book cover The Void Trilogy ends with The Evolutionary Void in a typical Hamiltonian way: completely off the scale science and fights, actions with galactic and universal implications and the bunch of special heroic people that lead the entire story to a climactic finish.

I couldn't wait for the last book of the trilogy to get out and I finally got hold of it, but more than a year had passed since reading the first two. Most of the characters I had to remember while reading the book, something that degraded a bit the reading experience. Take it as a hint: before starting a Peter F. Hamilton series of books, make sure they are all available before you start, as you can't let them out of your hands until you get to the end and the feeling of loss is horrible.

Now, about the book itself. The middle of the galaxy hosts an all devouring and unstoppable Void, inside which thought is the main law of physics and which feeds on the mass of the worlds outside in order to sustain itself. Basically, the heroes in the book are battling galactic cancer. The style of the narrative mixes incredibly advanced technology with an archetypal feudal heroic fantasy, bringing them flawlessly together at the end. Not everything makes sense, but then again, not everything could. Simple solutions to problems were available, but never explored, and some characters were popping in and out of the book stream like so many quantum fluctuations. But on the whole, it was a great reading, keeping me connected for the entire length and, unexpectedly judging by the Hamilton books I have read, with a good, satisfying ending.

Now, I plan on reading some non fiction books, then I will probably return to the Prince of Nothing universe. After that, who knows?

Thursday, November 04, 2010

Forcing open a WPF ContextMenu

I had this control where a button was displaying a ContextMenu. I wanted to keep the ContextMenu open so I can manipulate its content. I had assumed that the StaysOpen property would do that for me; it did not. Also, I tried using a ContextMenuClosing event approach, only to discover that it is one of those rare "ing" events that doesn't have a Cancel property. I've looked in the sources of ContextMenu and Popup to see just what is going on and I have decided that the design was impossible to patch in order to get the behaviour I wanted.

In the end, the only solution I could find was to inherit from ContextMenu into a new class that would coerce the IsOpen property to true when StaysOpen is set to true. That did the trick. Here is the code:

public class StaysOpenContextMenu:ContextMenu
{
static StaysOpenContextMenu()
{
fixContextMenuStaysOpen();
}

private static void fixContextMenuStaysOpen()
{
IsOpenProperty.OverrideMetadata(
typeof(StaysOpenContextMenu),
new FrameworkPropertyMetadata(false, null,coerceIsOpen));
StaysOpenProperty.OverrideMetadata(
typeof(StaysOpenContextMenu),
new FrameworkPropertyMetadata(false, null, coerceStaysOpen));
}

private static object coerceStaysOpen(DependencyObject d, object basevalue)
{
d.CoerceValue(IsOpenProperty);
return basevalue;
}

private static object coerceIsOpen(DependencyObject d, object basevalue)
{
ContextMenu menu = (ContextMenu)d;
if (menu.StaysOpen)
{
return true;
}
return basevalue;
}

}


Hope it helps people out.

Update:

This solution only works for the body of the ContextMenu, the submenus are something else. However, the submenus are defined in the control template of a menu item, so that can be easily remedied by changing it to your needs. One quick and dirty solution would be to add a trigger that sets the IsSubMenuOpen property to true whenever StaysOpenOnClick is set. Or, if you simply want to freeze a menu in place, change the template so that the mouse click or hover will only trigger IsSubMenuOpen when the parent ContextMenu has StaysOpen to false, while the StaysOpen property of the MenuItem Popup is set to the ContextMenu StaysOpen.

Tuesday, November 02, 2010

Installing Windows XP with SATA on a laptop - Part 2

A while ago I wrote a post detailing how to install Windows XP on a laptop with SATA drivers without using any floppy disk. Today I had to do such installation again and I've met with some annoying errors.

The laptop was an Acer Aspire, so I did everything in my old post and started the computer. It is important to use the correct drivers, as in my case the installation met with a blue screen with code 0x0000007B. It was like it tried to use some of the SATA drivers I had loaded on my WindowsXP CD, but not the right ones.

After the installation went ok, Windows XP would not boot up, not even in safe mode. In order to check what the hell is going on (because the default behaviour is to show a blue screen and immediately reboot) you need to start the computer and press F8, then disable the automated restart in case of error from the menu.

The problem is that the laptop had "AHCI mode" enabled in BIOS. Apparently, Windows XP doesn't support this mode. Set it to IDE BEFORE you start installing Windows XP. After that, you can enable AHCI after you install some stuff and change some registry entries, but it seems XP doesn't really have much use of this mode of access anyway. Here is a forum discussing this, but I haven't got around to trying the things described there yet.

Good luck with your installation. I almost went for installing Windows 7. Phew!