Stat Tracker

Monday, January 24, 2011

SQL / SOQL Injection

This past weekend I was hanging out with some friends and we came up on the topic of SQL injection. Yeah, we are nerds. Anyway, I was giving my buddy a hard time because he wasn't parametizing his SQL statement in PHP. Really I didn't even dig in his code that much, just glanced at it and wanted to give him a hard time since I was stressed about the Bears game. And for good reason, since we lost! Ah, but its all in good fun!

Anyhoot, I've played around in a lot of languages, but not PHP. There was some minor back and forth about this as another buddy shared his thoughts. I stated that I've never seen any language or database that takes a query and automatically escapes it for you once you call it. The standard defense against SQL injection that I've always used, and most often seen implemented in production has been SQL parametrization.

My friend stated that in PHP you can call built in escape string function on the SQL string and it will take care of it for you.  (Note: You can't escape the whole query string, you have to escape each individual input field and then use those escaped string in the query string).

I stated that generally as a developer you want to prevent SQL injection by using parametrization or persistence frameworks if possible. This set off some discussions, and then the Bears game got started so the discussion kind of died as my heart rate ramped up for the (disappointing) game. However, during lunch today I decided to write up on the topic.

You can checkout the SQL Injection wikipedia entry here, parametrization is the first method recommended. Escaping strings is also mentioned as a solution for PHP, although the ability to forget to escape a field makes this method error prone and cumbersome. Another SQL Injection site here recommends using escape string methods only when necessary as it creates frail code.

In Java using straight JDBC drivers you usually use parametrization of the query AKA prepared statements. (Java noobs click here). Some persistence frameworks like Hibernate will take care of parametization for you by default, but are still vulnerable to additional injection attacks you need to guard against. If your a glutten for pain your probably an Adobe Flex developer, and you also parametrize the SQL query. Shiver. I'm not a fan of developing in Adobe Flex. I spent about 6 months working with it and decided it wasn't for me!

In Force.com, we use parametization by using the bind ( :varName) ability of SOQL in Apex. Per the Force.com Documenation, "To prevent a SOQL injection attack, avoid using dynamic SOQL queries. Instead, use static queries and binding variables. "

For example:

List<String> idList = new List<String>{'XXXXXXXXX','YYYYYYYYY','ZZZZZZZZZZZ'};
List<Account> accounts = [Select Id, Name from Account where Id in :idList];

You can escape the user input, per Force.com documentation "If you must use dynamic SOQL, use the escapeSingleQuotes method to sanitize user-supplied input.". But they strongly recommend parametrization of queries.

Furthermore, Salesforce and Apex developers should be using the Force.com Security Scanner to check their code base for security holes like SOQL injection. Using the scanner is very easy, all you need to do is provide your login address to the security scanner at http://security.force.com/sourcescanner. It will automatically generate a pretty sweet code analysis report in PDF format and email it to your email address associated with the login address. It also gives you the solution on how to re-factor your code to solve the hole, which saves you time researching the solution. Pretty slick!

Tuesday, January 18, 2011

Using Visual Flow in Salesforce Spring 11

NOTE: As of Spring 12 all Orgs will have Visual Flow for FREE! SWEET! Also, this post is a little old, there is already an update with the new Cloud Flow Designer.

You know what can be tedious to work with? Wizards. And I’m not talking about wizards like Gandolf who can shoot lighting and carry swords with a +10 mana regeneration rate.  I’m talking about wizards that navigate a user through a flow or decision making process. Many programming languages and platforms provide setup wizards in their IDE’s that allow you to create a wizard framework quickly. This frees the developer from manually creating all the framework code to build one. 

As of Salesforce Winter 11, this was something that was lacking in Salesforce and Force.com platform.

You’d have to manually create a bunch of Visualforce Pages and Apex Controller and flow the user through them manually, which was a pain!

In Spring 11 however, we are getting Visual  Flows GA (Generally Available). This was previously available in Pilot for Winter 11 release under the name “Visual Process Manager”. This allows you to build business processes quickly by drag, dropping, and connecting items in the Flow Designer tool. In my Spring 11 Release org I’ve been playing around with it and it’s pretty sweet. You can even invoke Apex methods from the flows for reusable / complex logic.

Use Case: New Account Wizard

This use case will create a new account using the Visual Flow tool. To create a Visual Flow, we need to do a few things first. 
  1. Gain access to a Salesforce Pre-Release Spring 11 Org. https://www.salesforce.com/form/signup/prerelease-spring11.jsp
  2. Enable the user as a “Force.com Flow user”. You can access this in Setup -> Manage Users -> Edit A user. Check the “Force.com Flow User” box.
  3. Download the Flow Designer tool from Developer Tools and install. You can access this in Setup -> Create -> Workflows & Approvals - > Flows. The download link is on the screen.
Once we have our environments setup and our user configured as a Flow user, we can create a flow. I recommend following the User Manual PDF provided in the Flow Designer tool to learn how to create a beginning flow (Help -> User Manual). It contains a pretty decent quick tutorial, but it’s a little lightweight. For example, the flow tutorial only provides a flow which does a calculation. It does not utilize the Lookup or Update elements which are critical to a lot of workflows. But it does introduce you to the concepts.

After following the tutorial, I updated my flow to use the Data Update element and the Send Email element to perform an Account insert as well as email me a confirmation email that the account was created. I am including my test flow file so you can use it in your org. 

You can grab the complete test flow file here: Google Code - TestFlow File.

When I finished, my flow looked like this in the Flow Editor:


To test this flow, I created a homepage component that linked to the flow allowing the user to execute it from their homepage. As you can see, the flow will execute in a new window and the user can go through the generated screens and create a new Account.

1. User clicks the Homepage Component to execute the wizard:
 2. Wizard starts up and user goes through the prompts to create the record.


And finally we can see the account record created in the Accounts Detail Page:

You can also embed these flows inside Visualforce Mashups so maybe I’ll play around with that next.

Overall, this is pretty exciting for developers and even administrators of Salesforce. I can see a lot of efficiency by building all sorts of custom wizards quickly using this tool. This will probably be heavily utilized in all those call center applications. 

Friday, January 14, 2011

Generating a Barcode in a Visualforce Page using Javascript

You can generate a barcode in a Visualforce Page using Javascript pretty easily. Some folks forget that you can execute Javascript in a Visualforce page. This opens you up to a lot of the goodies you can do with the client browser.

The trick is to find the right Javascript library which provides the type of barcode you want to generate, or you could always write your own.

At a highlevel, the steps you need to do are:

1. Upload a JS Library (someJSLib.js) to your Static Resources in Salesforce.
2. Reference the JS Library in your Visualforce page by using the <apex:includeScript> tag.
3. Execute the Javascript functions to generate the barcode content and display in your page.

For this example, I am using a Barcode 39 Javascript library provided by http://www.codeproject.com/KB/HTML/Code-39-Barcode.aspx.

1. First I upload the JS Library to my Static Resources:
  

2. After I have uploaded the library, I embed the JS file in my VF Page using the <apex:includeScript> tag:
<apex:includeScript value="{!$Resource.BarcodeScript}"/>

3. I execute javascript in the Visualforce page to generate the barcode (Full VF Page Code):
<apex:page standardController="Position__c">
    <apex:includeScript value="{!$Resource.BarcodeScript}"/>
    <apex:detail relatedList="false"></apex:detail>
    <br/>
    <br/>
    <div id="inputdata">{!Position__c.Name}</div>
    <div id="externalbox" style="width:5in"></div>
    <script type="text/javascript">
    /* <![CDATA[ */
      function get_object(id) {
      alert('Executed');
       var object = null;
       if (document.layers) {
        object = document.layers[id];
       } else if (document.all) {
        object = document.all[id];
       } else if (document.getElementById) {
        object = document.getElementById(id);
       }
       return object;
      }
      get_object("inputdata").innerHTML=DrawCode39Barcode(get_object("inputdata").innerHTML,1);
     /* ]]> */
    </script>
</apex:page>


4. When I view this page it will take the Name field from my Position__c object and encode it in the Barcode:

That's all it takes!

The only challenging part really is finding JS Libraries that are opensource and support your barcode format.

Here are some websites that have JS Libraries available:

EAN-13: http://www.parkscomputing.com/barcode.html
Barcode 39: http://www.codeproject.com/KB/HTML/Code-39-Barcode.aspx
Barcode 39: http://www.atalasoft.com/cs/blogs/loufranco/archive/2008/04/25/writing-code-39-barcodes-with-javascript.aspx

Monday, January 10, 2011

Salesforce Spring 11 Release Update - Governor Limits

I just finished reading the Salesforce Spring 11 Release Notes and I am floored by the new Force.com updates. Some of my most frustrating headaches are getting alleviated. Not completely eliminated, but alleviated by a huge amount.

When I first started working on the Force.com Platform, coming from a J2EE background, I was instantly frustrated with the governor limits enforced on Apex code. Only 1000 records in all my SOQL queries in a Trigger context? Only 20 DML statements? It has been the most frustrating part of an otherwise simple development platform.

Well, in Spring 11, we are getting some huge updates!

First, all Apex code will now execute in a single context. Previously we had two context (Trigger, and Anonymous/Controller/Everything Else). These two context had their own governor limits, with the Trigger context being the most restrictive. Well, not anymore! All Apex code will now execute in one context! WOW.

And if thats not all, there's more!

Secondly, the total number of records in a context's SOQL queries has increased to 50,000! Yeah, 50,000! Previously in a Trigger you could only get 1,000. Thats 50 times the number of records!

Oh, and almost forgot. Full REST API is generally available!

Man, what an awesome release for developers.

Check out the full release notes here: Salesforce Spring 11 Release Notes

Sunday, January 9, 2011

The Death Star: Poor Project Management in Practice

This week I pulled out my Star Wars DVD's and watched them from start to finish for the first time in a few years. Those movies were the baseline for my childhood. I remember playing Star Wars with my friends on Sunday afternoons as a child. There would always be the argument over who would play Luke and who would play Han Solo, with the unluckiest kid getting stuck as Chewbacca or Lando. We'd run around the neighborhood fighing Tie Fighters and AT-AT's. But watching these holy films as an adult is a different experience entirely.

The opening scene of 'Return of the Jedi' is a prime example. Lord Vader arrives at the second Death Star which is under construction. Apparently the Death Star construction is behind schedule, and the primary stakehold (Emperor Palpatine) is not happy. So Lord Vader flies out there to speak with the Commander in charge of the construction to get them back on schedule. The commander tells Lord Vader that the timelines are ridiculous, and that he needs more men to meet the deadlines.

I watch this scene and now, I see the whole Death Star construction as a project. Complete with milestones, tasks, assigned resources,  stakeholders and status meetings. And I can't help but see a few of the problems facing the Death Star project.

1. Bad Assumptions

I can just see someone saying "Well, the second one should be easier than the first because we have learned so many lessons". Normally, yes this would be true. But you've got quite a few differences this time around. First, you've lost  Grand Moff Tarkin, arguably the father of the Death Star, when he died in the explosion of the first Death Star. Who knows how much knowledge was lost there that could impact timelines. If you lose your subject matter expert, don't expert to gain efficiencies on the next project automatically!

Secondly, even when repeating similar projects, they each have their own differences which can manifest unique problems. And I'm just talking about software development for enterprises. Imagine building giant space stations the size of a small moon!

2. Poor Escalation of Issues

The first thing the commander says to Darth Vader is "I need more men!". Really buddy? You have had resource bandwidth issues for long enough that the primary stakeholder has noticed and has had to take action? Your lucky Lord Vader didn't force choke you on the spot. You have to escalate the issues when they first crop up, not halfway through the development process.

Waiting until your already behind on the milestones and tasks is horrible project management. And just throwing more people at a problem is not going to solve it. You need bring in the right resources, not just more people. I've seen this dozen of times. A project is behind schedule, so the PM tries to just throw more hands at the problem by utilizing a bunch of offshore resources or low cost junior developers at the problem. The result? Poor quality deliverables that need to be rewritten by a more senior resource at greater expense and more time.

3. The Production Deadline Drives the Process

The Emperor engages the rebel fleet with this half constructed Death Star on purpose. Its not even fully built yet. Its fully operational in regards to the fact that its Planetary Laser is working, and he blows up a few capital ships. But a full frontal attack by capital ships was never the weakness of the Death Star, it was small fighters attacking it that made it vulnerable.

The second Death Star had the defect fixed so that the exhaust ports would not allow a direct hit to blow it up. But its outer hull and its full complement of defenses are not finished when the Emperor traps the rebels into fighting. If the Emperor had waited until the Death Star was fully completed like the first one, then there would have been no holes in the hull to allow the ships to fly to the center and blow it up!

Deploying a half completed application into production is going to bite you in the ass everytime!

Oh Palpatine, if you had just managed the construction of the second Death Star properly, you could have won! You could have crushed the rebel scum! Oh well.

Tuesday, January 4, 2011

Visualforce Page - Attachment Upload Example

I see a lot of folks posting questions in the developer forums about uploading an attachment into Salesforce through a Visualforce Page. It is actually very easy to accomplish this.

You will want to use the apex tag <apex:inputFile> to put the FileChooser Popup on the VF Page.

Inside your controller, you simply create an empty Document object, and you bind the <apex:inputFile> tag to the Document in the controller with this code here:

<apex:inputFile value="{!attach.body}" filename="{!attach.name}"/>

With your bindings all set, you just need to create an action on the controller to retrieve the values from the insert the Attachment Object. This can be done in the upload() method in the code below.

This small custom controller and Visualforce page will allow a user to upload a file and create an attachment on the record for an ID give. Here are the screenshots to show this in action.

 Once the upload() method finishes it sends the user to the new Attachment.



Here is the full code below:

AttachmentUploadController - Apex Controller
//Simple Custom Controller to Insert an Attachment into Salesforce
public with sharing class AttachmentUploadController
{
    public String parentId {get;set;}
    public Attachment attach {get;set;}
  
    public AttachmentUploadController()
    {
        attach = new Attachment();
    }
  
    //When user clicks upload button on Visualforce Page, perform upload/insert
    //Redirect user to newly inserted document
    public ApexPages.Pagereference upload()
    {
       
        //This shows how to insert an Attachment
        attach.ParentId = parentId;
        insert attach;
       
        return new ApexPages.Standardcontroller(attach).view();  
    }
}


AttachmentUpload - Visualforce Page
<apex:page controller="AttachmentUploadController">
    <apex:form >
        <apex:outputText value="Parent Object ID: "/><apex:inputText value="{!parentId}"/><br/>
        <apex:outputText value="Input File:  "/><apex:inputFile value="{!attach.body}" filename="{!attach.name}"/><br/>
        <apex:commandButton value="Upload" action="{!upload}"/>
    </apex:form>
</apex:page>



Its really that easy. Of course you'll need to add some error handling to check for null files and stuff like that, but the basics are super easy. This is a good example of a development activity that Apex makes quick and easy.

Of course when you hit Apex limits or things it doesn't do well, thats when you want to pull your hair out.

Monday, January 3, 2011

Building Dynamic SOQL - Select All Query

Salesforce SOQL does not allow select * queries. For example, you cannot do "Select * from Account where Id = 'XXXXXXXX'". This can be confusing to new Apex developers who are familiar with SQL, since SOQL syntax is very close to SQL. This presents developers with the question: How can I dynamically query for all the fields on an object? The answer is you can use Salesforce Schema Describe objects to dynamically build SOQL queries at run time to query for all fields on a record.

In this post, we are going to use the Schema Describe methods to do a few interesting things.
  1. We are going to dynamically determine the Object Type based on the ID at run-time.
  2. We are going to retrieve all the field definitions for the Object.
  3. We are going to build a SOQL query dynamically to query for all the fields.
  4. Just for fun we are going to populate the results dynamically in a Visualforce Page.
 The first thing we need to do is use the Schema classes to retrieve the SObject describe results into memory:
     Map<String,Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();

Now that we have the Schema SObjects in memory, we can iterate over the SObject to determine which type of SObject this ID referers to by calling this code here:


        List<Schema.SObjectType> sobjects = schemaMap.values();
        List<Sobject> theObjectResults;
        Schema.DescribeSObjectResult objDescribe;
        List<Schema.SObjectField> tempFields;
        for(Schema.SObjectType objType : sobjects)
        {
            objDescribe = objType.getDescribe();
            String sobjectPrefix = objDescribe.getKeyPrefix();
            if(id != null && sobjectPrefix != null && id.startsWith(sobjectPrefix))
            {
                objectType = objDescribe.getLocalName();
                Map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
                tempFields = fieldMap.values();
                for(Schema.SObjectField sof : tempFields)
                {
                    fields.add(sof.getDescribe());
                }
                getAllQuery = buildQueryAllString(fields,objDescribe,id);
            }
        }
       
        resultObject = Database.query(getAllQuery);
       
        for(Schema.DescribeFieldResult dfr : fields)
        {
            fieldVals.add(new GenericFieldVO(dfr,resultObject));
        }

We use the objDescribe.getKeyPrefix() method to retrieve the prefix for the Object. This is a great API call that I seldom see used. Many times I see developers hard-code the prefix in the code, which I personally can't stand. After we have the prefix, we check that against the ID to see if the ID starts with the prefix. If it does, then we know that this is the Object Describe to use.

Once we have the correct SObject definition, then we can get all the field definitions by calling objDescribe.fields.getMap(). This returns a Map of the SObjectField type which contains the field definitions (labels, data type, etc). With this information we are now ready to build a dynamic query which will query for all the data for this particular ID.
    //Build the Query String
    private String buildQueryAllString(List<Schema.DescribeFieldResult> queryFields,DescribeSObjectResult obj, String theId)
    {
        String query = QUERY_SELECT;
        for(Schema.DescribeFieldResult dfr : queryFields)
        {
            query = query + dfr.getName() + ',';
        }
        query = query.subString(0,query.length() - 1);
        query = query + QUERY_FROM;
        query = query + obj.getName();
        query = query + QUERY_WHERE;
        query = query + theId + '\'';
        system.debug('Build Query == ' + query);
        return query;
    }


Bam. We now have the ability to build dynamic queries which will retrieve all the information for a object. For this example I have built a Visualforce Page which displays the dynamic values. I will included the full source for this at the bottom of this post. Here is the output of our dynamic SOQL calls for when I give it an Contact ID:
And then I just provide a second ID of a Account:




You can see that the values are dynamically queried and populated on the screen. Of course this particular example doesn't have much business value, you can always just put http://www.salesforce.com/XXXXXXXXX where XXXXXXX is your ID and go straight to the record. But this example shows that you can build dynamic SOQL queries to do 'Select *' type functionality with relative ease.

Now here is the full Apex code dump of this simple page.

To test, just simply pass a URL like https://c.na3.visual.force.com/apex/GenericSelectAll?id=XXXXXXXXX into your browser where ?id=XXXXXXXXXXX is your ID.

SchemaManager
//This class will do all the methods to retrieve schema infomraiton on SObject for apex
//This will ensure that multiple calls to descibes aren't called so we don't hit gov limits
public with sharing class SchemaManager
{
    private static Map<String, Schema.SObjectType> sobjectSchemaMap;
   
    public static Map<String,Schema.SObjectType> getSchemaMap()
    {
        if(sobjectSchemaMap == null)
        {
            sobjectSchemaMap = Schema.getGlobalDescribe();
        }
        return sobjectSchemaMap;
    }
   
    //Retrieve the specific Schema.SobjectType for a object so we can inspect it
    public static Schema.SObjectType getObjectSchema(String objectAPIName)
    {
        getSchemaMap();
        Schema.SObjectType aSObjectType = sobjectSchemaMap.get(objectAPIName);
        return aSobjectType;
    }
}


GenericSelectAllController
//A simple custom controller that will take any ID as input
//and query for all fields (up to 90) on the SObject dynamically
public with sharing class GenericSelectAllController
{
    public List<Schema.DescribeFieldResult> fields {get;set;}
    public List<GenericFieldVO> fieldVals {get;set;}
    public String getAllQuery {get;set;}
    public SObject resultObject {get;set;}
    public String objectType {get;set;}
    public String searchId {get;set;}
    public List<SObject> vals {get;set;}
    public static final String ERROR_ID_MISSING = 'There was no id passed in the parameters. Id is required.';
    public static final String QUERY_SELECT = 'select ';
    public static final String QUERY_FROM = ' from ';
    public static final String QUERY_WHERE = ' where Id = \'';
    //Instantiate the controller. If there is no ID then send the error message to the page.
    public GenericSelectAllController()
    {
        init();
        String id = ApexPages.currentPage().getParameters().get('id');
        if(id == null || id == '')
        {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL,ERROR_ID_MISSING));
        }
        else
        {
            searchId = id;
            processSchemaInfo(id);
        }
    }
   
    //Process the Schema information
    //1. Retrieve the global Schema Information
    //2. Iterate over the SObject Schema Information
    //2.A Retrieve the SObject Key Prefix and match to the ID passed into page
    //2.B Describe all the Fields for the SObject
    //2.C Build a Query String from all the Fields
   
    private void processSchemaInfo(String id)
    {
        system.debug(id);
        Map<String,Schema.SObjectType> schemaMap = SchemaManager.getSchemaMap();
        List<Schema.SObjectType> sobjects = schemaMap.values();
        List<Sobject> theObjectResults;
        Schema.DescribeSObjectResult objDescribe;
        List<Schema.SObjectField> tempFields;
        for(Schema.SObjectType objType : sobjects)
        {
            objDescribe = objType.getDescribe();
            String sobjectPrefix = objDescribe.getKeyPrefix();
            if(id != null && sobjectPrefix != null && id.startsWith(sobjectPrefix))
            {
                objectType = objDescribe.getLocalName();
                Map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
                tempFields = fieldMap.values();
                for(Schema.SObjectField sof : tempFields)
                {
                    fields.add(sof.getDescribe());
                }
                getAllQuery = buildQueryAllString(fields,objDescribe,id);
            }
        }
       
        resultObject = Database.query(getAllQuery);
       
        for(Schema.DescribeFieldResult dfr : fields)
        {
            fieldVals.add(new GenericFieldVO(dfr,resultObject));
        }
       
    }
   
    private void init()
    {
        getAllQuery = '';
        fields = new List<Schema.DescribeFieldResult>();
        fieldVals = new List<GenericFieldVO>();
    }
   
    //Build the Query String
    private String buildQueryAllString(List<Schema.DescribeFieldResult> queryFields,DescribeSObjectResult obj, String theId)
    {
        String query = QUERY_SELECT;
        for(Schema.DescribeFieldResult dfr : queryFields)
        {
            query = query + dfr.getName() + ',';
        }
        query = query.subString(0,query.length() - 1);
        query = query + QUERY_FROM;
        query = query + obj.getName();
        query = query + QUERY_WHERE;
        query = query + theId + '\'';
        system.debug('Build Query == ' + query);
        return query;
    }
}




GenericFieldVO


GenericFieldVO
/* ============================================================
 * Part of this code has been modified from source that is part of the "apex-lang" open source project avaiable at:
 *
 *      http://code.google.com/p/apex-lang/
 *
 * This code is licensed under the Apache License, Version 2.0.  You may obtain a
 * copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 * ============================================================
 */


// A Generic View Object which is used to wrap generic SObject Field Data for Visualforce Page display.
public with sharing class GenericFieldVO
{
    public String fieldLabel {get;set;}
    public String stringVal {get;set;}
    public Boolean boolVal {get;set;}
    public Date dateVal {get;set;}
    public Integer intVal {get;set;}
    public Double doubleVal {get;set;}
    public DateTime dateTimeVal {get;set;}
    public ID idVal {get;set;}
    public Boolean isBool {get;set;}
   
    private static final List<Schema.DisplayType> STRING_TYPES      = new List<Schema.DisplayType>{
    Schema.DisplayType.base64
    ,Schema.DisplayType.Email
    ,Schema.DisplayType.MultiPicklist
    ,Schema.DisplayType.Phone
    ,Schema.DisplayType.Picklist
    ,Schema.DisplayType.String
    ,Schema.DisplayType.TextArea
    ,Schema.DisplayType.URL
    };
    private static final List<Schema.DisplayType> INTEGER_TYPES     = new List<Schema.DisplayType>{
        Schema.DisplayType.Integer
    };
    private static final List<Schema.DisplayType> ID_TYPES          = new List<Schema.DisplayType>{
        Schema.DisplayType.ID
        ,Schema.DisplayType.Reference
    };
    private static final List<Schema.DisplayType> DOUBLE_TYPES      = new List<Schema.DisplayType>{
        Schema.DisplayType.Currency
        ,Schema.DisplayType.Double
        ,Schema.DisplayType.Percent
    };
    private static final List<Schema.DisplayType> DATETIME_TYPES    = new List<Schema.DisplayType>{
        Schema.DisplayType.DateTime
    };
    private static final List<Schema.DisplayType> DATE_TYPES        = new List<Schema.DisplayType>{
        Schema.DisplayType.Date
    };
    private static final List<Schema.DisplayType> BOOLEAN_TYPES     = new List<Schema.DisplayType>{
        Schema.DisplayType.Boolean
        ,Schema.DisplayType.Combobox
    };

   
   
    public GenericFieldVO(Schema.DescribeFieldResult sourceField, SObject source)
    {
        fieldLabel = sourceField.getLabel();
        if(contains(STRING_TYPES,sourceField.getType())){
            stringVal = (String)source.get(sourceField.getName());
        } else if(contains(INTEGER_TYPES,sourceField.getType())){
            intVal = (Integer)source.get(sourceField.getName());
        } else if(contains(ID_TYPES,sourceField.getType())){
            idVal = (ID)source.get(sourceField.getName());
        } else if(contains(DOUBLE_TYPES,sourceField.getType())){
           doubleVal = (Double)source.get(sourceField.getName());
        } else if(contains(DATETIME_TYPES,sourceField.getType())){
           dateTimeVal = (DateTime)source.get(sourceField.getName());
        } else if(contains(DATE_TYPES,sourceField.getType())){
            dateVal = (Date)source.get(sourceField.getName());
        } else if(contains(BOOLEAN_TYPES,sourceField.getType())){
           boolVal = (Boolean)source.get(sourceField.getName());
           isBool = true;
        }
    }
   
    private static Boolean contains(List<Schema.DisplayType> aListActingAsSet, Schema.DisplayType typeToCheck){
        if(aListActingAsSet != null && aListActingAsSet.size() > 0){
            for(Schema.DisplayType aType : aListActingAsSet){
                if(aType == typeToCheck){
                    return true;
                }
            }
        }
        return false;
    }
}

GenericSelectAllPage
<apex:page controller="GenericSelectAllController">
    <style>
        table {width:100%;}
        td {width:100%;}
    </style>
    <apex:messages />
    <apex:pageBlock title="Generic Search All: {!searchId}">
        <apex:outputPanel layout="block" style="width:100%;" rendered="{!resultObject != null}" id="SobjectDetailPanel">
            <apex:outputText style="font-weight:bold;" value="Type: {!objectType}"/>
            <br/>
            <br/>
            <apex:repeat value="{!fieldVals}" var="fieldVal">
                <apex:outputText style="font-weight:bold;" value="{!fieldVal.fieldLabel}: "/>
                <apex:outputPanel rendered="{!fieldVal.stringVal != null}">
                    <apex:outputText value="{!fieldVal.stringVal}"/>
                </apex:outputPanel>
                <apex:outputPanel rendered="{!fieldVal.isBool == true}">
                    <apex:outputText value="{!fieldVal.boolVal}"/>
                </apex:outputPanel>
                <apex:outputPanel rendered="{!fieldVal.idVal != null}">
                    <a href="/{!fieldVal.idVal}"><apex:outputText value="{!fieldVal.idVal}"/></a>
                </apex:outputPanel>
                <apex:outputPanel rendered="{!fieldVal.intVal != null}">
                    <apex:outputText value="{0, number, 0}">
                       <apex:param value="{!fieldVal.intVal}" />
                     </apex:outputText>
                </apex:outputPanel>
                <apex:outputPanel rendered="{!fieldVal.dateVal != null}">
                    <apex:outputText value="{0,date,yyyy.MM.dd}">
                       <apex:param value="{!fieldVal.dateVal}" />
                    </apex:outputText>
                </apex:outputPanel>
                <apex:outputPanel rendered="{!fieldVal.dateTimeVal != null}">
                    <apex:outputText value="{0,date,yyyy.MM.dd G 'at' HH:mm:ss z}">
                       <apex:param value="{!fieldVal.dateTimeVal}" />
                    </apex:outputText>
                </apex:outputPanel>
                <apex:outputPanel rendered="{!fieldVal.doubleVal != null}">
                    <apex:outputText value="{0, number,0.00}">
                       <apex:param value="{!fieldVal.doubleVal}" />
                     </apex:outputText>
                </apex:outputPanel>
                <br/>
                <br/>
            </apex:repeat>
        </apex:outputPanel>
    </apex:pageBlock>
</apex:page>