Now Internet Explorer won’t even confess to being Internet Explorer

liar

The bizarre world of Internet Explorer never ceases to amaze me. Today’s revelation – Internet Explorer 11 doesn’t even like to admit that it’s Internet Explorer.

When a web browser visits a web site, it identifies itself to the web site with a string of information that contains various elements that say to the web site “hey, I’m here, this is the type of web browser I am, my version, operating system”. It’s known as the user-agent string.

In the past the user-agent string for Internet Explorer would look something like this:

Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)

The ‘MSIE’ stands for Microsoft Internet Explorer, so pretty easy to work out which browser is visiting your web site.

Today I was wondering why I could not teach some web site code to recognise it was being visited by IE, did a little research and came up with this page of explanation from Microsoft.

Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko

What’s missing? The ‘MSIE’ of course!

If I was using Firefox, the string would say FIREFOX, like this:

MOZILLA/5.0 (MACINTOSH; INTEL MAC OS X 10.8; RV:26.0) GECKO/20100101 FIREFOX/26.0

Safari would say ‘SAFARI’, and Chrome would, well now there’s the rub, because Chrome can say CHROME as well as SAFARI:

MOZILLA/5.0 (MACINTOSH; INTEL MAC OS X 10_8_5) APPLEWEBKIT/537.36 (KHTML, LIKE GECKO) CHROME/32.0.1700.77 SAFARI/537.36

Remind me again why I got into this web development malarky?

word-wrap: break-word CSS for long text options in drop down select lists

CSS+HTML

A quirk I ran across yesterday with CSS on a drop down list. The list is disabled and has a width fixed with CSS and is contained in a table cell. The selected option text is wider than the fixed width of the list.

<table class="grid_table_new">
  <tbody>
    <tr>
      <td><select style="width:130px;" disabled="disabled" >
          <option value="47" selected="selected">Traditur Preascep irruit. Sed now possum Non adamare te. Maneam</option>
        </select></td>
    </tr>
</table>

When viewed in the browser the list looks like as you would expect:

Screen Shot 2013-12-21 at 8.55.42 AM

Except someone showed me their screen, and it looked different:

Screen Shot 2013-12-21 at 9.00.08 AM

As you can see, the drop down has expanded vertically to display the entirety of the option text. I tested this page in a bunch of browsers and found this  was only happening in a couple of browsers:

  • Chrome (Win) – YES
  • FF (Win) – no
  • Safari (Win) – YES
  • IE11 – no
  • Chrome (Mac) – no
  • FF (Mac) – no
  • Safari (Mac) – no

After a significant amount of poking around in a large amount of CSS I finally tracked it down to this piece of CSS:

table.grid_table_new td, table.grid_table_new th {
	word-wrap: break-word;
}

word-wrap has been around for a while but from what I can tell is not officially applicable to options in a select list, it’s designed to help when formatting blocks of text on a page, and has now been renamed to overflow-wrap, which now seems to be supported by current browsers. I tried swapping the existing property to overflow-wrap – same outcomes though.

It seems this is a quirk of Chrome and Safari on Windows (note, NOT on Mac). And given it’s impossible to specific that my customers should use one of those browsers clearly we need an alternative solution to cope with these long text options. Thankfully JQuery gives us choices, such as this plugin.

puTTY SSH connections dropping when on wifi instead of ethernet

04082-fart-putty

I use puTTY to create SSH tunnel connections to servers, and usually have the connection up all day. Recently I’ve been plagued with puTTY losing the connection every 15 or 20 minutes – all because I moved to wifi instead of a wired connection. It’s because I bought a new MacBook Pro, which doesn’t have a standard ethernet port, a small fact I didn’t realise so I didn’t buy an adaptor. Plus my family was probably becoming a little bored with the blue network cable hanging down the stairs from our cable router to my study – makes the place look untidy.

I already had keep alives configured in puTTY:

Screen Shot 2013-11-06 at 9.19.46 AM

After some research I came across this post ‘Why Windows 7 / PuTTY drop TCP connections even on very brief outages?‘ which seemed to mirror my own experience to some extent.

I took a look at my Windows registry, and did not see the TcpMaxDataRetransmissions parameter, so added it in with a value of 15 (the superuser post suggests 15, the linked FAQ on the puTTY web site says 10).

2013-11-06_09-22-55

With this change my connection remained up for a couple of hours, and then died, a darn sight better than the previous habit of dropping a couple of times every hour – except this time puTTY doesn’t report the connection as dropped, it looks fine, I just can’t reach anything at the other end of the tunnel.

I decided to fiddle with the puTTY keepalive, and changed it from 30 seconds to 15 seconds, over the past day or two I’m seeing 3 or 4 hours uptime. Interestingly, I only notice when I try to connect to a server and receive a timeout message, previously puTTY would say it was disconnected, now it seems to think the session is still current.

All in all good progress. When I have some time I’ll play with the configuration some more. I haven’t even got to looking at whether there is a setting on my  wifi router that might be to blame.

Send file data via JSON from REST API and open as download file in browser (with Classic ASP/JQuery)

Pet project challenge of the day. I have a REST API that delivers a JSON response, and I want it to include file data, so the browser at the client end can download the file. In real world what I’m doing is offering a link to the user to export some data to an XLS and download to their desktop.

I messed around with this for a while. Carriage of the file data seemed simple – at the REST end encode it to base64 and stick that into the JSON. The problem lies at the client end. I have JQuery calling the REST, and dealing with the response. How then to get the base64 out of the JSON and contrive to offer it as a File Save As situation?

Finally here’s what I came up with, it was sparked by something I saw on StackOverflow, although I cannot lay my hands on the post right now:

At the REST, encode the XLS file text to base64, and return the base64 in the JSON as a text element

On the client, I have an ASP script that acts as the controller, it receives requests from the pages (eg JQuery calls this page), then it calls the remote REST, and returns the response back to JQuery. Obviously cross-browser rules means my JQuery can only call URLs on the same domain, and my REST is not. So this script acts as the transporter for the calls. It’s even called Frank.

On the page I have a form with a hidden field, JQuery puts the base64 file data into that hidden field, then submits the form to another page.

<form id="base64Form" action="openFileToBrowser.asp" method="post" name="base64Form">
<input id="base64data" type="hidden" name="base64data" value="" />
<input id="fileName" type="hidden" name="fileName" value="responses.xls" />
</form>

This new page grabs the file data, decodes it from base64 back to text, sets the content headers to XLS etc. And hey presto, the user gets a File Save As dialog. Here’s the code on that page:

<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<% Option Explicit%>
<% response.expires = 0 %>
<!--#include virtual="/includes/hex_sha1_base64.asp" -->
<%
	dim base64data
	base64data=request.form("base64data")
	if base64data<>"" then
	Response.ContentType = "application/vnd.ms-excel"
	Response.AddHeader "Content-Disposition", "attachment; filename="&request.form("fileName")
	response.write Base64_Decode(base64data)
	response.Flush()
	end if
%>

The base64 encode/decode routine I’m using is part of the very handy hex_sha1_base64.asp file which I also use for other encryption and encoding tasks (for example I use it for encryption as part of talking to OAUTH based APIs).

I haven’t tested this in all browsers yet, be interesting to see if kicks up problems with IE etc.

nvarchar(max) doesn’t work on Azure SQL with Classic ASP

stress

This is one of those completely obtuse issues that one hits from time to time – nvarchar(max) fields behave oddly on Microsoft Azure SQL – yet it all works fine on SQL Server 2008 on my local machine.

I battled this for an hour before finally simultaneously figuring out that trying to return data from an nvarchar(max) column via Classic ASP on Azure yields a blank value (or weird binary garbage); and falling over someone else who’s had exactly the same problem recently.

It’s fine to have a table with nvarchar(max) in Azure. I can push data into it, I can see the data via SSMS, but returning via ASP – nada.

I’m returning the data via a UDF, so I altered the table definition returned from the function so the column is nvarchar(4000). My function grabs the data from the (max) column and sticks it into the output column without trouble, and the function returns values fine, don’t even need a CAST.

It’s frustrating because I’m anticipating these columns to hold large blocks of text, and now I’m size restricted.

I haven’t had time to explore whether messing with the connection strings might do the trick.

Clean up double line spacing in Dreamweaver code

Adobe_Dreamweaver_CS6_Icon

I work across Mac and Windows, with Dreamweaver running on my Mac, and code that sometimes will be hosted on Windows Servers and sometimes not. So I often run into the problem of erratic line spacing. If I have code saved on my Mac HDD (as opposed to my Windows VM), push it up to a Windows Server, then pull it down again, I sometimes wind up with the code double spaced when I open the file again in Dreamweaver.

I finally tracked down a quick solution to clean up these pages, with grateful thanks to this page: Permanently Remove Double Space in Dreamweaver Code View.

Do a search and replace:

  • Search for: [\r\n]{2,}
  • Replace with: \n

Make sure you have the Use Regular Expressions option checked.

Of course, it’s also good to make sure you have the Line Beak Type set correctly under Dreamweaver’s Preferences, but I’ve found that doesn’t really help when you are working cross-platform.

Create Twitter-like REST API endpoints with IIS URL rewrite

Twitter’s REST API uses endpoints that look like this:

http://www.domain.com/[object]/method.json

In addition for GET request you can append parameters like this:

http://www.domain.com/[object]/[method].json?param1=a&param2=b

So for example a call to the Twitter REST might look like this:

https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=davideedle&count=2

I wanted to try and reproduce this format with a REST API I’ve been playing with, so I spent some time figuring out how to configure IIS URL rewrite to handle these URLs and deliver the parameters to an ASP page.

You’ll need IIS rewrite installed, in IIS Manager you should see the ULR rewrite icon if you click on a website, for example:

Screen Shot 2013-09-23 at 11.30.31 AM

If the icon is not there download and install URL rewrite extension from the Microsoft website, then open URL Rewrite and add a new Inbound Rule.

Here’s the regular expression pattern I came up with:

^rest/v1/([^/]*)/([^/]*)\.json$

With the Rewrite URL of:

rest/v1/?objectTypeName={R:1}&objectMethod={R:2}

This means that a URL like this:

http://www.domain.com/myObject/myMethod.json?param1=a&param2=b

Will pass the parameters into my ASP page like this:

objectTypeName = myObject
objectMethod = myMethod
param1 = a
param2 = b

You need to make sure you have the “Append query string” option checked for the Rule so the additional parameters (eg param1 and param2) are passed through the rewrite.

Source Control Window disappears in Visual Studio 2012

2844.VS_tm_Purp526_rgb

A little weirdness with Visual Studio 2012 – the Source Control Window disappeared and nothing seemed to bring it back. I could open a solution from the Recent list, and open a file from the Solution, but still no Source Control Window would launch or display. And View -> Other Windows -> Source Control Window did nothing.

All until a colleague pointed out that, if you watched closely, it seemed like the window was loading, just not visible. So we tried Window > Reset Window Layout and all was well.

Drove me crazy for 15 minutes – and the simplest solution turned out the right one.

Select a random record with SQL server

Easy little trick, if you need to select a random record with SQL server as part of a query:

SELECT TOP 10 column,column FROM table ORDER BY newId()

Or could do:

SELECT TOP 10 percent column,column FROM table ORDER BY newId()

This is not brilliant for very large data sets, you can use TABLESAMPLE, for example:

SELECT column, column FROM table TABLESAMPLE (10 PERCENT)

Or:

SELECT column, column FROM table TABLESAMPLE (100 ROWS)

There is  caveat with TABLESAMPLE, it’s not fabulously random – and the number of rows returned may not match what you asked for, especially with small values, so if you ask for 10 records you might get back 20. And if you ask for 5 you might not see anything returned at all. I’m not entirely sure I’ve completely wrapped my head around TABLESAMPLE, you can read more on MSDN. But newId() is something I use all the time, and I’d stick with that unless you find your data set is large and the query is slow.

Convert decimal/dotted IP number to hex string

I had need today to pull a bunch of IP numbers from a database and return them as hex strings from a query to my code. It took a little messing, but finally figured out a solution.

DECLARE @b varchar(30) SET @b = '64.233.160.0'

SELECT 
RIGHT(CONVERT(varchar(max), CONVERT(VARBINARY(4), CAST(PARSENAME(@b, 4) AS int)), 2),2)
+
RIGHT(CONVERT(varchar(max), CONVERT(VARBINARY(4), CAST(PARSENAME(@b, 3) AS int)), 2),2)
+
RIGHT(CONVERT(varchar(max), CONVERT(VARBINARY(4), CAST(PARSENAME(@b, 2) AS int)), 2),2)
+
RIGHT(CONVERT(varchar(max), CONVERT(VARBINARY(4), CAST(PARSENAME(@b, 1) AS int)), 2),2)

The above returns ’40E9A000′. Breaking it down:

— gives me the first octet as an integer

CAST(PARSENAME(@b, 4) AS int)

— converts the integer to a hex literal

CONVERT(VARBINARY(4), CAST(PARSENAME(@b, 4) AS int))

–converts the hex literal to a string

CONVERT(varchar(max), CONVERT(VARBINARY(4), CAST(PARSENAME(@b, 4) AS int)), 2)

–grabs the right hand 2 characters of the hex string

RIGHT(CONVERT(varchar(max), CONVERT(VARBINARY(4), CAST(PARSENAME(@b, 4) AS int)), 2),2)