9/1/11

Powershell Asynchronous Download String

WebClient DownloadStringAsync
Powershell Register-ObjectEvent
PSEventArgs Properties
# - get webclient
$webClient = new-object net.webclient

# - register event handler for DownloadStringCompleted event
#   action script block is event handler code, show string DownloadStringCompletedEventArgs.Result
register-objectEvent $webClient downloadStringCompleted e1 {write-host $args[1].result}  #positional input params

# - begin asynchronous download string
#   event handlers will execute when download is complete
$webClient.downloadStringAsync("http://www.expressionsoftware.com")

# - list event subscriptions
get-eventSubscriber  #output #SubscriptionId  : 1
                             #SourceObject    : System.Net.WebClient
                             #EventName       : downloadStringCompleted
                             #SourceIdentifier: e1
                             #Action          : System.Management.Automation.PSEventJob
                             #SupportEvent    : False
                             #ForwardEvent    : False
                             #HandlerDelegate :

# - list jobs
get-job | fl  #output  #Id           : 1
                       #Name         : e1
                       #Command      : write-host $args[1].result
                       #State        : Running
                       #JobStateInfo : Running
                       #HasMoreData  : True
                       #Finished     : System.Threading.ManualResetEvent
                       #InstanceId   : 010f31f4-e8d2-4742-a782-79057faefebf
                       #Module       : __DynamicModule_a48149c1-5a56-4172-bc68-473ec7c83119
                       #StatusMessage:   #Location
                       #ChildJobs    : {}  #Output, Error, Progress, Verbose, Debug, Warning

# - register another handler, multiple event handlers supported, named input params
register-objectEvent -inputObject $webClient `
                     -eventName downloadStringCompleted `
                     -sourceIdentifier e2 `
                     -action {write-host ("async event at {0}`nevent handler source identifier: {1}`n{2}" -f ($event.timeGenerated.tostring("HH:mm:ss")), $event.sourceIdentifier, $args[1].result)}

# - unregister events
unregister-event -subscriptionId 1
unregister-event -sourceIdentifier e2
get-eventsubscriber -force | unregister-event -force  #unregister all events

# - synchronous download string
$webClient.downloadString("http://www.expressionsoftware.com")

Powershell asynchronous download file with WebClient DownloadFileAsync

8/25/11

CSS Selector & XPath Expression Browser Commands

CSS selectors and XPath expressions can be used to answer queries such as
- How many scripts does this page have?
- How many are external? What are they?
- How many are inline? Show me the source.

CSS Selectors - W3
"Selectors are patterns that match against elements in a tree, and as such form one of several technologies that can be used to select nodes in an XML document. Selectors have been optimized for use with HTML and XML, and are designed to be usable in performance-critical code."

Firefox and Chrome support CSS and XPath commands in the console via the Firebug Command Line API.

Syntax
$$(selector)  Returns an array of elements that match the given CSS selector.
$x(xpath)     Returns an array of elements that match the given XPath expression.
$(id)         Returns a single element with the given id.
CSS Selector Examples
//scripts
$$("script")                     //script tags
$$("script").length              //count
$$("script[async]")              //async scripts
$$("script[src]")                //external scripts with src
$$("script:not([src])")          //inline scripts with no src not
$$("script:not([src])")[0].text  //show inline script source code

//list external scripts src url
var x = $$("script[src]"); console.log("page: " + window.location.href + "\n" + x.length + " external scripts"); for(var i = 0;i < x.length; i++){console.log(x[i].src)}

//list inline script source code
var x = $$("script:not([src])"); console.log("page: " + window.location.href + "\n" + x.length + " internal scripts"); for(var i = 0;i < x.length; i++){console.log("script #" + (i + 1.0) + "\n" + x[i].text)}

//*************
//anchors
$$("a")                   //anchor tags
$$("a").length            //count
$$("a[class]")            //anchors with class
$$("a[href]")             //anchors with hrefs
$$("a:not([href])")       //anchors with no hrefs not
$$("a[href*=foo]")        //anchors with href url containing "foo"
$$("a[href*=\\?]")        //anchors with href url containing querystring
$$("a[onclick]")          //anchors with onclick event
$$("a[onclick^=foobar]")  //anchors with onclick event name starts with foobar

//list anchor link href urls
var x = $$("a[href]"); console.log("page: " + window.location.href + "\n" + x.length + " anchor urls"); for(var i = 0;i < x.length; i++){console.log(x[i].href)}

//*************
//images
//list image src urls
var x = $$("img[src]"); console.log("page: " + window.location.href + "\n" + x.length + " image urls"); for(var i = 0;i < x.length; i++){console.log(x[i].src)}

//*************
//iframes
//list iframe src urls
var x = $$("iframe"); console.log("page: " + window.location.href + "\n" + x.length + " iframes"); for(var i = 0;i < x.length; i++){console.log("id: " + x[i].id +"\nsrc: "+ x[i].src)}

//*************
//meta tags
$$("meta[name^=descr]")[0].content  //description meta tag, meta tag with name starts with "descr"
$$("meta[name$=words]")[0].content  //keywords meta tag, meta tag with name ends with "words"

//list meta tags
var x = $$("meta"); console.log("page: " + window.location.href + "\n" + x.length + " meta tags"); for(var i = 0;i < x.length; i++){console.log(x[i])}

//*************
//all elements
$$("[class]")      //elements with class
$$("[class=foo]")  //elements with class name equal "foo" match
$$("[id]")         //elements with id

//list element ids
var x = $$("[id]"); console.log("page: " + window.location.href + "\n" + x.length + " ids"); for(var i = 0;i < x.length; i++){console.log(x[i].id)}

CSS Selector Syntax: www.w3.org/TR/css3-selectors/#selectors
Chrome Dev Tools Resources UI can be used to access image and external script info.
Don't even ask about ie just view source.


8/1/11

Visual Studio 2010 VB.NET Macros

'Visual Studio 2010 VB.NET Macros
'www.expressionsoftware.com
'v11.8.1

Imports System
Imports System.Collections.Generic
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100

Public Module ExpressionSoftwareMacros

    Sub PrintFilenamesForOpenFiles()
        Dim output = "macro: PrintFilenamesForOpenFiles" + vbCrLf
        Dim outputFiles As String
        Dim openFiles = GetOpenFiles()

        'openFiles.Sort()  'error: failed to compare two elements in the array
        openFiles.Sort(New EnvDteDocumentComparerClass())

        For Each file In openFiles
            outputFiles += "file: " + file.FullName + vbCrLf
        Next

        output += "date: " + Date.Now + vbCrLf
        output += "count: " + Str(openFiles.Count) + vbCrLf
        output += outputFiles
        Out(output)
    End Sub

    Sub HideLinebreakToBrace()
        Dim output = "macro: HideLinebreakToBrace" + vbCrLf
        Dim count = 0

        'vs pofs regex
        ':b whitespace or tab
        'Dim searchString = ":b*\n:b*\{"  'matches "\b\n{" which cannot be hidden, can use if count is not output, else count incorrect
        Dim searchString = "{:b+\n:b*\{}|{:b*\n:b+\{}"

        DTE.Find.FindWhat = searchString
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument  'search current file only
        DTE.Find.Action = vsFindAction.vsFindActionFind
        DTE.Find.MatchInHiddenText = True
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxRegExpr  'regex search
        DTE.SuppressUI = False

        DTE.ActiveDocument.Selection.StartOfDocument()  'set cursor top of file
        While DTE.Find.Execute() <> vsFindResult.vsFindResultNotFound
            count += 1
            DTE.ActiveDocument.Selection.CharLeft(True, 1)  'unselect brace char
            DTE.ExecuteCommand("Edit.HideSelection")
        End While
        DTE.ActiveDocument.Selection.StartOfDocument()

        output += "date: " + Date.Now + vbCrLf
        output += "file: " + DTE.ActiveDocument.FullName + vbCrLf
        output += "count: " + Str(count)
        Out(output)
    End Sub

    Private Function GetOpenFiles() As List(Of EnvDTE.Document)
        Dim openFiles As New List(Of EnvDTE.Document)

        For Each doc As EnvDTE.Document In DTE.Documents
            If doc.ProjectItem IsNot Nothing Then  'todo: combine 
                If doc.ProjectItem.IsOpen() Then
                    openFiles.Add(doc)
                End If
            End If
        Next

        Return openFiles
    End Function

    Private Sub Out(ByVal output)
        GetMacrosOutputWindow().OutputString(output)
    End Sub

    'requires Microsoft Samples Utilities module,
    'copy module into MyMacros project
    Private Function GetMacrosOutputWindow() As OutputWindowPane
        Dim windowTitle = "Expression Software Macros"
        Dim window As Window
        Dim target As Object
        Dim document As EnvDTE.Document

        window = DTE.Windows.Item(Constants.vsWindowKindCommandWindow)
        If DTE.ActiveWindow Is window Then
            target = window.Object
        Else
            target = Utilities.GetOutputWindowPane(windowTitle)
            target.clear()
        End If

        Return target
    End Function
End Module


Public Class EnvDteDocumentComparerClass
    Implements IComparer(Of EnvDTE.Document)

    'compare docs by full filename, for sorting
    Function Compare(ByVal file1 As EnvDTE.Document, _
                     ByVal file2 As EnvDTE.Document) _
                     As Integer Implements IComparer(Of EnvDTE.Document).Compare

        Return file1.FullName.CompareTo(file2.FullName)
    End Function
End Class


Public Class EnvDteDocumentComparableClass
    Implements IComparable(Of EnvDTE.Document)

    'compare docs by full filename, for sorting
    Function CompareTo(ByVal other As EnvDTE.Document) _
                       As Integer Implements IComparable(Of EnvDTE.Document).CompareTo

        Return FullName.CompareTo(other.FullName)
    End Function
End Class


'**************************************************************
'Misc
'DTE.Documents.Count includes closed docs
'DTE.ActiveDocument.FullName
'output += "date: " + Date.Now + vbCrLf
'Microsoft.VisualBasic.Constants.vbCrLf
'DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
'keyboard shortcuts
'  alt + F8    macro explorer
'  alt + F11   macros ide
'**************************************************************

3/20/11

View Product - Online Catalog Example using ASP.NET MVC 3

View Product URL: http://mvc.expressionsoftware.com/products/1000

Route
routes.MapRoute("view product",
                "products/{id}",
                new { controller = "Product",
                      action = "ViewProduct" });

Controller: \controllers\productController.cs
[HttpGet]
public ActionResult ViewProduct(int id)
{
    var product = Cache.GetProduct(id);
    return View(product);
}

Product Model Class & Object
namespace ExpressionSoftware.Model
{
   public class Product
   {
     public int Id { get; set; }
     public string Name { get; set; }
     public string Description { get; set; }

     public decimal Price { get; set; }
     public string Status { get; set; }
     public bool InStock { get; set; }
     public int StockCount { get; set; }

     public Dictionary<string, string> Metadata { get; set; }
   }
}

new Product() {
                Id = 1000,
                Name = "Foo",
                Description = "Some Foo...",
  
                Price=999.99m,
                Status = "In Stock",
                InStock = true,
                StockCount = 10,
  
                Metadata = new Dictionary<string, string>()
                {
                  { "Color", "Blue"},
                  { "Size", "30 x 16"},
                  { "Manufacturer", "Foo Makers Inc, USA"},
                }

              },

View: \views\product\viewProduct.cshtml
@model ExpressionSoftware.Model.Product
@{Layout = null;}

<!doctype html>
<html>
<head>
  <title>@Model.Name - Products</title>
  <link href="../../ux/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
  <h1>@Model.Name</h1>
  Id: @Model.Id<br />
  Description: @Model.Description<br /><br />

  Status: @{  //************************************
              if (@Model.InStock) {
                <span class="instock">@Model.Status</span><br />
                @:Count Available: @Model.StockCount
              }
              else {
                @Model.Status
              }
          }<br />

   Price: $@Model.Price<br /><br />
   
   @{  //************************************
       //metadata
       if (Model.Metadata != null) {
         foreach (var kvp in Model.Metadata) {
           @string.Format("{0}: {1}", kvp.Key, kvp.Value);<br />
         }
       }
   }<br />

   @{  //************************************
       <!-- wip - add to cart form / post action -->
       if (@Model.InStock) {
         <input type="submit" value="Add to Cart" />
       }
   }
</body>
</html>

Output HTML
<!doctype html>
<html>
<head>
  <title>Foo - Products</title>
  <link href="../../ux/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
  <h1>Foo</h1>
  
  Id: 1000<br />
  Description: Some Foo...<br /><br />

  Status: <span class="instock">In Stock</span><br />
  Count Available: 10<br />
  Price: $999.99<br /><br />

  Color: Blue<br />
  Size: 30 x 16<br />
  Manufacturer: Foo Makers Inc, USA<br /><br />
  
  <!-- wip - add to cart form / post action -->
  <input type="submit" value="Add to Cart" />
</body>
</html>



3/2/11

Integrating reCAPTCHA with ASP.NET MVC 3

Example using reCAPTCHA in an email-contact page.

www.google.com/recaptcha
code.google.com/apis/recaptcha
www.google.com/recaptcha/api/verify


RecaptchaController Class



\controllers\recaptcha\recaptchaController.cs
using System.Web.Mvc;

namespace ExpressionSoftware.Controllers
{
    public class RecaptchaController : Controller
    {
        //********************************************************
        // PRIVATE DATA - DO NOT HARDCODE
        
           const string RECAPTCHA_PRIVATE_KEY = "----------";
           const string EMAIL_ADDRESS = "john@email.com";
        
        //********************************************************

        const string RECAPTCHA_VERIFY_URL = "http://www.google.com/recaptcha/api/verify";
        
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult Default()
        {
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public string Default(FormCollection formValues)
        {
            string result = "fail";
            
            //do not submit recaptcha if form vars are null/empty
            if (!(string.IsNullOrEmpty(formValues["recaptcha_challenge_field"]) ||
                  string.IsNullOrEmpty(formValues["recaptcha_response_field"])))
            {
                //alt - validate using web service
                var recaptcha = new ExpressionSoftware.Recaptcha() { PrivateKey = RECAPTCHA_PRIVATE_KEY,
                                                                     VerifyUrl = RECAPTCHA_VERIFY_URL };

                if (recaptcha.Validate(Request.UserHostAddress, formValues["recaptcha_challenge_field"], 
                                                                formValues["recaptcha_response_field"]))
                {
                    result = EMAIL_ADDRESS;  //captcha test passed, show email address
                }
            }
            return result;
        }
    }
}

\views\recaptcha\default.cshtml
<h2>reCAPTCHA Demo for ASP.NET MVC 3</h2>

@using (Html.BeginForm()) {
<input id="b1" type="button" value="Show CAPTCHA" />
<a id="email" />
<div id="captchaDiv"></div>
<input id="submit" type="submit" value="Submit" style="display:none;"/>
<label id="error" style="display:none;">Invalid input, please try again.</label>    
}

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js" type="text/javascript"></script>
<script src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js" type="text/javascript"></script>
<script src="/js/recaptcha.js" type="text/javascript"></script>

\js\recaptcha.js
$(document).ready(function() {
  $("form").submit(
    function(event) {
      event.preventDefault();
      submit(this, updateUI, "html");
    });
  $("#b1").click(showCaptcha);
});

function submit(form, callback, format) {
  $.ajax({url: form.action,
          type: form.method,
          dataType: format,
          data: $(form).serialize(),
          success: callback
         });
}

function updateUI(result) {
  result = $.trim(result);
  
  if (result == "fail") {
    $("#error").show();
    Recaptcha.reload();
    Recaptcha.focus_response_field();
  }
  else {  //success
    $("#email").text(result);
    $("#email")[0].href = "mailto:"+result;
    $("#captchaDiv").hide();
    $("#submit").hide();
    $("#error").hide();
  }
}

function showCaptcha() {
  Recaptcha.create("6LdXGMISAAAAAKbqYwaabU7h1qjwGYEXoEelZjWV",  //api public key
                   "captchaDiv",
                   {
                     theme: "clean",
                     callback: Recaptcha.focus_response_field
                   }
                  );
  $("#b1").hide();
  $("#submit").show();
  return false;
}


Recaptcha Class / Web Service



recaptcha.cs
using System.IO;
using System.Net;
using System.Text;

namespace ExpressionSoftware
{
    public class Recaptcha
    {
        public string VerifyUrl { get; set; }
        public string PrivateKey { get; set; }

        public bool Validate(string remoteIP, string captchaChallenge, string captchaResponse)
        {
            bool result = false;
            string response = GetWebResponse(remoteIP, captchaChallenge, captchaResponse);
            result = response.ToLower().StartsWith("true");  //api response line 1 value: true or false
            return result;
        }

        string GetWebResponse(string remoteIP, string captchaChallenge, string captchaResponse)
        {
            string result = null;

            //convert params to byte array
            var parameters = string.Format("privatekey={0}&remoteip={1}&challenge={2}&response={3}",
                                           PrivateKey, remoteIP, captchaChallenge, captchaResponse);
            byte[] paramData = Encoding.UTF8.GetBytes(parameters);

            var request = (HttpWebRequest)WebRequest.Create(VerifyUrl);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = paramData.Length;
            request.ServicePoint.Expect100Continue = false;
            
            //write param data to request stream
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(paramData, 0, paramData.Length);
                requestStream.Close();
            }

            using (WebResponse response = (HttpWebResponse)request.GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                {
                    using (StreamReader responseReader = new StreamReader(stream))
                    {
                        result = responseReader.ReadToEnd();
                        responseReader.Close();
                    }
                    stream.Close();
                }
                response.Close();
            }
            return result;
        }
    }
}



2/11/11

PowerShell 2 Aliases

Get-Alias cmdlet

Alias    Definition  
%        ForEach-Object
?        Where-Object
ac       Add-Content
asnp     Add-PSSnapIn
cat      Get-Content
cd       Set-Location
chdir    Set-Location
clc      Clear-Content
clear    Clear-Host
clhy     Clear-History
cli      Clear-Item
clp      Clear-ItemProperty
cls      Clear-Host
clv      Clear-Variable
compare  Compare-Object
copy     Copy-Item
cp       Copy-Item
cpi      Copy-Item
cpp      Copy-ItemProperty
cvpa     Convert-Path
dbp      Disable-PSBreakpoint
del      Remove-Item
diff     Compare-Object
dir      Get-ChildItem
ebp      Enable-PSBreakpoint
echo     Write-Output
epal     Export-Alias
epcsv    Export-Csv
epsn     Export-PSSession
erase    Remove-Item
etsn     Enter-PSSession
exsn     Exit-PSSession
fc       Format-Custom
fl       Format-List
foreach  ForEach-Object
ft       Format-Table
fw       Format-Wide
gal      Get-Alias
gbp      Get-PSBreakpoint
gc       Get-Content
gci      Get-ChildItem
gcm      Get-Command
gcs      Get-PSCallStack
gdr      Get-PSDrive
ghy      Get-History
gi       Get-Item
gjb      Get-Job
gl       Get-Location
gm       Get-Member
gmo      Get-Module
gp       Get-ItemProperty
gps      Get-Process
group    Group-Object
gsn      Get-PSSession
gsnp     Get-PSSnapIn
gsv      Get-Service
gu       Get-Unique
gv       Get-Variable
gwmi     Get-WmiObject
h        Get-History
history  Get-History
icm      Invoke-Command
iex      Invoke-Expression
ihy      Invoke-History
ii       Invoke-Item
ipal     Import-Alias
ipcsv    Import-Csv
ipmo     Import-Module
ipsn     Import-PSSession
ise      powershell_ise.exe
iwmi     Invoke-WMIMethod
kill     Stop-Process
lp       Out-Printer
ls       Get-ChildItem
man      help
md       mkdir
measure  Measure-Object
mi       Move-Item
mount    New-PSDrive
move     Move-Item
mp       Move-ItemProperty
mv       Move-Item
nal      New-Alias
ndr      New-PSDrive
ni       New-Item
nmo      New-Module
nsn      New-PSSession
nv       New-Variable
ogv      Out-GridView
oh       Out-Host
popd     Pop-Location
ps       Get-Process
pushd    Push-Location
pwd      Get-Location
r        Invoke-History
rbp      Remove-PSBreakpoint
rcjb     Receive-Job
rd       Remove-Item
rdr      Remove-PSDrive
ren      Rename-Item
ri       Remove-Item
rjb      Remove-Job
rm       Remove-Item
rmdir    Remove-Item
rmo      Remove-Module
rni      Rename-Item
rnp      Rename-ItemProperty
rp       Remove-ItemProperty
rsn      Remove-PSSession
rsnp     Remove-PSSnapin
rv       Remove-Variable
rvpa     Resolve-Path
rwmi     Remove-WMIObject
sajb     Start-Job
sal      Set-Alias
saps     Start-Process
sasv     Start-Service
sbp      Set-PSBreakpoint
sc       Set-Content
select   Select-Object
set      Set-Variable
si       Set-Item
sl       Set-Location
sleep    Start-Sleep
sort     Sort-Object
sp       Set-ItemProperty
spjb     Stop-Job
spps     Stop-Process
spsv     Stop-Service
start    Start-Process
sv       Set-Variable
swmi     Set-WMIInstance
tee      Tee-Object
type     Get-Content
where    Where-Object
wjb      Wait-Job
write    Write-Output


2-Column Custom Format Example using Get-Alias
Dynamically format a 2-column output with N-spaces padding, based on first column width
1. get data
2. calc column 1 max length
3. calc column 2 start index
4. loop & print
$data = get-alias
$numberOfSpaces = 2
$col1MaxLength = ($data | %{$_.name.length} | measure -max).maximum  #7
$col2StartIndex = ($col1MaxLength + $numberOfSpaces)  #9

#format: 0=alias, 1=calc padding, 2=def
$data | %{"{0}{1}{2}" -f $_.name, (" " * (($col2StartIndex - $_.name.length))), $_.definition}
Debug
AliasInfo Class
#get-alias returns AliasInfo array
$data[0].gettype()  #AliasInfo : System.Management.Automation.CommandInfo

#using the measure-object cmdlet to get alias name length stats
$data | %{$_.name.length} | measure -min -max -ave -sum
count   : 137
average : 3.25
sum     : 445   #na
maximum : 7     #for this example we only need MAX
minimum : 1

2/1/11

HTTP Response Status Codes

1xx Informational
100 Continue
101 Switching Protocols
102 Processing (WebDAV)

2xx Success
200 OK
201 Created
202 Accepted
203 Non-Authoritative Information
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

3xx Redirection
300 Multiple Choices
301 Moved Permanently (permanent redirect)
302 Found (temporary redirect)
303 See Other
304 Not Modified
305 Use Proxy
306 Switch Proxy
307 Temporary Redirect

4xx Client Errors
400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Timeout
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Request Entity Too Large
414 Request-URI Too Long
415 Unsupported Media Type
416 Requested Range Not Satisfiable
417 Expectation Failed
418 I'm a teapot
422 Unprocessable Entity (WebDAV)
423 Locked (WebDAV)
424 Failed Dependency (WebDAV)
425 Unordered Collection
444 No Response
426 Upgrade Required
449 Retry With
450 Blocked by Windows Parental Controls
499 Client Closed Request

5xx Server Errors
500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates
507 Insufficient Storage (WebDAV)
509 Bandwidth Limit Exceeded (Apache)
510 Not Extended

JavaScript encodeURI and encodeURIComponent

ASCII Char Comparisons
#    CH  EU     EUC  NOTES
32       %20    %20  space char
96   `   %60    %60
33   !   !      !
64   @   @      %40  x
35   #   #      %23  x
36   $   $      %24  x
37   %   %25    %25
94   ^   %5E    %5E
38   &   &      %26  x
42   *   *      *
40   (   (      (
41   )   )      )
45   -   -      -
61   =   =      %3D  x
91   [   %5B    %5B
93   ]   %5D    %5D
92   \   %5C    %5C
59   ;   ;      %3B  x
39   '   '      '
44   ,   ,      %2C  x
46   .   .      .
47   /   /      %2F  x
126  ~   ~      ~
95   _   _      _
43   +   +      %2B  x
123  {   %7B    %7B
125  }   %7D    %7D
124  |   %7C    %7C
58   :   :      %3A  x
34   "   %22    %22
60   <   %3C    %3C
62   >   %3E    %3E
63   ?   ?      %3F  x

LEGEND
#   ascii code
CH  char
EU  encodeURI
EUC encodeURIComponent
x   diffs

List Chars using jQuery map()
//escape char: \
chars = " `!@#$%^&*()-=[]\\;',./~_+{}|:\"<>?"
jQuery.map(chars.split(""),
  function(c) {
    console.log(c.charCodeAt(0) + " " + c + "  " + encodeURI(c) + "  " + encodeURIComponent(c));
  })

NATO Phonetic Alphabet

AAlpha•–
BBravo–•••
CCharlie–•–•
DDelta–••
EEcho
FFoxtrot••–•
GGolf––•
HHotel••••
IIndia••
JJuliet•–––
KKilo–•–
LLima•–••
MMike––
NNovember–•
OOscar–––
PPapa•––•
QQuebec––•–
RRomeo•–•
SSierra•••
TTango
UUniform••–
VVictor•••–
WWhiskey•––
XX–ray–••–
YYankee–•––
ZZulu––••

1/29/11

JavaScript Dates

Dates contain the number of milliseconds since 1-1-1970 00:00:00 UTC.

Date Constructor
new Date()  //returns current datetime
new Date(milliseconds)
new Date(dateString)
new Date(year, month, day [, hour, minute, second, millisecond])  //optional time-params default to 0

Params: milliseconds ms since 1-1-1970 00:00:00 UTC
        dateString   string format
        year         4 digit year
        month        0-11
        day          1-31  day of the month
        hour         0-23  hour of the day
        minute       0-59  minute segment of a time reading
        second       0-59  second segment of a time reading
        millisecond  0-999 ms segment of a time reading

Static Methods
These methods return the milliseconds since 1-1-1970
Date.now()  //use for timestamps & unique IDs, todo: minimum 15 millisecond resolution on windows?
Date.parse(datestring)
Date.UTC(year, month [, date, hrs, min, sec, ms])  //universal time

d = new Date("Jan 7, 2011")               //Fri Jan 07 2011 00:00:00 GMT-0700 (Mountain Standard Time)
d.getMonth()                              //0 (0-11)
d.getDay()                                //5 (0-6) friday
d.getDate()                               //7 (1-31)
d.getFullYear()                           //2011
d.getHours()                              //0

d = new Date("Jan 07 2011 01:02:03")      //Fri Jan 07 2011 01:02:03 GMT-0700 (Mountain Standard Time)
d.getHours()                              //1
d.getMinutes()                            //2
d.getSeconds()                            //3

d = new Date("Jan 07 2011 01:02:03:456")  //Fri Jan 07 2011 01:02:03 GMT-0700 (Mountain Standard Time)
d = new Date(2011, 0, 7, 1, 2, 3, 456)
d.getMilliseconds()                       //456
d.getTime()                               //1294387323456 milliseconds since 1-1-1970
Date.parse("01-07-2011 01:02:03:456")     //1294387323456 milliseconds since 1-1-1970
Date.UTC(2011, 0, 7, 1, 2, 3, 456)        //1294362123456

formatDate(d)                             //"1-7-2011"
formatDatePad(d)                          //"01-07-2011"
formatDateTime(d)                         //"1-7-2011 1:2:3:456"
formatDateTime(addMinutes(d, 60))         //"1-7-2011 2:2:3:456"
formatDateTime(addMinutes(d, 10))         //"1-7-2011 1:12:3:456"
formatDateTime(addMinutes(d, 1440))       //"1-8-2011 1:2:3:456"

//debug
console.log(d.getMonth());console.log(d.getDate());console.log(d.getFullYear());console.log(d.getHours());console.log(d.getMinutes());console.log(d.getSeconds());console.log(d.getMilliseconds())

//equivalent date constructors, exclude times for date only, string formats can be used with Date.parse()
new Date("01-07-2011 01:02:03")
new Date(2011, 0, 7, 1, 2, 3)
new Date("Jan 07 2011 01:02:03")
new Date("Fri Jan 7 2011 1:2:3")
new Date("Fri Jan 07 2011 01:02:03 GMT-0700")

//-------------
function addMinutes(date, minutes){  //returns date
  var result = new Date(date.getTime());
  result.setMinutes(result.getMinutes() + parseInt(minutes));
  return result;
}

function formatDate(date){  //returns string
  return (date.getMonth() + 1) + "-" + date.getDate() + "-" + date.getFullYear();
}

function formatDatePad(date){  //returns string
  return (pad2(date.getMonth() + 1)) + "-" + pad2(date.getDate()) + "-" + pad2(date.getFullYear());
}

function formatDateTime(date){  //returns string
  return (date.getMonth() + 1) + "-" + date.getDate() + "-" + date.getFullYear() + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + ":" + date.getMilliseconds();
}

//http://www.electrictoolbox.com/pad-number-two-digits-javascript/
function pad2(number){  //returns string
  return (number < 10 ? "0" : "") + number;
}

Conversions
INTERVAL       MS   SECS  MINS   HOURS
1 sec        1000      1  1/60  1/3600
1 min       60000     60     1    1/60
10 min     600000    600    10   10/60
1 hour    3600000   3600    60       1
1 day    86400000  86400  1440      24  ms=24*60*60*1000

1/17/11

Powershell Appcmd IIS 7 Command Line Tool

Appcmd Objects
APPapplications
APPPOOLapplication pools
BACKUPserver configuration backups
CONFIGgeneral configuration sections
MODULEserver modules
REQUESTHTTP requests
SITEvirtual sites
TRACEworking with failed request trace logs
VDIRvirtual directories
WPworker processes

$appcmd = "c:\windows\system32\inetsrv\appcmd.exe"
&$appcmd /?  #help

#list all sites
&$appcmd list site
&$appcmd list site /xml        #use xml to get attribute names
&$appcmd list site /text:name  #use text to get attribute values

&$appcmd list site /text:name | sort  #ps sort

#list all app pools
&$appcmd list apppool

#list app pool names
&$appcmd list apppool /text:name

#list app pool .net framework version
&$appcmd list apppool /text:managedRuntimeVersion

#list all w3wp.exe worker processes, use to debug match process id to iis website
&$appcmd list wp

#list started sites, running
&$appcmd list site /state:started

#list stopped app pools
&$appcmd list apppool /state:stopped

#list all virtual directory/physical paths
&$appcmd list vdir

#list site bindings ipaddress
(&$appcmd list site prod /text:bindings).split(",")

#list response headers
&$appcmd list config prod /section:httpProtocol

#add response headers
&$appcmd set config prod /section:httpProtocol /+"customHeaders.[name='foo', value='bar']"

#delete response headers
&$appcmd set config prod /section:httpProtocol /-"customHeaders.[name='foo']"
&$appcmd set config prod /section:httpProtocol /-"customHeaders.[name='x-powered-by']"

#output site configuration text
&$appcmd list site prod /text:*

#list website virtual directory/physical path
&$appcmd list vdir prod/

#stop website
&$appcmd stop apppool prod; &$appcmd stop site prod

#start website
&$appcmd start apppool prod; &$appcmd start site prod

#stop all running sites
&$appcmd list site /state:started /xml | &$appcmd stop site /in  

#stop all running app pools
&$appcmd list apppool /state:started /xml | &$appcmd stop apppool /in

#list mime types
&$appcmd list config prod /section:system.webServer/staticContent

v11.09

1/15/11

ASP.NET MVC 3 - Project Template for Visual Studio 2010

References
Microsoft.CSharp
System
System.Core
System.Web
System.Web.Helpers
System.Web.Mvc
System.Web.Routing
System.Web.Services
System.Web.WebPages

Folders
controllers
js
models
properties
ux
views
views\home
views\shared

Files
controllers\homeController.cs
demo.csproj
demo.csproj.user
global.asax
global.asax.cs
js\alert.js
properties\assemblyInfo.cs
ux\style.css
views\_viewStart.cshtml
views\home\default.cshtml
views\shared\error.cshtml
views\shared\_layout.cshtml
views\web.config
web.config
web.debug.config
web.release.config

controllers\homeController.cs
using System.Web.Mvc;

namespace Demo.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Default()
        {
            ViewBag.Message = "ViewBag.Message, set in HomeController";

            return View();
        }
    }
}

demo.csproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion></ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{A8C1B3E9-6897-4456-A450-2662343B9E6F}</ProjectGuid>
    <ProjectTypeGuids>{E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>properties</AppDesignerFolder>
    <RootNamespace>Demo</RootNamespace>
    <AssemblyName>demo</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <MvcBuildViews>false</MvcBuildViews>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PublishDatabases>false</PublishDatabases>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Web" />
    <Reference Include="System.Web.Helpers" />
    <Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
    <Reference Include="System.Web.Routing" />
    <Reference Include="System.Web.Services" />
    <Reference Include="System.Web.WebPages" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="global.asax.cs">
      <DependentUpon>global.asax</DependentUpon>
    </Compile>
    <Compile Include="properties\assemblyInfo.cs" />
    <Compile Include="controllers\homeController.cs" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="global.asax" />
    <Content Include="js\alert.js" />
    <Content Include="ux\style.css" />
    <Content Include="views\_viewStart.cshtml" />
    <Content Include="views\home\default.cshtml" />
    <Content Include="views\shared\_layout.cshtml" />
    <Content Include="views\shared\error.cshtml" />
    <Content Include="views\web.config" />
    <Content Include="web.config" />
    <Content Include="web.Debug.config">
      <DependentUpon>web.config</DependentUpon>
    </Content>
    <Content Include="web.Release.config">
      <DependentUpon>web.config</DependentUpon>
    </Content>
  </ItemGroup>
  <ItemGroup>
    <Folder Include="models\" />
  </ItemGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target> -->
  <Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
    <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
  </Target>
  <ProjectExtensions>
    <VisualStudio>
      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
        <WebProjectProperties>
          <UseIIS>False</UseIIS>
          <AutoAssignPort>True</AutoAssignPort>
          <DevelopmentServerPort>1234</DevelopmentServerPort>
          <DevelopmentServerVPath>/</DevelopmentServerVPath>
          <IISUrl></IISUrl>
          <NTLMAuthentication>False</NTLMAuthentication>
          <UseCustomServer>True</UseCustomServer>
          <CustomServerUrl>http://dev.mvcdemo.com/</CustomServerUrl>
          <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
        </WebProjectProperties>
      </FlavorProperties>
    </VisualStudio>
  </ProjectExtensions>
</Project>

demo.csproj.user
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ProjectView>ShowAllFiles</ProjectView>
  </PropertyGroup>
  <ProjectExtensions>
    <VisualStudio>
      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
        <WebProjectProperties>
          <StartPageUrl></StartPageUrl>
          <StartAction>NoStartPage</StartAction>
          <AspNetDebugging>True</AspNetDebugging>
          <SilverlightDebugging>False</SilverlightDebugging>
          <NativeDebugging>False</NativeDebugging>
          <SQLDebugging>False</SQLDebugging>
          <ExternalProgram></ExternalProgram>
          <StartExternalURL></StartExternalURL>
          <StartCmdLineArguments></StartCmdLineArguments>
          <StartWorkingDirectory></StartWorkingDirectory>
          <EnableENC>False</EnableENC>
          <AlwaysStartWebServerOnDebug>True</AlwaysStartWebServerOnDebug>
        </WebProjectProperties>
      </FlavorProperties>
    </VisualStudio>
  </ProjectExtensions>
</Project>

global.asax
<%@ Application Codebehind="global.asax.cs" Inherits="Demo.MvcApplication" Language="C#" %>

global.asax.cs
using System.Web.Mvc;
using System.Web.Routing;

namespace Demo
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "default",                     // Route name
                "{controller}/{action}/{id}",  // URL with parameters
                new { controller = "Home",     // Parameter defaults
                      action     = "Default", 
                      id         = UrlParameter.Optional }
            );
        }

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }
    }
}

js\alert.js
//<script src="/js/alert.js" type="text/javascript"></script>
alert("/js/alert.js");

properties\assemblyInfo.cs
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("MVC Demo")]
[assembly: AssemblyCompany("Expression Software")]
[assembly: ComVisible(false)]
[assembly: Guid("28bf9b70-c4f2-4007-986f-5598dd52dfa8")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

ux\style.css
body{
background:#000;
color:#fff;
font-family:Verdana, Arial, Helvetica, Sans-Serif;
}

views\_viewStart.cshtml
@*file: \views\_viewStart.cshtml
  desc: common view code, executed at the start of View render
*@

@{
    //set default layout
    Layout = "~/views/shared/_layout.cshtml";
}

views\home\default.cshtml
@{
    ViewBag.PageTitle = null;  //breakpoint
    ViewBag.PageTitle += "MVC Demo";
}

@*html body - view source for line breaks & whitespace*@
<h1>@ViewBag.PageTitle</h1>
ViewBag.PageTitle: @ViewBag.PageTitle<br />
ViewBag.Message: @ViewBag.Message

views\shared\error.cshtml
@{
    Layout = null;
}
<!doctype html>
<html>
<head>
  <title>Error</title>
  <meta charset=utf-8>
</head>
<body>
  error...
</body>
</html>

views\shared\_layout.cshtml
<!doctype html>
<html>
<head>
  <title>@ViewBag.PageTitle - Expression Software</title>
  <meta charset=utf-8>
  <link href="/ux/style.css" rel="stylesheet" type="text/css" />
  <!--<script src="/js/alert.js" type="text/javascript"></script>-->
</head>
<body>
  @RenderBody()

  <br />------------------------<br />
  @DateTime.Now.ToString("MM-dd-yy HH:mm:ss:fff")

  <br />------------------------
  @foreach(var x in new [] {0,1,2})
  {
      ;<br />@x;  //use leading semicolon to prevent generating extra, collapsed, whitespace
  }
</body>
</html>

views\web.config
<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

  <appSettings>
    <add key="webpages:Enabled" value="false" />
  </appSettings>

  <system.web>
    <httpHandlers>
      <add path="*" verb="*" type="System.Web.HttpNotFoundHandler" />
    </httpHandlers>

    <!-- Enabling request validation in view pages would cause validation to occur after the input has already been processed by the controller.
         By default MVC performs request validation before a controller processes the input. 
         To change this behavior apply the ValidateInputAttribute to a controller or action. -->
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add tagPrefix="mvc" namespace="System.Web.Mvc" assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </controls>
    </pages>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />

    <handlers>
      <remove name="BlockViewHandler" />
      <add name="BlockViewHandler" 
           path="*" verb="*"
           preCondition="integratedMode" 
           type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>
</configuration>

web.config
<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="ClientValidationEnabled" value="true"/> 
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/> 
  </appSettings>

  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>

    <authentication mode="None" />

    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages"/>
      </namespaces>
    </pages>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

web.debug.config
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
</configuration>

web.release.config
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
  </system.web>
</configuration>



1/12/11

Using External JavaScript Files with Google Analytics

For basic page tracking, put the code in an external file.

Then you can use this
<script src="/js/googleAnalytics.js" type="text/javascript"></script>

instead of
<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXX-X']);
  _gaq.push(['_trackPageview']);
  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
</script>

Add to files, right before the closing head tag.


googleAnalytics.js
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
_gaq.push(['_trackPageview']);
(function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();