Wednesday, November 21, 2007

Temporarily Bypass Popup Blocking in IE7

I read over on ZMan's blog the other day about how he was having some serious issues with downloading VS2008. The list of problems is extensive, but I'll quote a bit of it here:

 

You have to turn off your pop up blocker. "You will also need to allow pop-ups (at least temporarily)." - and they REALLY mean turn it off. You can't ctrl-click. You can't wait for the yellow bar and then say allow it because the site does multiple redirects and so you never get to see the page with the yellow bar. Remember that pop up blocker is ON by default in IE. You would think MS could make this a little easier in their own browser.

 

I rarely use IE myself (preferring Firefox), but I do know a few people on the MSDN team, so I made them aware of it. One of them posted this little workaround on ZMan's blog in response, but I think ZMan has comment moderation turned on and hasn't gotten around to approving the comment yet, so I'll put it here in case it saves someone some grief:

 

From your comments, it sounds like you are running IE7 on Vista.  If this is the case, to temporarily bypass the pop-up blocking functionality of IE7, you need to hold down Ctrl-Alt and click the link (Ctrl-click was how IE6 behaved). 

 

ZMan also had some issues with download location - read the rest of his post for the details. I'll reprint the response to that part here as well.

 

The second issue you had regarding the controlling of where downloads can be saved by an ActiveX control and the message prompts you received is a feature of IE7’s protected mode.  You can adjust these settings by clicking on the “Protected Mode” text in the lower right area of IE7.  Finally, to draw attention to the fact that downloads are being launched with a pop-up, our content team bolded the text on the download control to ensure it stands out a little better.

Friday, November 2, 2007

Simple Filename Wildcarding

I was writing a command-line application for a client the other day, and I found myself wanting to support syntax like this:

 

foobar *.foo *.bar foo*bar

 

which is to say, "run foobar against files that end with .foo, end with .bar, or that start with foo and end with bar." This is a fairly familiar thing for command-line apps to do.

 

One way to approach this is to interpret things like "*.foo" as regular expressions. I don't particularly like this solution, since a) it makes people learn regular expressions to use my app effectively, and b) the common patterns like *.foo don't really work like you want them to - "*.foo" is a regular expression meaning "anything that contains 'foo'" rather than "anything that ends with '.foo'".

 

Another way to deal with this is to use Directory.GetFiles. If you read the documentation, however, there are two issues. The first is that the caveats called out in the notes make the behavior pretty weird. For example, "*1*.txt" matches "LongFileNameHere.txt". Ick. The other issue is that this approach doesn't allow multiple patterns, so I have to scan the directory multiple times and merge the results to do the "*.foo *.bar foo*bar" example above.

 

I hit what I think is a fairly elegant solution, and I wanted to share it with you. The basic idea is to use string.Split, string.Join, and Regex.Escape to create a regular expression that supports exactly one "operator": the asterisk, which matches zero or more of any character. Here's the code:

internal static bool IsMatch(string name, string pattern)
{
// Short-circuit common cases
if (string.IsNullOrEmpty(pattern)) {
return false;
}
if (string.IsNullOrEmpty(name)) {
return false;
}
if (pattern.Equals("*")) {
return true;
}
if (pattern.Equals(name, StringComparison.CurrentCultureIgnoreCase)) {
return true;
}


// Bust the pattern apart at the asterisks
string[] parts = pattern.Split('*');
List patternParts = new List();
foreach (string part in parts) {
patternParts.Add(Regex.Escape(part));
}
// Then put it back together with .*, which matches
// any sequence of characters, and surround it with
// the start-of-string (^) and end-of-string ($) patterns
// so we don't match on things that only start or end
// with what we're after.
string newPattern = "^" + string.Join(".*", patternParts.ToArray()) + "$";
Regex expression = new Regex(newPattern, RegexOptions.IgnoreCase);
return expression.IsMatch(name);
}

Which, I think, is pretty nice, if I do say so myself. Best of all, it has semantics that make it match what I expect file patterns to do.

 

Using it is a simple matter of calling Directory.GetFiles to get all the files in the directory, and then filtering it via a looped call to this method.

 

You'll note that I haven't put in support for the ? operator (match exactly one character), because a) I hardly ever use this myself, and b) it would be pretty simple to bodge in if I ever needed to. It would just take a second call to Split/Join over each patternPart.

 

Hope this helps someone. It was fun to write.