Interesting Issue with eval() and JavaScript JSON

April 23rd, 2009

SquirrelFish.jpg

I was enhancing my web app today based on a request that someone voiced about making it easier to have a user see everything all the time. Face it, there are a good chunk of users that are in the Risk Management group that are going to need to see everything all the time. If I made a permissioning scheme based on an enumerated list, then when I added a new portfolio, I'd have to update these users. Sort of a hassle.

So the request was to have a wildcard for the portfolio list, and when a user had this, they would be able to see all portfolios regardless of how many there were. It's a good idea, I just hadn't thought of it.

But that's not the issue.

What I realized was that there were likely going to be a lot more changes to the permissioning scheme, and in that case, my semi-colon-delimited list of values was not going to do. What I needed was to be able to pass in a fully created JavaScript object and then let the page be able to interrogate it as necessary.

For example, if my validation applet was given a parameter out of json then it might return the following JSON output:

  { username: 'beatyr',
    page: 'PnLTool',
    approved: true,
    portfolios: ['Indexes', 'Nasdaq'] }

then when parsed, I should be able to say things like:

  if (!userInfo.approved) {
  }

Nice.

All this seems well and good, and I should be able to simply say:

  var userInfo = eval(xhr.responseText);

but that won't work. Why? The fact lies in the interpretation of the initial '{' in the string value. The parser in eval() thinks it's the start of a block of code, not a JSON value, so you have to force eval() to get into object evaluation mode by wrapping the JSON in '()'. Like:

  var userInfo = eval('(' + xhr.responseText + ')');

When you put this into the script, it works like a charm. Perfectly understandable from the point of eval(), but a little tricky if you forget about it.

Adding User Permissioning with AJAX

April 22nd, 2009

AJAX.jpg

I got a request for my web app to add in user-based permissioning. Basically, the management wanted to restrict the data any one person in the Shop might see based on their login name. Since I'd already done the user authentication with a signed Java applet, it seemed like a natural extension to add in the portfolios that the individual user could see. I simply change the JavaScript code to parse the response and then went back to the java servlet and added in the database lookup of a new column of data from the database table with the list of usernames.

I decided that it was easiest, for now, to just have a semi-colon-separated list of values, the first would be the YES or NO of the approval, and if YES, then the remainder would be the names of the allowed portfolios for this user. This was taken straight out of the database column.

Like I said, simple.

As I get more requests, I'll probably try to make it JSON and have that allow for the map-like capabilities of the basic JavaScript object. At that time, I'll move to returning JavaScript and then running eval(xhr.responseTest) in the return method. That will make it easier to extend in the future. The only wrinkle is that I'll have to assume that there's a standard variable that the response is coded to, but that's not horrible.

When I got the servlet working, and the simple parsing of the results, I then set about to allow the user to see only that portion of the data that was contained in the portfolio list I'd just parsed. This, as it turns out, was pretty easy.

The first thing I did was to get rid of the repetition in the HTML and JavaScript for all the individual portfolios. There were check boxes, checks on the data, etc. All those needed to be automated and made expandable simply. When I looked at the code, it was pretty simple. Leave all the checkboxes as-is, and create a simple JavaScript array of the names of the portfolios. Then, in the initialChecks() call, use document.getElementById() where the id was the name of the portfolio. Simple.

The tougher part was making the checkboxes disappear when the user shouldn't be able to see their data. The answer was really rather simple: make a div that surrounds the checkbox and name it "div_Portfolio". That way I can make an array of them and get their references by again using document.getElementById('div_' + portfolio). Then, I can make them invisible by:

  // get all the references of the checkboxes and enclosing divs
  var portfolioChecks = [];
  var portfolioDivs = [];
  for (var i = 0; i < portfolioNames.length; ++i) {
    portfolioChecks[i] = document.getElementById(portfolioNames[i]);
    portfolioDivs[i] = document.getElementById('div_' + portfolioNames[i]);
  }
 
  // ...get the list of the available portfolios
 
  // remove the portfolios that the user can't see
  for (var i = 0; i < portfolioNames.length; ++i) {
    if (response.indexOf(portfolioNames[i]) < 0) {
      portfolioChecks[i].checked = false;
      portfolioDivs[i].style.display = 'none';
    }
  }

with this 'turn off, then remove' code, I was able to leave the large part of the app unchanged and it just worked. I was very pleased with the way it turned out.

Now I have something that looks good for all users, and they can see only the data the management wants them to see. Lovely.

Detecting Installed Plug-Ins in JavaScript

April 22nd, 2009

WebDevel.jpg

The support guys at the Shop have asked me if I could detect the presence/absence of the Flash plug-in on the allowed browsers for my web app. Currently, I check for IE and toss it out due to it's horrible JavaScript memory management. I also toss out versions of Firefox prior to 3 for the same reason. But after that, I was letting the browser deal with the existence of Flash and Java applet support. This was a mistake, as a lot of the folks didn't have these and it made for a bad user experience.

So I set about getting the detection code working. It turns out that it's really pretty easy to do because it's all pretty much there in the data within the browser, you just have to know how to parse it up. The method I came up with was part of a browser detection script, as it seemed most logical that I extend that and add methods like BrowserDetect.gotFlash and BrowserDetect.gotJava.

The code looks at the MIME types for the existence of the plug-in and then looks at the list of plug-ins to see if the version matches the minimum versions for my application.

  var BrowserDetect = {
    init: function() {
      // ...checking code for browser, version, and OS
      // check for the Flash plug-in
      this.gotFlash = this.checkPlugin('application/x-shockwave-flash',
                                       'Shockwave Flash', 10);
      // check for the Java Applet plug-in
      if (this.OS == 'Windows') {
        this.gotJava = this.checkPlugin('application/x-java-applet',
                                        'Java Plug-in', 1.6);
      } else {
        this.gotJava = this.checkPlugin('application/x-java-applet',
                                        'Java(TM) Plug-in', 1.6);
      }
    },
 
    // ...more methods...
 
    checkPlugin: function(mime, descKey, minVer) {
      // assume there's no valid plug-in matching these requirements
      var flag = false;
      var plugin = (navigator.mimeTypes && navigator.mimeTypes[mime]) ?
                   navigator.mimeTypes[mime].enabledPlugin : 0;
      if (plugin) {
        var cnt = navigator.plugins.length;
        for (var p = 0; p < cnt; ++p) {
          if (navigator.plugins[p].description.indexOf(descKey) >= 0) {
            var words = navigator.plugins[p].description.split(' ');
            for (var i = 0; i < words.length; ++i) {
              if (isNaN(parseFloat(words[i])))
                continue;
              var pluginVersion = parseFloat(words[i]);
            }
            flag = (pluginVersion >= minVer);
            // no need to check any further
            break;
          }
        }
      }
      return flag;
    },
 
    // ...more methods...
  };
  // initialize this guy so we can be ready to read all the values
  BrowserDetect.init();

With this code, I'm able to use the BrowserDetect.gotFlash call to put out a little notice about downloading the latest Flash plug-in - which is great because I'm not only detecting the existence, I'm also checking the version. This has proven to be a major hassle with Flash as the Google Visualization widget appears to work, but there are subtle things that make it seem broken. It's always been the version of Flash being less than 9. With version 10, we're good to go. That's a load off.

In general, I can see all these AJAX frameworks popping up. If I had known of one that had all this built-in, it'd be really nice. As it's already built, I'll look after-the-fact and if I run across something, I'll look at using it. But I can see why folks write these frameworks, and then use them over and over again.

Great code.

Firefox 3.0.9 is Out

April 22nd, 2009

Firefox.jpg

Once again, we have a 'security and stability' update from the Mozilla crew for Firefox. This time, it's an update to 3.0.9. It's not bad to update my Mac, but at work, on linux, it's a pain as it's an RPM and not allowed to auto-update.

Still... it'd be great for them to get a better JavaScript engine into their code so I can use it freely without crashing on my web app. They will... eventually.

Google Labs Releases Open Source 3D Viewer – O3D

April 22nd, 2009

google-labs-logo.gif

This morning I read about something new out of Google Labs - an Open Source 3D viewer for the browser call O3D. The Mac plugin is at version 0.1.34.2 and while it's still a little rough around the edges, it's got something there that is worth looking into. VRML just hasn't really taken off, and I thought that was going to be a beautiful solution for complex visualizations. It just never found critical mass.

I'm looking at O3D and hoping that with the Google backing, it's going to have a lot better chance of being the web standard for complex, 3D visualizations. I'm not looking for a game engine, or a general drawing package - both those exist built on OpenGL and other technologies. No, I'm looking for the tool to easily represent 3D spaces (real and imagined) so that, for example, the output of a 2D solid-state simulator can be visualized from many angles, etc., using 3D and color. It's a powerful idea.

So I got O3D for my Mac, and we'll see how it evolves. Like I said, it's got a long way to go, but I'm hoping it makes it.

Exciting How Easy AJAX Really is to Work With

April 21st, 2009

WebDevel.jpg

I was working on my web app and I needed to have a simple AJAX call to a servlet to hit the back-end database and verify that the provided username was in a table of authorized users for this app. This wasn't going to be using the Google API, so I had to decide if I wanted to code it up on my own, or use one of the AJAX Frameworks. I looked at the code if I rolled it myself, and decided that it was far easier if I did it myself - considering that I did not have to support IE, so I did.

The result was amazingly simple:

  var username = document.bridgeApplet.getUsername();
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "validate?" + escape(username) + "&page=PnLTool");
  xhr.onreadystatechange = function() {
    // if we're not yet done, skip doing anything
    if (xhr.readyState != 4) {
      return;
    }
    // ...otherwise, look at the response for what I need
    if (xhr.responseText != 'YES') {
      // we can't allow unauthorized access
      var tag = document.getElementById('chart_div');
      tag.innerHTML = '<br/><br/><br/><p class="header">'
            + 'Unknown User</p><br/>'
            + '<p class="reason">The user "' + username + '" is not registered '
            + 'on this application. Please contact the Risk Analytics Team '
            + 'about adding your username to the list of known users.</p>'
            + '<p class="reason">Response: ' + xhr.responseText + '</p>';
    } else {
      // this user was valid, so finish the initialization
      initialize();
    }
  }
  xhr.send(null);

in this little bit, I can issue the URL, track it's progress, and then decode the answer. It's absolutely the most elegant solution I've seen in ages. I'm getting hooked on the AJAX way of doing things and while I wasn't a big fan of servlets, I'm getting there as they are a wonderful way to get into the back-end without having an enormous overhead, and subclassing really works there. Have a nice servlet that does all the database work, and subclass a bunch of servlets off that.

I have to admit, this is changing the way I look at web site building. It's also a lot more fun than the old way.

VoodooPad Pro 4.1.2 is Out

April 21st, 2009

VoodooPad4.jpg

I saw this morning that VoodooPad Pro 4.1.2 was out with a handful of fixes for little bugs that seem to focus primarily on the iPhone app interaction. Since I'm not an iPhone owner, this doesn't really effect me, but I understand that this is where everyone is right now, so I have to deal with it.

Nice to see progress.

Amazing Hoops to Jump Through for the Username

April 20th, 2009

dukeplug.gif

I've been working on the idea of getting the logged in user name into JavaScript so that I can make my little web app allow (and disallow) people without having to resort to JSP pages and login pages with security profiles, etc. Basically, I wanted to get the username, send it to the server for verification, and then if it's OK, show the data, if not, then don't.

I had no idea it was going to be this hard. In retrospect, I should have known, it's not something that Google or Firefox wants to allow as it's a security hole, but come on, folks there are a ton of legitimate intranets where, like us, it'd be ideal to have the username picked off and then used as the basis for simple permissioning. That way, we can use the XP login as the 'rules' for passwords, duration, etc., and if they are logged on, then they have to be who they say they are.

Anyway, I looked at a lot of different techniques. Turns out, the one that's the easiest to do is IE, but that's the one that I can't use because it's got a horrible JavaScript engine, and it's simply not stable enough to use. For IE the JavaScript is as simple as:

  var info = new ActiveXObject("WScript.network");
  alert('user is: ' + info.UserName);

which is a security risk, yes, but it's something that can be handled in the trust system within IE. It's clean, and I wish Chrome and Firefox had been as nice.

For these guys, I had to use a small Java applet. The code was simple enough:

  import java.awt.*;
  import java.applet.*;
 
  public class Bridge extends Applet {
    /**
     * This method returns the user that's logged into the box this
     * applet (and therefore, web browser) is running on. It's a quick
     * way to get a basic authentication going.
     */
    public String getUsername() {
      String  who = "unknown";
      try {
        who = System.getProperty("user.name");
      } catch (Exception e) {
        // any exception means we get the default
      }
      return who;
    }
  }

Because I'm using Tomcat 6, and there are security restrictions on the accessing of things within the WEB-INF directory, I needed to place the source code (notice, there's no package statement at the top of the file) in the root of the src/ directory in the project. The ant target compile would build it, but then deposit it in the directory WEB-INF/classes - no good to leave it there - the browser won't be able to get at it. Additionally, there's no reason to package this one class into a jar file - it can be used as-is, as a .class file - we just need to make it available.

So I made a slight addition to the compile target in my build.xml file:

  <!-- Copy special applet class files to public area -->
  <copy todir="${build.home}">
    <fileset dir="${build.home}/WEB-INF/classes/"
      includes="*.class"/>
  </copy>

so that when all the source java files are compiled into their class files, the ones that do not sit in a package are copied to the root of the web app, and therefore, are publically accessible.

Once we have this all built, we need to have the applet incorporated on the page. Since the class file is at the root of the web app, we can simply say:

  <applet code="Bridge.class" name="bridgeApplet" height=10 width=10>
  </applet>

and then in the JavaScript initialize() method for the page, we can have:

  var username = document.bridgeApplet.getUsername();
  if (username == 'joe') {
    ...
  }

where we're allowing 'joe' to do something, or not, as the logic may be. Unfortunately, we're not all done yet. There's the little problem of the security manager for the Java applets. It's not going to allow us to do this quite yet.

What we need to do is to have a java policy file placed into the 'home' directory on each OS that reads:

  grant {
    permission java.util.PropertyPermission "user.name", "read";
  };

and any other properties you'd like to allow to be read. For this example, it's just the 'user.name', but there are others, and you can add them as you like.

The last trick is where to put this file. On linux, it's easy - 'home' is 'home', and you place it at ~/.java.policy and restart Firefox and you're good to go. The policy file will allow the applet to read the property, the JavaScript will get it from the tiny applet, and everything will be OK.

On Windows/XP it's a little different - C:\Documents and Settings\username\.java.policy but it's the exact same file. Since this is the roaming profile for a user, it's not horrible, and it's only the one property.

This doesn't look like much, but it's taken me several hours on the weekend to come up with ideas that didn't work, and then most of the day today to try to come up with something that actually did work. But, in the end, I have something that works, and I can use the simple approved list in a database to drive who can see the tool. Not bad.

[4/21] UPDATE: I was thinking about this morning, and I really came to the conclusion that the .java.policy file wasn't the right thing to do. It was going to be a lot better if I just created the self-signed certificate and then signed the jar. Then, once they accepted the certificate, they were good to go for all the things I write. Much better.

So, to make the certificate, I did the following in the root of the project I was working on:

  $ mkdir cert
  $ cd cert
  $ keytool -genkey -keystore key.store -alias RATcert -validity 3650
  ...answer questions...

the -validity 3650 says that the certificate should be valid for 10 years (more than enough) and the questions just need to be answered. Don't forget to write down the keystore password and then the alias key password - if it's different from the keystore password.

Now that you have the certificate created, you need to sign the jar. I added the following to the ant target compile in place of the 'copy' action that I mentioned above:

  <!-- Create applet JAR file -->
  <jar jarfile="${build.home}/firecache.jar"
    basedir="${build.home}/WEB-INF/classes/"
    includes="*.class" />
  <signjar alias="RATcert" keystore="${cert.home}/key.store"
    storepass="keystore-password" keypass="cert-password">
    <path>
      <fileset dir="${build.home}" includes="*.jar"/>
    </path>
  </signjar>

where I'd added the property in the build.xml file:

  <property name="cert.home" value="${basedir}/cert"/>

so that I can reference the location of the certificate keystore that I created above.

There's a nasty wrinkle with calling even a signed java applet from an unsigned JavaScript method. Turns out that the security model falls back to the lesser of the two. In this case, it means that even if I sign the jar, I don't get anywhere. What I found was that I needed to add a little code to the Java applet and then everything worked:

  import java.awt.*;
  import java.applet.*;
  import java.security.*;
 
  public class Bridge extends Applet {
    /**
     * This method returns the user that's logged into the box this
     * applet (and therefore, web browser) is running on. It's a quick
     * way to get a basic authentication going.
     */
    public String getUsername() {
      String  who = "unknown";
      who = (String) AccessController.doPrivileged(new PrivilegedAction() {
          public Object run() {
            who = System.getProperty("user.name");
          }
      });
      return who;
    }
  }

The use of the doPrivileged() method seems to be allowing the applet to run at it's security level and not that of the less-secure JavaScript that is calling it. Interesting, but it was a pain to find this one.

The final thing is the change in the applet tag in the HTML to reference the class file in the signed jar:

  <applet archive="firecache.jar" code="Bridge"
    name="bridgeApplet" height=10 width=10>
  </applet>

Note that because the Bridge class file is in the root of the jar file, you don't want to have the ".class" on the end. This makes it possible to deploy the jar as signed and then the user can just accept it and we don't have to have the .java.policy file. This is a lot better.

Handy Tool for Debugging JavaScript

April 17th, 2009

Firefox.jpg

I was trying to find a syntax error I had in my JavaScript today, and realized, once again, that the tools built in to the browsers on Windows/Linux (Firefox and IE) are pretty sad. Sure, Google Chrome has a little more, and Safari 4 beta as well, but I was on linux and that meant Firefox, and it wasn't really helpful.

Then I asked a co-worker, and he said he'd used a Firefox plugin Web Developer to debug JavaScript. So I downloaded it and tried it out. What a difference! This is what I was looking for all along. Something that points out the line with the error and at least some sense of the problem.

WIth this, I was able to diagnose my problem in no time. Thank goodness.

Browser Detection in JavaScript – Interesting Code

April 17th, 2009

WebDevel.jpg

I was working on my web app today and my boss stopped by to say that it was probably a good idea to add in some kind of checking to see what browser is being used and only allow those that we know are stable - Google Chrome and Firefox 3. I was thinking that I'd have to do it in a JSP - take the entire page I'd had and make it a JSP and then do the checking there, but in reality, I can do it all in JavaScript.

I googled around and found this page where a pretty nice version of the browser detection is done. It's simple, fast, extensible, and works perfectly for my needs. Sure, I agree with the page and saying that this is not the best way to make a system cross-browser, but that's not what I'm after. I know which browsers are OK and which ones aren't. And it's got nothing to do with the capabilities - it's the stability of the JavaScript engine. So I really did want something as simple as letting me know the browser and version.

I put this into my code and then simply set the innerHTML value of a div that was to be the graph on the page to a simple paragraph explaining why we weren't able to show the data, and what they needed to do in order to see it. Basically, get Chrome and try again.

It's a pretty sweet little bit of code. Nice to have around.