Last time I wrote about how I switched from Delicious to Google Reader's shared links feature only to find out that week that Google was removing the Google Reader shared links feature in favor of Google Plus social features (I'll save my Google Plus rant for another day).
Forced to find something new again, I'm now very pleased with Tumblr. Google Reader has Tumblr in its preset list of Send To sites which makes it relatively easy to add articles. And Tumblr's UX for adding things lets me easily pick a photo or video to display from the article - something which I had put together with a less convenient UX on my bespoke blogging system. For adding things outside of Google Reader I made a Tumblr accelerator to hookup to the Tumblr Add UX.
Of course they have an RSS feed which I hooked up to my blog. The only issue I had there is that when you add a link (and not a video or photo) to Tumblr, the RSS feed entry title for that link is repeated in the entry description as a link followed by a colon and then the actual description entered into Tumblr. I want my title separate so I can apply my own markup so I did a bit of parsing of the description to remove the repeated title from the description.
From the document: ‘Appendix B. Implementation Report: The encoding defined in this document currently is used for two different HTTP header fields: “Content-Disposition”, defined in [RFC6266], and “Link”, defined in [RFC5988]. As the encoding is a profile/clarification of the one defined in [RFC2231] in 1997, many user agents already supported it for use in “Content-Disposition” when [RFC5987] got published.
Since the publication of [RFC5987], two more popular desktop user agents have added support for this encoding; see http://purl.org/
NET/http/content-disposition-tests#encoding-2231-char for details. At this time, only one major
desktop user agent (Safari) does not support it.
Note that the implementation in Internet Explorer 9 does not support the ISO-8859-1 encoding; this document revision acknowledges that UTF-8 is sufficient for expressing all code points, and removes the requirement to support ISO-8859-1.’
Yay for UTF-8!
Shortly after joining the Internet Explorer team I got a bug from a PM on a popular Microsoft web server product that I'll leave unnamed (from now on UWS). The bug said that IE was handling empty path segments incorrectly by not removing them before resolving dotted path segments. For example UWS would do the following:
A.1. http://example.com/a/b//../
A.2. http://example.com/a/b/../
A.3. http://example.com/a/
In step 1 they are given a URI with dotted path segment and an empty
path segment. In step 2 they remove the empty path segment, and in step 3 they resolve the dotted path segment. Whereas, given the same initial URI, IE would do the following:
B.1. http://example.com/a/b//../
B.2. http://example.com/a/b/
IE simply resolves the dotted path segment against the empty path segment and removes them both. So, how
did I resolve this bug? As "By Design" of course!
The URI RFC allows path segments of zero length and does not assign them any special meaning. So generic user agents that intend to work on the web must not treat an empty path segment any different from a path segment with some text in it. In the case above IE is doing the correct thing.
That's the case for generic user agents, however servers may decide that a URI with an empty path segment returns the same resource as a the same URI without that empty path segment. Essentially they can decide to ignore empty path segments. Both IIS and Apache work this way and thus return the same resource for the following URIs:
http://exmaple.com/foo//bar///baz
http://example.com/foo/bar/baz
The issue for UWS is that it removes empty path segments before resolving dotted path segments. It must
follow normal URI procedure before applying its own additional rules for empty path segments. Not doing that means they end up violating URI equivalency rules: URIs (A.1) and (B.2) are equivalent
but UWS will not return the same resource for them.
I wanted to ensure that my switch statement in my implementation of IInternetSecurityManager::ProcessURLAction had a case for every possible documented URLACTION. I wrote the following short command line sequence to see the list of all URLACTIONs in the SDK header file not found in my source file:
grep URLACTION urlmon.idl | sed 's/.*\(URLACTION[a-zA-Z0-9_]*\).*/\1/g;' | sort | uniq > allURLACTIONs.txt
grep URLACTION MySecurityManager.cpp | sed 's/.*\(URLACTION[a-zA-Z0-9_]*\).*/\1/g;' | sort | uniq > myURLACTIONs.txt
comm -23 allURLACTIONs.txt myURLACTIONs.txt
I'm
not a sed expert so I had to read the sed documentation, and I heard about comm from Kris Kowal's blog which happilly was in the Win32 GNU tools pack I
already run.
But in my effort to learn and use PowerShell I found the following similar command line:
diff
(more urlmon.idl | %{ if ($_ -cmatch "URLACTION[a-zA-Z0-9_]*") { $matches[0] } } | sort -uniq)
(more MySecurityManager.cpp | %{ if ($_ -cmatch "URLACTION[a-zA-Z0-9_]*") { $matches[0] } } | sort -uniq)
In
the PowerShell version I can skip the temporary files which is nice. 'diff' is mapped to 'compare-object' which seems similar to comm but with no parameters to filter out the different streams
(although this could be done more verbosely with the ?{ } filter syntax). In PowerShell uniq functionality is built into sort. The builtin -cmatch operator (c is for case sensitive) to do regexp is
nice plus the side effect of generating the $matches variable with the regexp results.
When you run clip.exe, whatever comes into its standard input is put onto the clipboard. So when you need to move the result of something in your command window somewhere else you can pipe the result into clip.exe. Then you won't have to worry about the irritating way cmd.exe does block copy/pasting and you avoid having to manually fixup line breaks in wrapped lines. For instance, you can put the contents of a script into the clipboard with:
more cdo.cmd | clip
I've got a lot of stuff dumped in my bin folder that I sync across all my PCs so I didn't realize that clip.exe is a part of standard Windows installs.
Nice for avoiding the block copy in cmd.exe but I'd prefer to have the contents sort of tee'd into the clipboard and standard output. So TeeClip.ps1:
$input | tee -var teeclipout | clip;
$teeclipout;
I'm trying to learn and use PowerShell more, but plenty of other folks I know don't use PowerShell. To allow them to use my scripts I use the following cmd.exe batch file to make it easy to call
PowerShell scripts. To use, just name the batch file name the same as the corresponding PowerShell script filename and put it in the same directory.
@echo off
if "%1"=="/?" goto help
if "%1"=="/h" goto help
if "%1"=="-?" goto help
if "%1"=="-h" goto help
%systemroot%\system32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -Command . %~dpn0.ps1 %*
goto end
:help
%systemroot%\system32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -Command help %~dpn0.ps1 -full
goto end
:end
Additionally for PowerShell scripts that modify the current working directory I use the following batch file:
@echo off
if "%1"=="/?" goto help
if "%1"=="/h" goto help
if "%1"=="-?" goto help
if "%1"=="-h" goto help
%systemroot%\system32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -Command . %~dpn0.ps1 %*;(pwd).Path 1> %temp%\%~n0.tmp 2> nul
set /p newdir=
I used FiddlerCore in GeolocMock to edit HTTPS responses and ran into two stumbling blocks that I'll document here. The first is that I didn't check if the Fiddler root cert existed or was installed, which of course is necessary to edit HTTPS traffic. The following is my code where I check for the certs.
if (!Fiddler.CertMaker.rootCertExists())
{
if (!Fiddler.CertMaker.createRootCert())
{
throw new Exception("Unable to create cert for FiddlerCore.");
}
}
if (!Fiddler.CertMaker.rootCertIsTrusted())
{
if (!Fiddler.CertMaker.trustRootCert())
{
throw new Exception("Unable to install FiddlerCore's cert.");
}
}
The second problem I had (which would have been solved had I read all the sample code first) was that my changes weren't being applied. In my app I only need the BeforeResponse but in order to modify the response I must also sign up for the BeforeRequest event and mark the bBufferResponse flag on the session before the response comes back. For example:
Fiddler.FiddlerApplication.BeforeRequest += new SessionStateHandler(FiddlerApplication_BeforeRequest);
Fiddler.FiddlerApplication.BeforeResponse += new SessionStateHandler(FiddlerApplication_BeforeResponse);
...
private void FiddlerApplication_BeforeRequest(Session oSession)
{
if (IsInterestingSession(oSession))
{
oSession.bBufferResponse = true;
}
}