Thursday, August 30, 2012

Cookies, Cross-site Scripting, etc..

This blog:
http://lcamtuf.blogspot.com/2010/10/http-cookies-or-how-not-to-design.html
has the most succinct description of cookies and the problems with web browsers that I have ever seen.

makefile:10: *** missing separator. Stop.

I almost always use spaces instead of tabs because everyone's text editor interprets a TAB differently, so I map TAB to be a number of SPACEs. I spent about 20 minutes trying to figure out why "make" was generating an error of "missing separator". The answer is here:
 CC = $(CROSS_COMPILE)gcc-4.6.1
 LD = $(CROSS_COMPILE)ld
make requires TABS, and I had tabs converted to spaces.
<--tab-->CC = $(CROSS_COMPILE)gcc-4.6.1
<--tab-->LD = $(CROSS_COMPILE)ld
Sheesh...

Saturday, August 25, 2012

XMLHttpRequest doesn't work on IE, and the fix.

I was working on a website that needed content from another site using AJAX. The site worked fine in chrome, safari, but not IE 9. IE just threw errors without any real information. The issue was a cross-site exception. In this case, the content was JSON information from graph.facebook.com. Even if you have your application inside a facebook iframe, Internet Explorers XMLHttpRequest implementation will not allow calls to graph.facebook.com because it is a cross-site call.

Here's the short list of what you need to keep in mind to get it working:
  • 1. No mixed content
    If your website is https, all calls must be https. Even though it is faster to use http://graph.facebook.com, the fact that facebook enforces https means that you must makes calls to https://graph.facebook.com if you want the information from it. I fixed this by having Javascript check to see if the browser was IE, and then did a passthrough from the hosting server via PHP.
  • 2. No Callback for Null Returns!
    If you do an AJAX callback, the callback will not run if request.responseText is "". So, you cannot use a null response a trigger for a function, even if the status is good.
  • 3. You need to use ActiveX
    You need to check to see if you are using IE, and if you are, you need to explicitly load XMLHttpRequest from ActiveX because the build-in one does not work the same! (on IE 9)
  • 4. IE caches everything
    What I mean by this is that it aggressively caches everything. As an example, if you have a file called test.php?id=10 that returns data that is changing, IE will only get it once unless you explicitly have expiry assignments in the headers.

The following is what worked for Javascript:
function getInternetExplorerVersion()
// Returns the version of Internet Explorer or a -1
// (indicating the use of another browser).
// http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx
{
  var rv = -1; // Return value assumes failure.
  if (navigator.appName == 'Microsoft Internet Explorer')
  {
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  return rv;
}

function ajax(url, callbackFunction, p_targetid) {
    "use strict";
    var str_err, request, errorcode, isIE, newurl, done, ok, url_alt, a_url, fbid, tmp; 
    request = false;
    if(getInternetExplorerVersion() === -1)
    {
      request=new XMLHttpRequest();
    } else {     
       if(!request)
       {
         try{
         request=new ActiveXObject("Msxml2.XMLHTTP.6.0"); 
        try { 
        request=new ActiveXObject("Msxml2.XMLHTTP.3.0"); 
        } catch(e) { request=false;
        }
         }catch(e) { request=false;
    } 
       //here we need to change our forwarding options to go off site.
    if (url.indexOf("https://graph") == 0) {
         a_url = url.split("/")      
         tmp = a_url.length;
         tmp = tmp - 1;
         fbid = a_url[tmp];
         url_alt = '/forwardrequest.php';
         url_alt = url_alt.concat('?fbid=',fbid);
         url = url_alt;
       }
     } 
     }

  request.open("GET", url, true);
  request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  request.onreadystatechange = function () {
    done = 4;
    ok = 200;
    if (request.readyState === done && request.status === ok) {
      if (request.responseText) { callbackFunction(request.responseText, p_targetid); }
    }
  };
  request.send();
}

Notice where forwardrequest.php is the fix for IE calls offsite, in this case, JSON information. Most of the sites users are non-IE, so the burden is then completely on the browser, but you need to be mindful of hitting forwardrequest.php so much, so implemented a caching scheme for my calls to it in Javascript. That is not included here.

The forwardrequest.php that worked for me:
<?php
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

function getFBPublicInfo($p_userid)
{
  $url  = "http://graph.facebook.com/$p_userid";
  $array_json = json_decode(file_get_contents($url),true); //true is important to make it an array
  return($array_json);
}
if($_GET["fbid"])
{
  $p_userid = $_GET["fbid"];
  $url  = "http://graph.facebook.com/$p_userid";
  $result = file_get_contents($url);
  $result = getFBPublicInfo($p_userid);
    $i = count($result);
    $i = $i -1;
    $j = 0;
    echo "{\n";
    while (list($key, $value) = each($result)) {
        echo "  \"$key\": \"$value\"";
        if($j==$i)
        {
            echo"\n";
        }else
        {
            echo",\n";
        }
        $j++;
    }
echo "}\n";
}
?>
I have to explicitly build a JSON structure because the special characters were being stripped, so I just did a JSON decode and then rebuilt it.
I am just happy to be finished, and this is a reminder why I do not do web programming unless a friend asks. It's only worth it if you aren't billing because these silly things can take forever.

Tuesday, August 21, 2012

The relationship funciton.

I just had a relationship described in chat as:
function Settling(personA, personB) 
{ 
if(personA.loves(personB) && personB.loves(personA) && 
personA.willingto(SACRIFICE|COMPROMISE|LISTEN|FORGIVE) == true &&
personB.willingto(SACRIFICE|COMPROMISE|LISTEN|FORGIVE) == true && 
personA.wants(personB.happy()) && personB.wants(personA.happy()))
{ return(false);} else {return(true);} 
}
This is why women do not like to date computer scientists...

Thursday, August 16, 2012

Working the system...

Academics love to work the system, particularly when they already know the answer.
I read http://www.tgdaily.com/space-features/65458-helium-found-in-moons-atmosphere and this quote:

"The question now becomes, does the helium originate from inside the moon, for example, due to radioactive decay in rocks, or from an exterior source, such as the solar wind?" says Dr Alan Stern, LAMP principal investigator.

...pretty much sums it up. The only viable reason to go to the moon economically is to retrieve He-3, and we know that the moon has abundant supplies of helium. Here's to you for answering the answered questions Dr. Alan Stern.
(shrug)

Wednesday, August 15, 2012

Javascript Loops

Something that I have been doing recently looks very much like a run loop for a video game. I load things in a sequence to give the illusion of speed on a webpage. This blog had a nice writeup. In the same way as having a redraw in a game, you can have a loop to check user input and get local updates. Mine were on the order of seconds, but it worked really well.

Saturday, August 11, 2012

101 ways to start a fight

I now know the the author of: A Hundred and One Ways to Start a Fight by "an Irish gentleman whose name eludes me for the moment".
It is a Mr. Taylor. Way to go Katie!

If one must be internationally famous for fighting, you might as well be from Ireland.