Commits

Anonymous committed 012545a

We don't need lib level

  • Participants
  • Parent commits 1b2aa9a
  • Branches couchdb010

Comments (0)

Files changed (28)

File helpers/ejs/ejs.js

+/*--------------------------------------------------------------------------
+ *  EJS - Embedded JavaScript, version 0.1.0
+ *  Copyright (c) 2007 Edward Benson
+ *  http://www.edwardbenson.com/projects/ejs
+ *  ------------------------------------------------------------------------
+ *
+ *  EJS is freely distributable under the terms of an MIT-style license.
+ *
+ *  EJS is a client-side preprocessing engine written in and for JavaScript.
+ *  If you have used PHP, ASP, JSP, or ERB then you get the idea: code embedded
+ *  in <% // Code here %> tags will be executed, and code embedded in <%= .. %> 
+ *  tags will be evaluated and appended to the output. 
+ * 
+ *  This is essentially a direct JavaScript port of Masatoshi Seki's erb.rb 
+ *  from the Ruby Core, though it contains a subset of ERB's functionality. 
+ * 
+ *  Requirements:
+ *      prototype.js
+ * 
+ *  Usage:
+ *      // source should be either a string or a DOM node whose innerHTML
+ *      // contains EJB source.
+ *  	var source = "<% var ejb="EJB"; %><h1>Hello, <%= ejb %>!</h1>"; 
+ *      var compiler = new EjsCompiler(source);		
+ *	    compiler.compile();	
+ *	    var output = eval(compiler.out);
+ *      alert(output); // -> "<h1>Hello, EJB!</h1>"
+ *       
+ *  For a demo:      see demo.html
+ *  For the license: see license.txt
+ *
+ *--------------------------------------------------------------------------*/
+
+/* Make a split function like Ruby's: "abc".split(/b/) -> ['a', 'b', 'c'] */
+String.prototype.rsplit = function(regex) {
+	var item = this;
+	var result = regex.exec(item);
+	var retArr = new Array();
+	while (result != null)
+	{
+		var first_idx = result.index;
+		var last_idx = regex.lastIndex;
+		if ((first_idx) != 0)
+		{
+			var first_bit = item.substring(0,first_idx);
+			retArr.push(item.substring(0,first_idx));
+			item = item.slice(first_idx);
+		}		
+		retArr.push(result[0]);
+		item = item.slice(result[0].length);
+		result = regex.exec(item);	
+	}
+	if (! item == '')
+	{
+		retArr.push(item);
+	}
+	return retArr;
+};
+
+/* Chop is nice to have too */
+String.prototype.chop = function() {
+	return this.substr(0, this.length - 1);
+}
+
+/* Adaptation from the Scanner of erb.rb  */
+var EjsScanner = function(source, left, right) {
+	this.left_delimiter = 	left +'%'	//<%
+	this.right_delimiter = 	'%'+right	//>
+	this.double_left = 		left+'%%'
+	this.double_right = 	'%%'+right
+	this.left_equal = 		left+'%='
+	this.left_comment = 	left+'%#'
+	if(left=='[')
+		this.SplitRegexp = /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/;
+	else
+		this.SplitRegexp = new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)') 
+	
+	this.source = source;
+	this.stag = null;
+	this.lines = 0;
+};
+EjsView = function(data){
+	this.data = data
+}
+EjsView.prototype.partial = function(options, data){
+	if(!data) data = this.data;
+	return new EJS(options).render(data);
+}
+
+EjsScanner.to_text = function(input){
+	if(input == null || input === undefined)
+        return '';
+    if(input instanceof Date)
+		return input.toDateString();
+	if(input.toString) 
+        return input.toString()
+	return '';
+}
+
+EjsScanner.prototype = {
+
+  /* For each line, scan! */
+  scan: function(block) {
+     scanline = this.scanline;
+	 regex = this.SplitRegexp;
+	 if (! this.source == '')
+	 {
+	 	 var source_split = this.source.rsplit(/\n/);
+	 	 for(var i=0; i<source_split.length; i++) {
+		 	 var item = source_split[i];
+			 this.scanline(item, regex, block);
+		 }
+	 }
+  },
+  
+  /* For each token, block! */
+  scanline: function(line, regex, block) {
+	 this.lines++
+	 var line_split = line.rsplit(regex);
+ 	 for(var i=0; i<line_split.length; i++) {
+	   var token = line_split[i];
+       if (token != null) {
+		   	try{
+	         	block(token, this);
+		 	}catch(e){
+				throw {type: 'EjsScanner', line: this.lines}
+			}
+       }
+	 }
+  }
+};
+
+/* Adaptation from the Buffer of erb.rb  */
+var EjsBuffer = function(pre_cmd, post_cmd) {
+	this.line = new Array();
+	this.script = "";
+	this.pre_cmd = pre_cmd;
+	this.post_cmd = post_cmd;
+	
+	for (var i=0; i<this.pre_cmd.length; i++)
+	{
+		this.push(pre_cmd[i]);
+	}
+}
+EjsBuffer.prototype = {
+	
+  push: function(cmd) {
+	this.line.push(cmd);
+  },
+
+  cr: function() {
+	this.script = this.script + this.line.join('; ');
+	this.line = new Array();
+	this.script = this.script + "\n";
+  },
+
+  close: function() {
+	if (this.line.length > 0)
+	{
+		for (var i=0; i<this.post_cmd.length; i++)
+		{
+			this.push(pre_cmd[i]);
+		}
+		this.script = this.script + this.line.join('; ');
+		line = null;
+	}
+  }
+ 	
+};
+
+/* Adaptation from the Compiler of erb.rb  */
+EjsCompiler = function(source, left) {
+	this.pre_cmd = ['___ejsO = "";'];
+	this.post_cmd = new Array();
+	this.source = ' ';	
+	if (source != null)
+	{
+		if (typeof source == 'string')
+		{
+		    source = source.replace(/\r\n/g, "\n");
+            source = source.replace(/\r/g,   "\n");
+			this.source = source;
+		}
+		else if (source.innerHTML)
+		{
+			this.source = source.innerHTML;
+		} 
+		if (typeof this.source != 'string')
+		{
+			this.source = "";
+		}
+	}
+	left = left || '<'
+	var right = '>'
+	switch(left) {
+		case '[':
+			right = ']'
+			break;
+		case '<':
+			break;
+		default:
+			throw left+' is not a supported deliminator'
+			break;
+	}
+	this.scanner = new EjsScanner(this.source, left, right);
+	this.out = '';
+}
+EjsCompiler.prototype = {
+  compile: function(options) {
+  	options = options || {};
+	this.out = '';
+	var put_cmd = "___ejsO += ";
+	var insert_cmd = put_cmd;
+	var buff = new EjsBuffer(this.pre_cmd, this.post_cmd);		
+	var content = '';
+	var clean = function(content)
+	{
+	    content = content.replace(/\\/g, '\\\\');
+        content = content.replace(/\n/g, '\\n');
+        content = content.replace(/"/g,  '\\"');
+        return content;
+	} 
+	this.scanner.scan(function(token, scanner) {
+		if (scanner.stag == null)
+		{
+			//alert(token+'|'+(token == "\n"))
+			switch(token) {
+				case '\n':
+					content = content + "\n";
+					buff.push(put_cmd + '"' + clean(content) + '";');
+					buff.cr()
+					content = '';
+					break;
+				case scanner.left_delimiter:
+				case scanner.left_equal:
+				case scanner.left_comment:
+					scanner.stag = token;
+					if (content.length > 0)
+					{
+						// Chould be content.dump in Ruby
+						
+						buff.push(put_cmd + '"' + clean(content) + '"');
+					}
+					content = '';
+					break;
+				case scanner.double_left:
+					content = content + scanner.left_delimiter;
+					break;
+				default:
+					content = content + token;
+					break;
+			}
+		}
+		else {
+			switch(token) {
+				case scanner.right_delimiter:
+					switch(scanner.stag) {
+						case scanner.left_delimiter:
+							if (content[content.length - 1] == '\n')
+							{
+								content = content.chop();
+								buff.push(content);
+								buff.cr();
+							}
+							else {
+								buff.push(content);
+							}
+							break;
+						case scanner.left_equal:
+							buff.push(insert_cmd + "(EjsScanner.to_text(" + content + "))");
+							break;
+					}
+					scanner.stag = null;
+					content = '';
+					break;
+				case scanner.double_right:
+					content = content + scanner.right_delimiter;
+					break;
+				default:
+					content = content + token;
+					break;
+			}
+		}
+	});
+	if (content.length > 0)
+	{
+		// Chould be content.dump in Ruby
+		buff.push(put_cmd + '"' + clean(content) + '"');
+	}
+	buff.close();
+	this.out = buff.script + ";";
+	var to_be_evaled = 'this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {'+this.out+" return ___ejsO;}}}catch(e){e.lineNumber=null;throw e;}};";
+	
+	try{
+		eval(to_be_evaled);
+	}catch(e){
+		if(typeof JSLINT != 'undefined'){
+			JSLINT(this.out)
+			for(var i = 0; i < JSLINT.errors.length; i++){
+				var error = JSLINT.errors[i];
+				if(error.reason != "Unnecessary semicolon."){
+					error.line++;
+					var e = new Error();
+					e.lineNumber = error.line;
+					e.message = error.reason;
+					if(options.url)
+						e.fileName = options.url;
+					throw e;
+				}
+			}
+		}else{
+			throw e;
+		}
+	}
+  }
+}
+
+
+//type, cache, folder
+EJS = function( options ){
+	this.set_options(options)
+	
+	if(options.url){
+		var template = EJS.get(options.url, this.cache)
+		if (template) return template;
+	    if (template == EJS.INVALID_PATH) return null;
+		this.text = EJS.request(options.url)
+		if(this.text == null){
+			//EJS.update(options.url, this.INVALID_PATH);
+			throw 'There is no template at '+options.url
+		}
+		this.name = options.url
+	}else if(options.element)
+	{
+		if(typeof options.element == 'string'){
+			var name = options.element
+			options.element = document.getElementById(  options.element )
+			if(options.element == null) throw name+'does not exist!'
+		}
+		if(options.element.value){
+			this.text = options.element.value
+		}else{
+			this.text = options.element.innerHTML
+		}
+		this.name = options.element.id
+		this.type = '['
+	}
+	var template = new EjsCompiler(this.text, this.type);
+
+	template.compile(options);
+
+	
+	EJS.update(this.name, this);
+	this.template = template
+}
+EJS.config = function(options){
+	EJS.cache = options.cache != null ? options.cache : EJS.cache
+	EJS.type = options.type != null ? options.type : EJS.type
+	var templates_directory = {} //nice and private container
+	
+	EJS.get = function(path, cache){
+		if(cache == false) return null;
+		if(templates_directory[path]) return templates_directory[path];
+  		return null;
+	}
+	
+	EJS.update = function(path, template) { 
+		if(path == null) return;
+		templates_directory[path] = template 
+	}
+	
+	EJS.INVALID_PATH =  -1;
+	
+	
+}
+EJS.config( {cache: true, type: '<' } )
+
+EJS.prototype = {
+	render : function(object){
+		var v = new EjsView(object);
+		return this.template.process.call(v, object,v);
+	},
+	out : function(){
+		return this.template.out
+	},
+	set_options : function(options){
+		this.type = options.type != null ? options.type : EJS.type
+		this.cache = options.cache != null ? options.cache : EJS.cache
+		this.text = options.text != null ? options.text : null
+		this.name = options.name != null ? options.name : null
+	},
+	// called without options, returns a function that takes the object
+	// called with options being a string, uses that as a url
+	// called with options as an object
+	update : function(element, options){
+		if(typeof element == 'string'){
+			element = document.getElementById(element)
+		}
+		if(options == null){
+			_template = this;
+			return function(object){
+				EJS.prototype.update.call(_template, element, object)
+			}
+		}
+		if(typeof options == 'string'){
+			params = {}
+			params.url = options
+			_template = this;
+			params.onComplete = function(request){
+				var object = eval( request.responseText )
+				EJS.prototype.update.call(_template, element, object)
+			}
+			EJS.ajax_request(params)
+		}else
+		{
+			element.innerHTML = this.render(options)
+		}
+	}
+}
+
+	EJS.newRequest = function(){
+	   var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }];
+	   for(var i = 0; i < factories.length; i++) {
+	        try {
+	            var request = factories[i]();
+	            if (request != null)  return request;
+	        }
+	        catch(e) { continue;}
+	   }
+	}
+	
+	EJS.request = function(path){
+	   var request = new EJS.newRequest()
+	   request.open("GET", path, false);
+	   
+	   try{request.send(null);}
+	   catch(e){return null;}
+	   
+	   if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null;
+	   
+	   return request.responseText
+	}
+	EJS.ajax_request = function(params){
+		params.method = ( params.method ? params.method : 'GET')
+		
+		var request = new EJS.newRequest();
+		request.onreadystatechange = function(){
+			if(request.readyState == 4){
+				if(request.status == 200){
+					params.onComplete(request)
+				}else
+				{
+					params.onComplete(request)
+				}
+			}
+		}
+		request.open(params.method, params.url)
+		request.send(null)
+	}
+//}
+
+

File helpers/ejs/view.js

+EjsView.prototype.date_tag = function(name, value , html_options) {
+    if(! (value instanceof Date))
+		value = new Date()
+	
+	var month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+	var years = [], months = [], days =[];
+	var year = value.getFullYear();
+	var month = value.getMonth();
+	var day = value.getDate();
+	for(var y = year - 15; y < year+15 ; y++)
+	{
+		years.push({value: y, text: y})
+	}
+	for(var m = 0; m < 12; m++)
+	{
+		months.push({value: (m), text: month_names[m]})
+	}
+	for(var d = 0; d < 31; d++)
+	{
+		days.push({value: (d+1), text: (d+1)})
+	}
+	var year_select = this.select_tag(name+'[year]', year, years, {id: name+'[year]'} )
+	var month_select = this.select_tag(name+'[month]', month, months, {id: name+'[month]'})
+	var day_select = this.select_tag(name+'[day]', day, days, {id: name+'[day]'})
+	
+    return year_select+month_select+day_select;
+}
+
+EjsView.prototype.form_tag = function(action, html_options) {
+                 
+    
+    html_options     = html_options                     || {};
+	html_options.action = action
+    if(html_options.multipart == true) {
+        html_options.method = 'post';
+        html_options.enctype = 'multipart/form-data';
+    }
+    
+    return this.start_tag_for('form', html_options)
+}
+
+EjsView.prototype.form_tag_end = function() { return this.tag_end('form'); }
+
+EjsView.prototype.hidden_field_tag   = function(name, value, html_options) { 
+    return this.input_field_tag(name, value, 'hidden', html_options); 
+}
+
+EjsView.prototype.input_field_tag = function(name, value , inputType, html_options) {
+    
+    html_options = html_options || {};
+    html_options.id  = html_options.id  || name;
+    html_options.value = value || '';
+    html_options.type = inputType || 'text';
+    html_options.name = name;
+    
+    return this.single_tag_for('input', html_options)
+}
+
+EjsView.prototype.is_current_page = function(url) {
+	return (window.location.href == url || window.location.pathname == url ? true : false);
+}
+
+EjsView.prototype.link_to = function(name, url, html_options) {
+    if(!name) var name = 'null';
+    if(!html_options) var html_options = {}
+	
+	if(html_options.confirm){
+		html_options.onclick = 
+		" var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} "
+		html_options.confirm = null;
+	}
+    html_options.href=url
+    return this.start_tag_for('a', html_options)+name+ this.tag_end('a');
+}
+
+EjsView.prototype.submit_link_to = function(name, url, html_options){
+	if(!name) var name = 'null';
+    if(!html_options) var html_options = {}
+    html_options.onclick = html_options.onclick  || '' ;
+	
+	if(html_options.confirm){
+		html_options.onclick = 
+		" var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} "
+		html_options.confirm = null;
+	}
+	
+    html_options.value = name;
+	html_options.type = 'submit'
+    html_options.onclick=html_options.onclick+
+		(url ? this.url_for(url) : '')+'return false;';
+    //html_options.href='#'+(options ? Routes.url_for(options) : '')
+	return this.start_tag_for('input', html_options)
+}
+
+EjsView.prototype.link_to_if = function(condition, name, url, html_options, post, block) {
+	return this.link_to_unless((condition == false), name, url, html_options, post, block);
+}
+
+EjsView.prototype.link_to_unless = function(condition, name, url, html_options, block) {
+	html_options = html_options || {};
+	if(condition) {
+		if(block && typeof block == 'function') {
+			return block(name, url, html_options, block);
+		} else {
+			return name;
+		}
+	} else
+		return this.link_to(name, url, html_options);
+}
+
+EjsView.prototype.link_to_unless_current = function(name, url, html_options, block) {
+	html_options = html_options || {};
+	return this.link_to_unless(this.is_current_page(url), name, url, html_options, block)
+}
+
+
+EjsView.prototype.password_field_tag = function(name, value, html_options) { return this.input_field_tag(name, value, 'password', html_options); }
+
+EjsView.prototype.select_tag = function(name, value, choices, html_options) {     
+    html_options = html_options || {};
+    html_options.id  = html_options.id  || name;
+    html_options.value = value;
+	html_options.name = name;
+    
+    var txt = ''
+    txt += this.start_tag_for('select', html_options)
+    
+    for(var i = 0; i < choices.length; i++)
+    {
+        var choice = choices[i];
+        var optionOptions = {value: choice.value}
+        if(choice.value == value)
+            optionOptions.selected ='selected'
+        txt += this.start_tag_for('option', optionOptions )+choice.text+this.tag_end('option')
+    }
+    txt += this.tag_end('select');
+    return txt;
+}
+
+EjsView.prototype.single_tag_for = function(tag, html_options) { return this.tag(tag, html_options, '/>');}
+
+EjsView.prototype.start_tag_for = function(tag, html_options)  { return this.tag(tag, html_options); }
+
+EjsView.prototype.submit_tag = function(name, html_options) {  
+    html_options = html_options || {};
+    //html_options.name  = html_options.id  || 'commit';
+    html_options.type = html_options.type  || 'submit';
+    html_options.value = name || 'Submit';
+    return this.single_tag_for('input', html_options);
+}
+
+EjsView.prototype.tag = function(tag, html_options, end) {
+    if(!end) var end = '>'
+    var txt = ' '
+    for(var attr in html_options) { 
+	   if(html_options[attr] != null)
+        var value = html_options[attr].toString();
+       else
+        var value=''
+       if(attr == "Class") // special case because "class" is a reserved word in IE
+        attr = "class";
+       if( value.indexOf("'") != -1 )
+            txt += attr+'=\"'+value+'\" ' 
+       else
+            txt += attr+"='"+value+"' " 
+    }
+    return '<'+tag+txt+end;
+}
+
+EjsView.prototype.tag_end = function(tag)             { return '</'+tag+'>'; }
+
+EjsView.prototype.text_area_tag = function(name, value, html_options) { 
+    html_options = html_options || {};
+    html_options.id  = html_options.id  || name;
+    html_options.name  = html_options.name  || name;
+	value = value || ''
+    if(html_options.size) {
+        html_options.cols = html_options.size.split('x')[0]
+        html_options.rows = html_options.size.split('x')[1]
+        delete html_options.size
+    }
+    
+    html_options.cols = html_options.cols  || 50;
+    html_options.rows = html_options.rows  || 4;
+    
+    return  this.start_tag_for('textarea', html_options)+value+this.tag_end('textarea')
+}
+EjsView.prototype.text_tag = EjsView.prototype.text_area_tag
+
+EjsView.prototype.text_field_tag     = function(name, value, html_options) { return this.input_field_tag(name, value, 'text', html_options); }
+
+EjsView.prototype.url_for = function(url) {
+        return 'window.location="'+url+'";'
+}
+EjsView.prototype.img_tag = function(image_location, alt, options){
+	options = options || {};
+	options.src = image_location
+	options.alt = alt
+	return this.single_tag_for('img', options)
+}

File helpers/md5.js

+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ keep
+ */
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ keep
+ */
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ keep
+ */
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}

File helpers/template.js

+// simple helper to reder template from ejs
+//
+
+function template(str, data) {
+    html = new EJS({text: str}).render(data);
+    return html;
+}
+
+

File lib/helpers/ejs/ejs.js

-/*--------------------------------------------------------------------------
- *  EJS - Embedded JavaScript, version 0.1.0
- *  Copyright (c) 2007 Edward Benson
- *  http://www.edwardbenson.com/projects/ejs
- *  ------------------------------------------------------------------------
- *
- *  EJS is freely distributable under the terms of an MIT-style license.
- *
- *  EJS is a client-side preprocessing engine written in and for JavaScript.
- *  If you have used PHP, ASP, JSP, or ERB then you get the idea: code embedded
- *  in <% // Code here %> tags will be executed, and code embedded in <%= .. %> 
- *  tags will be evaluated and appended to the output. 
- * 
- *  This is essentially a direct JavaScript port of Masatoshi Seki's erb.rb 
- *  from the Ruby Core, though it contains a subset of ERB's functionality. 
- * 
- *  Requirements:
- *      prototype.js
- * 
- *  Usage:
- *      // source should be either a string or a DOM node whose innerHTML
- *      // contains EJB source.
- *  	var source = "<% var ejb="EJB"; %><h1>Hello, <%= ejb %>!</h1>"; 
- *      var compiler = new EjsCompiler(source);		
- *	    compiler.compile();	
- *	    var output = eval(compiler.out);
- *      alert(output); // -> "<h1>Hello, EJB!</h1>"
- *       
- *  For a demo:      see demo.html
- *  For the license: see license.txt
- *
- *--------------------------------------------------------------------------*/
-
-/* Make a split function like Ruby's: "abc".split(/b/) -> ['a', 'b', 'c'] */
-String.prototype.rsplit = function(regex) {
-	var item = this;
-	var result = regex.exec(item);
-	var retArr = new Array();
-	while (result != null)
-	{
-		var first_idx = result.index;
-		var last_idx = regex.lastIndex;
-		if ((first_idx) != 0)
-		{
-			var first_bit = item.substring(0,first_idx);
-			retArr.push(item.substring(0,first_idx));
-			item = item.slice(first_idx);
-		}		
-		retArr.push(result[0]);
-		item = item.slice(result[0].length);
-		result = regex.exec(item);	
-	}
-	if (! item == '')
-	{
-		retArr.push(item);
-	}
-	return retArr;
-};
-
-/* Chop is nice to have too */
-String.prototype.chop = function() {
-	return this.substr(0, this.length - 1);
-}
-
-/* Adaptation from the Scanner of erb.rb  */
-var EjsScanner = function(source, left, right) {
-	this.left_delimiter = 	left +'%'	//<%
-	this.right_delimiter = 	'%'+right	//>
-	this.double_left = 		left+'%%'
-	this.double_right = 	'%%'+right
-	this.left_equal = 		left+'%='
-	this.left_comment = 	left+'%#'
-	if(left=='[')
-		this.SplitRegexp = /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/;
-	else
-		this.SplitRegexp = new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)') 
-	
-	this.source = source;
-	this.stag = null;
-	this.lines = 0;
-};
-EjsView = function(data){
-	this.data = data
-}
-EjsView.prototype.partial = function(options, data){
-	if(!data) data = this.data;
-	return new EJS(options).render(data);
-}
-
-EjsScanner.to_text = function(input){
-	if(input == null || input === undefined)
-        return '';
-    if(input instanceof Date)
-		return input.toDateString();
-	if(input.toString) 
-        return input.toString()
-	return '';
-}
-
-EjsScanner.prototype = {
-
-  /* For each line, scan! */
-  scan: function(block) {
-     scanline = this.scanline;
-	 regex = this.SplitRegexp;
-	 if (! this.source == '')
-	 {
-	 	 var source_split = this.source.rsplit(/\n/);
-	 	 for(var i=0; i<source_split.length; i++) {
-		 	 var item = source_split[i];
-			 this.scanline(item, regex, block);
-		 }
-	 }
-  },
-  
-  /* For each token, block! */
-  scanline: function(line, regex, block) {
-	 this.lines++
-	 var line_split = line.rsplit(regex);
- 	 for(var i=0; i<line_split.length; i++) {
-	   var token = line_split[i];
-       if (token != null) {
-		   	try{
-	         	block(token, this);
-		 	}catch(e){
-				throw {type: 'EjsScanner', line: this.lines}
-			}
-       }
-	 }
-  }
-};
-
-/* Adaptation from the Buffer of erb.rb  */
-var EjsBuffer = function(pre_cmd, post_cmd) {
-	this.line = new Array();
-	this.script = "";
-	this.pre_cmd = pre_cmd;
-	this.post_cmd = post_cmd;
-	
-	for (var i=0; i<this.pre_cmd.length; i++)
-	{
-		this.push(pre_cmd[i]);
-	}
-}
-EjsBuffer.prototype = {
-	
-  push: function(cmd) {
-	this.line.push(cmd);
-  },
-
-  cr: function() {
-	this.script = this.script + this.line.join('; ');
-	this.line = new Array();
-	this.script = this.script + "\n";
-  },
-
-  close: function() {
-	if (this.line.length > 0)
-	{
-		for (var i=0; i<this.post_cmd.length; i++)
-		{
-			this.push(pre_cmd[i]);
-		}
-		this.script = this.script + this.line.join('; ');
-		line = null;
-	}
-  }
- 	
-};
-
-/* Adaptation from the Compiler of erb.rb  */
-EjsCompiler = function(source, left) {
-	this.pre_cmd = ['___ejsO = "";'];
-	this.post_cmd = new Array();
-	this.source = ' ';	
-	if (source != null)
-	{
-		if (typeof source == 'string')
-		{
-		    source = source.replace(/\r\n/g, "\n");
-            source = source.replace(/\r/g,   "\n");
-			this.source = source;
-		}
-		else if (source.innerHTML)
-		{
-			this.source = source.innerHTML;
-		} 
-		if (typeof this.source != 'string')
-		{
-			this.source = "";
-		}
-	}
-	left = left || '<'
-	var right = '>'
-	switch(left) {
-		case '[':
-			right = ']'
-			break;
-		case '<':
-			break;
-		default:
-			throw left+' is not a supported deliminator'
-			break;
-	}
-	this.scanner = new EjsScanner(this.source, left, right);
-	this.out = '';
-}
-EjsCompiler.prototype = {
-  compile: function(options) {
-  	options = options || {};
-	this.out = '';
-	var put_cmd = "___ejsO += ";
-	var insert_cmd = put_cmd;
-	var buff = new EjsBuffer(this.pre_cmd, this.post_cmd);		
-	var content = '';
-	var clean = function(content)
-	{
-	    content = content.replace(/\\/g, '\\\\');
-        content = content.replace(/\n/g, '\\n');
-        content = content.replace(/"/g,  '\\"');
-        return content;
-	} 
-	this.scanner.scan(function(token, scanner) {
-		if (scanner.stag == null)
-		{
-			//alert(token+'|'+(token == "\n"))
-			switch(token) {
-				case '\n':
-					content = content + "\n";
-					buff.push(put_cmd + '"' + clean(content) + '";');
-					buff.cr()
-					content = '';
-					break;
-				case scanner.left_delimiter:
-				case scanner.left_equal:
-				case scanner.left_comment:
-					scanner.stag = token;
-					if (content.length > 0)
-					{
-						// Chould be content.dump in Ruby
-						
-						buff.push(put_cmd + '"' + clean(content) + '"');
-					}
-					content = '';
-					break;
-				case scanner.double_left:
-					content = content + scanner.left_delimiter;
-					break;
-				default:
-					content = content + token;
-					break;
-			}
-		}
-		else {
-			switch(token) {
-				case scanner.right_delimiter:
-					switch(scanner.stag) {
-						case scanner.left_delimiter:
-							if (content[content.length - 1] == '\n')
-							{
-								content = content.chop();
-								buff.push(content);
-								buff.cr();
-							}
-							else {
-								buff.push(content);
-							}
-							break;
-						case scanner.left_equal:
-							buff.push(insert_cmd + "(EjsScanner.to_text(" + content + "))");
-							break;
-					}
-					scanner.stag = null;
-					content = '';
-					break;
-				case scanner.double_right:
-					content = content + scanner.right_delimiter;
-					break;
-				default:
-					content = content + token;
-					break;
-			}
-		}
-	});
-	if (content.length > 0)
-	{
-		// Chould be content.dump in Ruby
-		buff.push(put_cmd + '"' + clean(content) + '"');
-	}
-	buff.close();
-	this.out = buff.script + ";";
-	var to_be_evaled = 'this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {'+this.out+" return ___ejsO;}}}catch(e){e.lineNumber=null;throw e;}};";
-	
-	try{
-		eval(to_be_evaled);
-	}catch(e){
-		if(typeof JSLINT != 'undefined'){
-			JSLINT(this.out)
-			for(var i = 0; i < JSLINT.errors.length; i++){
-				var error = JSLINT.errors[i];
-				if(error.reason != "Unnecessary semicolon."){
-					error.line++;
-					var e = new Error();
-					e.lineNumber = error.line;
-					e.message = error.reason;
-					if(options.url)
-						e.fileName = options.url;
-					throw e;
-				}
-			}
-		}else{
-			throw e;
-		}
-	}
-  }
-}
-
-
-//type, cache, folder
-EJS = function( options ){
-	this.set_options(options)
-	
-	if(options.url){
-		var template = EJS.get(options.url, this.cache)
-		if (template) return template;
-	    if (template == EJS.INVALID_PATH) return null;
-		this.text = EJS.request(options.url)
-		if(this.text == null){
-			//EJS.update(options.url, this.INVALID_PATH);
-			throw 'There is no template at '+options.url
-		}
-		this.name = options.url
-	}else if(options.element)
-	{
-		if(typeof options.element == 'string'){
-			var name = options.element
-			options.element = document.getElementById(  options.element )
-			if(options.element == null) throw name+'does not exist!'
-		}
-		if(options.element.value){
-			this.text = options.element.value
-		}else{
-			this.text = options.element.innerHTML
-		}
-		this.name = options.element.id
-		this.type = '['
-	}
-	var template = new EjsCompiler(this.text, this.type);
-
-	template.compile(options);
-
-	
-	EJS.update(this.name, this);
-	this.template = template
-}
-EJS.config = function(options){
-	EJS.cache = options.cache != null ? options.cache : EJS.cache
-	EJS.type = options.type != null ? options.type : EJS.type
-	var templates_directory = {} //nice and private container
-	
-	EJS.get = function(path, cache){
-		if(cache == false) return null;
-		if(templates_directory[path]) return templates_directory[path];
-  		return null;
-	}
-	
-	EJS.update = function(path, template) { 
-		if(path == null) return;
-		templates_directory[path] = template 
-	}
-	
-	EJS.INVALID_PATH =  -1;
-	
-	
-}
-EJS.config( {cache: true, type: '<' } )
-
-EJS.prototype = {
-	render : function(object){
-		var v = new EjsView(object);
-		return this.template.process.call(v, object,v);
-	},
-	out : function(){
-		return this.template.out
-	},
-	set_options : function(options){
-		this.type = options.type != null ? options.type : EJS.type
-		this.cache = options.cache != null ? options.cache : EJS.cache
-		this.text = options.text != null ? options.text : null
-		this.name = options.name != null ? options.name : null
-	},
-	// called without options, returns a function that takes the object
-	// called with options being a string, uses that as a url
-	// called with options as an object
-	update : function(element, options){
-		if(typeof element == 'string'){
-			element = document.getElementById(element)
-		}
-		if(options == null){
-			_template = this;
-			return function(object){
-				EJS.prototype.update.call(_template, element, object)
-			}
-		}
-		if(typeof options == 'string'){
-			params = {}
-			params.url = options
-			_template = this;
-			params.onComplete = function(request){
-				var object = eval( request.responseText )
-				EJS.prototype.update.call(_template, element, object)
-			}
-			EJS.ajax_request(params)
-		}else
-		{
-			element.innerHTML = this.render(options)
-		}
-	}
-}
-
-	EJS.newRequest = function(){
-	   var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }];
-	   for(var i = 0; i < factories.length; i++) {
-	        try {
-	            var request = factories[i]();
-	            if (request != null)  return request;
-	        }
-	        catch(e) { continue;}
-	   }
-	}
-	
-	EJS.request = function(path){
-	   var request = new EJS.newRequest()
-	   request.open("GET", path, false);
-	   
-	   try{request.send(null);}
-	   catch(e){return null;}
-	   
-	   if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null;
-	   
-	   return request.responseText
-	}
-	EJS.ajax_request = function(params){
-		params.method = ( params.method ? params.method : 'GET')
-		
-		var request = new EJS.newRequest();
-		request.onreadystatechange = function(){
-			if(request.readyState == 4){
-				if(request.status == 200){
-					params.onComplete(request)
-				}else
-				{
-					params.onComplete(request)
-				}
-			}
-		}
-		request.open(params.method, params.url)
-		request.send(null)
-	}
-//}
-
-

File lib/helpers/ejs/view.js

-EjsView.prototype.date_tag = function(name, value , html_options) {
-    if(! (value instanceof Date))
-		value = new Date()
-	
-	var month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
-	var years = [], months = [], days =[];
-	var year = value.getFullYear();
-	var month = value.getMonth();
-	var day = value.getDate();
-	for(var y = year - 15; y < year+15 ; y++)
-	{
-		years.push({value: y, text: y})
-	}
-	for(var m = 0; m < 12; m++)
-	{
-		months.push({value: (m), text: month_names[m]})
-	}
-	for(var d = 0; d < 31; d++)
-	{
-		days.push({value: (d+1), text: (d+1)})
-	}
-	var year_select = this.select_tag(name+'[year]', year, years, {id: name+'[year]'} )
-	var month_select = this.select_tag(name+'[month]', month, months, {id: name+'[month]'})
-	var day_select = this.select_tag(name+'[day]', day, days, {id: name+'[day]'})
-	
-    return year_select+month_select+day_select;
-}
-
-EjsView.prototype.form_tag = function(action, html_options) {
-                 
-    
-    html_options     = html_options                     || {};
-	html_options.action = action
-    if(html_options.multipart == true) {
-        html_options.method = 'post';
-        html_options.enctype = 'multipart/form-data';
-    }
-    
-    return this.start_tag_for('form', html_options)
-}
-
-EjsView.prototype.form_tag_end = function() { return this.tag_end('form'); }
-
-EjsView.prototype.hidden_field_tag   = function(name, value, html_options) { 
-    return this.input_field_tag(name, value, 'hidden', html_options); 
-}
-
-EjsView.prototype.input_field_tag = function(name, value , inputType, html_options) {
-    
-    html_options = html_options || {};
-    html_options.id  = html_options.id  || name;
-    html_options.value = value || '';
-    html_options.type = inputType || 'text';
-    html_options.name = name;
-    
-    return this.single_tag_for('input', html_options)
-}
-
-EjsView.prototype.is_current_page = function(url) {
-	return (window.location.href == url || window.location.pathname == url ? true : false);
-}
-
-EjsView.prototype.link_to = function(name, url, html_options) {
-    if(!name) var name = 'null';
-    if(!html_options) var html_options = {}
-	
-	if(html_options.confirm){
-		html_options.onclick = 
-		" var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} "
-		html_options.confirm = null;
-	}
-    html_options.href=url
-    return this.start_tag_for('a', html_options)+name+ this.tag_end('a');
-}
-
-EjsView.prototype.submit_link_to = function(name, url, html_options){
-	if(!name) var name = 'null';
-    if(!html_options) var html_options = {}
-    html_options.onclick = html_options.onclick  || '' ;
-	
-	if(html_options.confirm){
-		html_options.onclick = 
-		" var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} "
-		html_options.confirm = null;
-	}
-	
-    html_options.value = name;
-	html_options.type = 'submit'
-    html_options.onclick=html_options.onclick+
-		(url ? this.url_for(url) : '')+'return false;';
-    //html_options.href='#'+(options ? Routes.url_for(options) : '')
-	return this.start_tag_for('input', html_options)
-}
-
-EjsView.prototype.link_to_if = function(condition, name, url, html_options, post, block) {
-	return this.link_to_unless((condition == false), name, url, html_options, post, block);
-}
-
-EjsView.prototype.link_to_unless = function(condition, name, url, html_options, block) {
-	html_options = html_options || {};
-	if(condition) {
-		if(block && typeof block == 'function') {
-			return block(name, url, html_options, block);
-		} else {
-			return name;
-		}
-	} else
-		return this.link_to(name, url, html_options);
-}
-
-EjsView.prototype.link_to_unless_current = function(name, url, html_options, block) {
-	html_options = html_options || {};
-	return this.link_to_unless(this.is_current_page(url), name, url, html_options, block)
-}
-
-
-EjsView.prototype.password_field_tag = function(name, value, html_options) { return this.input_field_tag(name, value, 'password', html_options); }
-
-EjsView.prototype.select_tag = function(name, value, choices, html_options) {     
-    html_options = html_options || {};
-    html_options.id  = html_options.id  || name;
-    html_options.value = value;
-	html_options.name = name;
-    
-    var txt = ''
-    txt += this.start_tag_for('select', html_options)
-    
-    for(var i = 0; i < choices.length; i++)
-    {
-        var choice = choices[i];
-        var optionOptions = {value: choice.value}
-        if(choice.value == value)
-            optionOptions.selected ='selected'
-        txt += this.start_tag_for('option', optionOptions )+choice.text+this.tag_end('option')
-    }
-    txt += this.tag_end('select');
-    return txt;
-}
-
-EjsView.prototype.single_tag_for = function(tag, html_options) { return this.tag(tag, html_options, '/>');}
-
-EjsView.prototype.start_tag_for = function(tag, html_options)  { return this.tag(tag, html_options); }
-
-EjsView.prototype.submit_tag = function(name, html_options) {  
-    html_options = html_options || {};
-    //html_options.name  = html_options.id  || 'commit';
-    html_options.type = html_options.type  || 'submit';
-    html_options.value = name || 'Submit';
-    return this.single_tag_for('input', html_options);
-}
-
-EjsView.prototype.tag = function(tag, html_options, end) {
-    if(!end) var end = '>'
-    var txt = ' '
-    for(var attr in html_options) { 
-	   if(html_options[attr] != null)
-        var value = html_options[attr].toString();
-       else
-        var value=''
-       if(attr == "Class") // special case because "class" is a reserved word in IE
-        attr = "class";
-       if( value.indexOf("'") != -1 )
-            txt += attr+'=\"'+value+'\" ' 
-       else
-            txt += attr+"='"+value+"' " 
-    }
-    return '<'+tag+txt+end;
-}
-
-EjsView.prototype.tag_end = function(tag)             { return '</'+tag+'>'; }
-
-EjsView.prototype.text_area_tag = function(name, value, html_options) { 
-    html_options = html_options || {};
-    html_options.id  = html_options.id  || name;
-    html_options.name  = html_options.name  || name;
-	value = value || ''
-    if(html_options.size) {
-        html_options.cols = html_options.size.split('x')[0]
-        html_options.rows = html_options.size.split('x')[1]
-        delete html_options.size
-    }
-    
-    html_options.cols = html_options.cols  || 50;
-    html_options.rows = html_options.rows  || 4;
-    
-    return  this.start_tag_for('textarea', html_options)+value+this.tag_end('textarea')
-}
-EjsView.prototype.text_tag = EjsView.prototype.text_area_tag
-
-EjsView.prototype.text_field_tag     = function(name, value, html_options) { return this.input_field_tag(name, value, 'text', html_options); }
-
-EjsView.prototype.url_for = function(url) {
-        return 'window.location="'+url+'";'
-}
-EjsView.prototype.img_tag = function(image_location, alt, options){
-	options = options || {};
-	options.src = image_location
-	options.alt = alt
-	return this.single_tag_for('img', options)
-}

File lib/helpers/md5.js

-/*
- * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
- * Digest Algorithm, as defined in RFC 1321.
- * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
- * Distributed under the BSD License
- * See http://pajhome.org.uk/crypt/md5 for more info.
- */
-
-/*
- * Configurable variables. You may need to tweak these to be compatible with
- * the server-side, but the defaults work in most cases.
- */
-var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
-var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
-var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
-
-/*
- * These are the functions you'll usually want to call
- * They take string arguments and return either hex or base-64 encoded strings
- */
-function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
-function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
-function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
-function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
-function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
-function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
-
-/*
- * Perform a simple self-test to see if the VM is working
- */
-function md5_vm_test()
-{
-  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
-}
-
-/*
- * Calculate the MD5 of an array of little-endian words, and a bit length
- keep
- */
-function core_md5(x, len)
-{
-  /* append padding */
-  x[len >> 5] |= 0x80 << ((len) % 32);
-  x[(((len + 64) >>> 9) << 4) + 14] = len;
-
-  var a =  1732584193;
-  var b = -271733879;
-  var c = -1732584194;
-  var d =  271733878;
-
-  for(var i = 0; i < x.length; i += 16)
-  {
-    var olda = a;
-    var oldb = b;
-    var oldc = c;
-    var oldd = d;
-
-    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
-    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
-    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
-    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
-    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
-    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
-    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
-    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
-    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
-    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
-    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
-    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
-    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
-    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
-    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
-    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
-
-    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
-    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
-    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
-    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
-    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
-    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
-    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
-    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
-    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
-    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
-    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
-    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
-    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
-    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
-    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
-    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
-
-    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
-    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
-    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
-    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
-    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
-    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
-    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
-    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
-    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
-    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
-    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
-    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
-    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
-    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
-    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
-    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
-
-    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
-    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
-    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
-    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
-    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
-    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
-    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
-    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
-    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
-    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
-    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
-    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
-    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
-    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
-    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
-    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
-
-    a = safe_add(a, olda);
-    b = safe_add(b, oldb);
-    c = safe_add(c, oldc);
-    d = safe_add(d, oldd);
-  }
-  return Array(a, b, c, d);
-
-}
-
-/*
- * These functions implement the four basic operations the algorithm uses.
- */
-function md5_cmn(q, a, b, x, s, t)
-{
-  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
-}
-function md5_ff(a, b, c, d, x, s, t)
-{
-  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
-}
-function md5_gg(a, b, c, d, x, s, t)
-{
-  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
-}
-function md5_hh(a, b, c, d, x, s, t)
-{
-  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
-}
-function md5_ii(a, b, c, d, x, s, t)
-{
-  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
-}
-
-/*
- * Calculate the HMAC-MD5, of a key and some data
- */
-function core_hmac_md5(key, data)
-{
-  var bkey = str2binl(key);
-  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
-
-  var ipad = Array(16), opad = Array(16);
-  for(var i = 0; i < 16; i++)
-  {
-    ipad[i] = bkey[i] ^ 0x36363636;
-    opad[i] = bkey[i] ^ 0x5C5C5C5C;
-  }
-
-  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
-  return core_md5(opad.concat(hash), 512 + 128);
-}
-
-/*
- * Add integers, wrapping at 2^32. This uses 16-bit operations internally
- * to work around bugs in some JS interpreters.
- */
-function safe_add(x, y)
-{
-  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
-  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
-  return (msw << 16) | (lsw & 0xFFFF);
-}
-
-/*
- * Bitwise rotate a 32-bit number to the left.
- */
-function bit_rol(num, cnt)
-{
-  return (num << cnt) | (num >>> (32 - cnt));
-}
-
-/*
- * Convert a string to an array of little-endian words
- * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
- keep
- */
-function str2binl(str)
-{
-  var bin = Array();
-  var mask = (1 << chrsz) - 1;
-  for(var i = 0; i < str.length * chrsz; i += chrsz)
-    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
-  return bin;
-}
-
-/*
- * Convert an array of little-endian words to a string
- */
-function binl2str(bin)
-{
-  var str = "";
-  var mask = (1 << chrsz) - 1;
-  for(var i = 0; i < bin.length * 32; i += chrsz)
-    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
-  return str;
-}
-
-/*
- * Convert an array of little-endian words to a hex string.
- keep
- */
-function binl2hex(binarray)
-{
-  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
-  var str = "";
-  for(var i = 0; i < binarray.length * 4; i++)
-  {
-    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
-           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
-  }
-  return str;
-}
-
-/*
- * Convert an array of little-endian words to a base-64 string
- */
-function binl2b64(binarray)
-{
-  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-  var str = "";
-  for(var i = 0; i < binarray.length * 4; i += 3)
-  {
-    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
-                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
-                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
-    for(var j = 0; j < 4; j++)
-    {
-      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
-      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
-    }
-  }
-  return str;
-}

File lib/helpers/template.js

-// simple helper to reder template from ejs
-//
-
-function template(str, data) {
-    html = new EJS({text: str}).render(data);
-    return html;
-}
-
-

File lib/templates/edit.html

-<!DOCTYPE html>
-<html lang="fr">
-<head>
-    <meta charset="utf-8"/>
-    <title>benoît chesneau web - edit</title>
-
-    <!--[if IE]>
-
-    <script>
-        // allow IE to recognize HTMl5 elements
-        document.createElement('section');
-        document.createElement('article');
-        document.createElement('aside');
-        document.createElement('footer');
-        document.createElement('header');
-        document.createElement('nav');
-        document.createElement('time');
-
-    </script>
-    <![endif]-->
-    <link rel="openid.server" href="http://www.myopenid.com/server">
-    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
-    <link rel="home index" href="http://benoitc.org/" type="text/html">
-    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
-
-    <link rel="stylesheet" href="../../css/benoitc.css" type="text/css" media="screen, projection" />
-    
-
-
-</head>
-
-
-<body>
-        <header>
-        <h1>
-            <a rel="me author" href="../../benoitc.html">Benoît Chesneau</a>
-        </h1>
-        </header>
-        <div id="edit">
-            <h2>Nouvel article</h2>
-            <form id="fedit" name="fedit" action="new.html"
-                method="post">
-                        
-                <textarea name="body" id="body" cols="80"
-                    rows="20"></textarea>
-                
-                <ol>
-                    <li><label for="title">Titre<label><input type="text"
-                            name="title" id="title" value=""></li>
-
-                    <li><label for="labels">Libellés</label><input type="text"
-                name="labels" id="labels" value=""></li>
-                </ol>
-                
-                <p><input type="submit" name="save" id="save" value="Save">
-                or <a href="<%= index %>">Cancel</a> <span id="saved" style="display:none;">Saved</span></p>
-            </form>
-            <div id="mdpreview"></div>
-        </div>
-
-        <footer id="main-footer">
-        <p>2009 (c) <a href="../../benoitc.html">Benoît Chesneau</a> - <a rel="license" href="http://creativecommons.org/licenses/by/2.0/fr/">Certains droits reservés</a>.</p>
-        </footer> 
-
-    
-</body>
-
-    <script src="/_utils/script/json2.js"></script>
-    <script src="/_utils/script/jquery.js"></script>
-    <script src="/_utils/script/jquery.cookies.js"></script>
-    <script src="/_utils/script/jquery.couch.js"></script>
-    <script src="../../js/showdown.js"></script>
-    <script src="../../js/textarea.jquery.js"></script>
-    <script src="../../js/jquery.couchapp.js"></script>
-    <script src="../../js/editor.js"></script>
-    <script src="../../js/strftime.js"></script>
-    <script src="../../js/blog.js"></script>
-    <script src="../../js/urlify.js"></script>
-
-    <script>
-        $(document).ready(function() {
-
-            $.CouchApp(function(app) {
-                app.loggedInNow(function(login) {
-                    $("header").prepend('<span id="login">'+login+'</span>');
-                    
-                    var B = new Blog(app);
-
-                    var postForm = app.docForm("form#fedit", {
-                        id : <%= docid %>,
-                        fields : ["title", "body", "labels"],
-                        template : {
-                            doc_type : "post",
-                            format : "markdown",
-                            author : login
-                        },
-                        onLoad : function(doc) {
-                            if (doc._id) {
-                                $("#edit h2").html('Édition de ' + B.link_for(doc._id));
-                            } 
-                        },
-                        beforeSave : function(doc) {
-                            if (doc.body)
-                                doc.html = B.formatBody(doc.body);
-
-                            if (!doc.created_at) {
-                                doc.created_at = new Date().rfc3339();
-                            }
-
-                            if (!doc.slug && doc.title) {
-                                doc.slug = doc.created_at.slice(0, 10).replace(/\-*/g, '') 
-                                + "_" + URLify(doc.title, 255);
-                                doc._id = doc.slug;
-                            }
-
-                            doc.updated = new Date().rfc3339();
-                            if(doc.labels) {
-                                doc.labels = doc.labels.split(",");
-                                for(var idx in doc.labels) {
-                                    doc.labels[idx] = $.trim(doc.labels[idx]);
-                                }
-                            } 
-                        },
-                        success : function(resp) {
-                           $("#saved").text("Enregistré _rev: "+resp.rev).fadeIn(500).fadeOut(3000);
-                           $("#edit h2").html('Édition de ' + B.link_for(resp.id));
-                        }
-                    });  
-
-                    new Editor(); 
-                    }, function() {
-                    // callback
-                    $('body').append('<a href="../../account.html#'+document.location+'">redirect</a>');
-                    var absurl = $('body a:last')[0].href;
-                    document.location = absurl;
-                });
-            });
-        
-        });
-    </script>
-</html>

File lib/templates/index/head.html

-<!DOCTYPE html>
-<html lang="fr">
-<head>
-    <meta charset="utf-8"/>
-    <title>benoît chesneau web, artisan web.</title>
-
-    <!--[if IE]>
-
-    <script>
-        // allow IE to recognize HTMl5 elements
-        document.createElement('section');
-        document.createElement('article');
-        document.createElement('aside');
-        document.createElement('footer');
-        document.createElement('header');
-        document.createElement('nav');
-        document.createElement('time');
-
-    </script>
-    <![endif]-->
-    <link rel="openid.server" href="http://www.myopenid.com/server">
-    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
-    <link rel="home index" href="http://benoitc.org/" type="text/html">
-    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
-    <link type='application/atom+xml' href='<%= feedPath %>' rel='alternate' title='Writings'>
-
-    <link rel="stylesheet" href="../../css/benoitc.css" type="text/css" media="screen, projection" />
-</head>
-
-
-<body class="index">
-    <div id="container">
-        <header class="page">
-            <nav id="mainav">
-                <ul>
-                    <li><a href="<%= archivesPath %>">archives</a></li>
-                    <li><a href="<%= feedPath %>" type='application/atom+xml' class="atom">suivre</a></li>
-                </ul>
-            </nav>
-            <h1>
-                <a rel="me author" href="../../benoitc.html">Benoît Chesneau</a>
-            </h1>
-            <h2>artisan web</h2>
-
-            
-        </header>

File lib/templates/index/row.html

-<article class="entry article">
-    <header class="meta">
-        <p><time title="GMT" datetime="<%= post.created_at %>"
-        class="caps"><%= fcreated_at %></time></p>
-    </header>
-    <h3>
-        <a href="<%= link %>"><%= post.title %></a>
-    </h3>
-    <p><%= post.summary %></p>
-</article>

File lib/templates/index/tail.html

-        <p class="next"><a href="<%= nextPath %>">articles suivants »</a></p>
-
-        <footer id="main-footer">
-            <p>2009 (c) <a href="../../benoitc.html">Benoît Chesneau</a> - <a rel="license" href="http://creativecommons.org/licenses/by/2.0/fr/">Certains droits reservés</a>.</p>
-        </footer>
-    </div>
-</body>
-    <script src="/_utils/script/json2.js"></script>
-    <script src="/_utils/script/jquery.js"></script>
-    <script src="/_utils/script/jquery.couch.js"></script>
-    <script src="../../js/jquery.couchapp.js"></script>
-    <script src="../../js/strftime.js"></script>
-    <script src="../../js/blog.js"></script>
-    <script>
-        $(document).ready(function() {
-            localizeDates();
-        });
-
-    </script>
-</html>

File lib/templates/post.html

-<!DOCTYPE html>
-<html lang="fr">
-<head>
-    <meta charset="utf-8"/>
-    <title>benoît chesneau web - <%= doc.title %></title>
-
-    <!--[if IE]>
-
-    <script>
-        // allow IE to recognize HTMl5 elements
-        document.createElement('section');
-        document.createElement('article');
-        document.createElement('aside');
-        document.createElement('footer');
-        document.createElement('header');
-        document.createElement('nav');
-        document.createElement('time');
-
-    </script>
-    <![endif]-->
-    <link rel="openid.server" href="http://www.myopenid.com/server">
-    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
-    <link rel="home index" href="http://benoitc.org" type="text/html">
-    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
-
-    <link rel="stylesheet" href="../../css/benoitc.css" type="text/css"