Commits

Anonymous committed e7a1387

use inditeweb vendor

Comments (0)

Files changed (30)

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)
-	}
-//}
-
-

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)
-}

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;
-}

helpers/template.js

-// simple helper to reder template from ejs
-//
-
-function template(str, data) {
-    html = new EJS({text: str}).render(data);
-    return html;
-}
-
-
 function(head, req) {
   // !json templates.index
   // !json blog
-  // !code helpers/ejs/*.js
-  // !code helpers/template.js
-  // !code vendor/couchapp/date.js
-  // !code vendor/couchapp/path.js
+  // !code vendor/inditeweb/ejs/*.js
+  // !code vendor/inditeweb/template.js
+  // !code vendor/inditeweb/date.js
+  // !code vendor/inditeweb/path.js
     
   var indexPath = listPath('index','recent-posts',{descending:true, limit:8});
   var feedPath = listPath('index','recent-posts',{descending:true, limit:8, format:"atom"});
 function(head, req) {
   // !json templates.search
   // !json blog
-  // !code helpers/ejs/*
-  // !code helpers/template.js
-  // !code vendor/couchapp/date.js
-  // !code vendor/couchapp/path.js
-    
+  // !code vendor/inditeweb/ejs/*.js
+  // !code vendor/inditeweb/template.js
+  // !code vendor/inditeweb/date.js
+  // !code vendor/inditeweb/path.js
+
   var indexPath = listPath('index','recent-posts',{descending:true, limit:8});
   var feedPath = listPath('search','topics',{descending:true, limit:8, format:"atom"});
   var archivesPath = listPath('index','recent-posts',{descending:true, limit:25});
 function(doc, req) {  
   // !json templates.edit
   // !json blog
-  // !code helpers/ejs/*
-  // !code helpers/template.js
-  // !code vendor/couchapp/date.js
-  // !code vendor/couchapp/path.js
+  // !code vendor/inditeweb/ejs/*.js
+  // !code vendor/inditeweb/template.js
+  // !code vendor/inditeweb/date.js
+  // !code vendor/inditeweb/path.js
 
   // we only show html
   //
 function(doc, req) {  
   // !json templates.post
   // !json blog
-  // !code helpers/ejs/*
-  // !code helpers/template.js
-  // !code vendor/couchapp/date.js
-  // !code vendor/couchapp/path.js
+  // !code vendor/inditeweb/ejs/*.js
+  // !code vendor/inditeweb/template.js
+  // !code vendor/inditeweb/date.js
+  // !code vendor/inditeweb/path.js
+
 
   var fcreated_at = new Date().setRFC3339(doc.created_at).toLocaleString();
 

vendor/couchapp/README.md

+## CouchApp - more than just a filesystem mapper
+
+This is where documentation will go for the client and server JavaScript parts of CouchApp.

vendor/couchapp/_attachments/jquery.couchapp.js

+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License.  You may obtain a copy
+// of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+// Usage: The passed in function is called when the page is ready.
+// CouchApp passes in the app object, which takes care of linking to 
+// the proper database, and provides access to the CouchApp helpers.
+// $.CouchApp(function(app) {
+//    app.db.view(...)
+//    ...
+// });
+
+function escapeHTML(st) {                                       
+  return(                                                                 
+    st && st.replace(/&/g,'&amp;').                                         
+      replace(/>/g,'&gt;').                                           
+      replace(/</g,'&lt;').                                           
+      replace(/"/g,'&quot;')                                         
+  );                                                                     
+};
+
+
+function f(n) {    // Format integers to have at least two digits.
+    return n < 10 ? '0' + n : n;
+}
+
+Date.parseRFC3339 = function (string) {
+    var date=new Date(0);
+    var match = string.match(/(\d{4})-(\d\d)-(\d\d)\s*(?:[\sT]\s*(\d\d):(\d\d)(?::(\d\d))?(\.\d*)?\s*(Z|([-+])(\d\d):(\d\d))?)?/);
+    if (!match) return;
+    if (match[2]) match[2]--;
+    if (match[7]) match[7] = (match[7]+'000').substring(1,4);
+    var field = [null,'FullYear','Month','Date','Hours','Minutes','Seconds','Milliseconds'];
+    for (var i=1; i<=7; i++) if (match[i]) date['setUTC'+field[i]](match[i]);
+    if (match[9]) date.setTime(date.getTime()+(match[9]=='-'?1:-1)*(match[10]*3600000+match[11]*60000) );
+    return date.getTime();
+}
+
+Date.prototype.rfc3339 = function() {
+    return this.getUTCFullYear()   + '-' +
+         f(this.getUTCMonth() + 1) + '-' +
+         f(this.getUTCDate())      + 'T' +
+         f(this.getUTCHours())     + ':' +
+         f(this.getUTCMinutes())   + ':' +
+         f(this.getUTCSeconds())   + 'Z';
+};
+
+Date.prototype.setRFC3339 = function(dString){
+    var regexp = /(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)(T)?(\d\d)(:)?(\d\d)(:)?(\d\d)(\.\d+)?(Z|([+-])(\d\d)(:)?(\d\d))/;
+
+    if (dString.toString().match(new RegExp(regexp))) {
+        var d = dString.match(new RegExp(regexp));
+        var offset = 0;
+
+        this.setUTCDate(1);
+        this.setUTCFullYear(parseInt(d[1],10));
+        this.setUTCMonth(parseInt(d[3],10) - 1);
+        this.setUTCDate(parseInt(d[5],10));
+        this.setUTCHours(parseInt(d[7],10));
+        this.setUTCMinutes(parseInt(d[9],10));
+        this.setUTCSeconds(parseInt(d[11],10));
+        if (d[12])
+            this.setUTCMilliseconds(parseFloat(d[12]) * 1000);
+        else
+            this.setUTCMilliseconds(0);
+        if (d[13] != 'Z') {
+            offset = (d[15] * 60) + parseInt(d[17],10);
+            offset *= ((d[14] == '-') ? -1 : 1);
+            this.setTime(this.getTime() - offset * 60 * 1000);
+        }
+    } else {
+        this.setTime(Date.parse(dString));
+    }
+    return this;
+};
+
+/*
+File: Math.uuid.js
+Version: 1.3
+Copyright (c) 2008, Robert Kieffer
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+    * Neither the name of Robert Kieffer nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+Math.uuid =  function (len, radix) {
+  // Private array of chars to use
+  var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); 
+
+  
+    var chars = CHARS, uuid = [], rnd = Math.random;
+    radix = radix || chars.length;
+
+    if (len) {
+      // Compact form
+      for (var i = 0; i < len; i++) uuid[i] = chars[0 | rnd()*radix];
+    } else {
+      // rfc4122, version 4 form
+      var r;
+
+      // rfc4122 requires these characters
+      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
+      uuid[14] = '4';
+
+      // Fill in random data.  At i==19 set the high bits of clock sequence as
+      // per rfc4122, sec. 4.1.5
+      for (var i = 0; i < 36; i++) {
+        if (!uuid[i]) {
+          r = 0 | rnd()*16;
+          uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
+        }
+      }
+    }
+
+    return uuid.join('');
+  };
+  
+Math.uuidHex = function() {
+  return Math.uuid().replace(/-/g, '');
+};
+
+
+Math.uuidInt = function() {
+  return parseInt(Math.uuidHex(), 16);
+};
+
+
+// Convert a options object to an url query string.
+// ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"'
+function encodeOptions(options) {
+  var buf = []
+  if (typeof(options) == "object" && options !== null) {
+    for (var name in options) {
+      if (name == "error" || name == "success") continue;
+      var value = options[name];
+      if (name == "key" || name == "startkey" || name == "endkey" || name == "keys") {
+        value = toJSON(value);
+      }
+      buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value));
+    }
+  }
+  return buf.length ? "?" + buf.join("&") : "";
+}
+
+function toJSON(obj) {
+  return obj !== null ? JSON.stringify(obj) : null;
+}
+
+(function($) {
+
+  function Design(db, name) {
+    this.view = function(view, opts) {
+      db.view(name+'/'+view, opts);
+    };
+  };
+
+  
+  function init(app) {
+    $(function() {
+      var dbname = document.location.href.split('/')[3];
+      var dname = unescape(document.location.href).split('/')[5];
+      var db = $.couch.db(dbname);
+      var design = new Design(db, dname);
+      
+      // docForm applies CouchDB behavior to HTML forms.
+      function docForm(formSelector, opts) {
+        var localFormDoc = {};
+        var opts = opts || {};
+        opts.fields = opts.fields || [];
+        
+        // turn the form into deep json
+        // field names like 'author-email' get turned into json like
+        // {"author":{"email":"quentin@example.com"}}
+        function formToDeepJSON(form, fields, doc) {
+          var form = $(form);
+          opts.fields.forEach(function(field) {
+            var val = form.find("[name="+field+"]").val()
+            if (!val) return;
+            var parts = field.split('-');
+            var frontObj = doc, frontName = parts.shift();
+            while (parts.length > 0) {
+              frontObj[frontName] = frontObj[frontName] || {}
+              frontObj = frontObj[frontName];
+              frontName = parts.shift();
+            }
+            frontObj[frontName] = val;
+          });
+        };
+        
+        // Apply the behavior
+        $(formSelector).submit(function(e) {
+          e.preventDefault();
+          // formToDeepJSON acts on localFormDoc by reference
+          formToDeepJSON(this, opts.fields, localFormDoc);
+          if (opts.validForm && !opts.validForm(localFormDoc)) return false;
+          if (opts.beforeSave) opts.beforeSave(localFormDoc);
+          db.saveDoc(localFormDoc, {
+            success : function(resp) {
+              if (opts.success) opts.success(resp, localFormDoc);
+            }
+          })
+          
+          return false;
+        });
+
+        // populate form from an existing doc
+        function docToForm(doc) {
+          var form = $(formSelector);
+          // fills in forms
+          opts.fields.forEach(function(field) {
+            var parts = field.split('-');
+            var run = true, frontObj = doc, frontName = parts.shift();
+            while (frontObj && parts.length > 0) {                
+              frontObj = frontObj[frontName];
+              frontName = parts.shift();
+            }
+            if (frontObj && frontObj[frontName])
+              form.find("[name="+field+"]").val(frontObj[frontName]);
+          });            
+        };
+        
+        if (opts.id) {
+          db.openDoc(opts.id, {
+            success: function(doc) {
+              if (opts.onLoad) opts.onLoad(doc);
+              localFormDoc = doc;
+              docToForm(doc);
+          }});
+        } else if (opts.template) {
+          if (opts.onLoad) opts.onLoad(opts.template);
+          localFormDoc = opts.template;
+          docToForm(localFormDoc);
+        }
+        var instance = {
+          deleteDoc : function(opts) {
+            opts = opts || {};
+            if (confirm("Really delete this document?")) {                
+              db.removeDoc(localFormDoc, opts);
+            }
+          },
+          localDoc : function() {
+            formToDeepJSON(formSelector, opts.fields, localFormDoc);
+            return localFormDoc;
+          }
+        }
+        return instance;
+      }
+      
+      function prettyDate(time){
+      	var date = new Date(time),
+      		diff = (((new Date()).getTime() - date.getTime()) / 1000),
+      		day_diff = Math.floor(diff / 86400);
+
+        // if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ) return;
+
+      	return day_diff < 1 && (
+      			diff < 60 && "just now" ||
+      			diff < 120 && "1 minute ago" ||
+      			diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
+      			diff < 7200 && "1 hour ago" ||
+      			diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
+      		day_diff == 1 && "yesterday" ||
+      		day_diff < 21 && day_diff + " days ago" ||
+      		day_diff < 45 && Math.ceil( day_diff / 7 ) + " weeks ago" ||
+      		day_diff < 730 && Math.ceil( day_diff / 31 ) + " months ago" ||
+      		Math.ceil( day_diff / 365 ) + " years ago";
+      };
+      
+      function login(options) {
+        options = options || {};
+        var username = options.username, 
+        password = options.password;
+        
+        var userdb = options.userdb || dbname;
+        $.ajax({
+          type: "POST",
+          url: "/_session",
+          dataType: "json",
+          data: { username: username, password: password },
+          beforeSend: function(req) {
+            req.setRequestHeader('X-CouchDB-WWW-Authenticate', 'Cookie');
+          },
+          success: function(data) {
+            if (data.ok) {
+              if (options.success) options.success(data);
+            } else {
+              options.error(data);
+            } 
+          }
+        });
+      };
+      
+      function logout(options) {
+        options = options || {};
+        var userdb = options.userdb || dbname;
+        $.ajax({
+          type: "DELETE", url: "/_session", dataType: "json",
+          beforeSend: function(req) {
+            req.setRequestHeader('X-CouchDB-WWW-Authenticate', 'Cookie');
+          },
+          complete: function(req) {
+            var resp = $.httpData(req, "json");
+            if (req.status == 200) {
+              if (options.success) options.success(resp);
+            } else if (options.error) {
+              options.error(req.status, resp.error, resp.reason);
+            } else {
+              alert("An error occurred logging out: " + resp.reason);
+            }
+          }
+        });
+      };
+      
+      app({
+        showPath : function(funcname, docid) {
+          // I wish this was shared with path.js...
+          if (docid)
+            return '/'+[dbname, '_design', dname, '_show', funcname, docid].join('/')
+          else
+            return '/'+[dbname, '_design', dname, '_show', funcname].join('/')
+        },
+        listPath : function(funcname, viewname) {
+          return '/'+[dbname, '_design', dname, '_list', funcname, viewname].join('/')
+        },
+        slugifyString : function(string) {
+          return string.replace(/\W/g,'-').
+            replace(/\-*$/,'').replace(/^\-*/,'').
+            replace(/\-{2,}/,'-');
+        },
+        isLogged: function(loggedIn, loggedOut) {
+          $.getJSON("/_session", function(data) {
+            if (data.name) {
+              loggedIn && loggedIn(data);
+            } else {
+              loggedOut && loggedOut();
+            }
+          });
+          
+          
+        },
+        name: dname,
+        db : db,
+        design : design,
+        view : design.view,
+        docForm : docForm,
+        prettyDate : prettyDate,
+        login: login,
+        logout: logout
+      });
+    });
+  };
+
+  $.CouchApp = $.CouchApp || init;
+
+})(jQuery);

vendor/couchapp/_attachments/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
+ */
+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.
+ */
+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.
+ */
+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;
+}

vendor/couchapp/_attachments/sha1.js

+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS PUB 180-1
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+
+/*
+ * 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_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
+function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
+function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
+function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
+function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
+function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function sha1_vm_test()
+{
+  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
+}
+
+/*
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+function core_sha1(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << (24 - len % 32);
+  x[((len + 64 >> 9) << 4) + 15] = len;
+
+  var w = Array(80);
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+  var e = -1009589776;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+    var olde = e;
+
+    for(var j = 0; j < 80; j++)
+    {
+      if(j < 16) w[j] = x[i + j];
+      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
+                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
+      e = d;
+      d = c;
+      c = rol(b, 30);
+      b = a;
+      a = t;
+    }
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+    e = safe_add(e, olde);
+  }
+  return Array(a, b, c, d, e);
+
+}
+
+/*
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+function sha1_ft(t, b, c, d)
+{
+  if(t < 20) return (b & c) | ((~b) & d);
+  if(t < 40) return b ^ c ^ d;
+  if(t < 60) return (b & c) | (b & d) | (c & d);
+  return b ^ c ^ d;
+}
+
+/*
+ * Determine the appropriate additive constant for the current iteration
+ */
+function sha1_kt(t)
+{
+  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
+         (t < 60) ? -1894007588 : -899497514;
+}
+
+/*
+ * Calculate the HMAC-SHA1 of a key and some data
+ */
+function core_hmac_sha1(key, data)
+{
+  var bkey = str2binb(key);
+  if(bkey.length > 16) bkey = core_sha1(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_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
+  return core_sha1(opad.concat(hash), 512 + 160);
+}
+
+/*
+ * 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 rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert an 8-bit or 16-bit string to an array of big-endian words
+ * In 8-bit function, characters >255 have their hi-byte silently ignored.
+ */
+function str2binb(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) << (32 - chrsz - i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of big-endian words to a string
+ */
+function binb2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of big-endian words to a hex string.
+ */
+function binb2hex(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] >> ((3 - i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of big-endian words to a base-64 string
+ */
+function binb2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * (3 - (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;
+}

vendor/couchapp/_attachments/sha256.js

+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
+ * in FIPS 180-2
+ * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ * Also http://anmar.eu.org/projects/jssha2/
+ */
+
+/*
+ * 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   */
+
+/*
+ * 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_sha256(s)    { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); }
+function b64_sha256(s)    { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); }
+function any_sha256(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); }
+function hex_hmac_sha256(k, d)
+  { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function b64_hmac_sha256(k, d)
+  { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function any_hmac_sha256(k, d, e)
+  { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function sha256_vm_test()
+{
+  return hex_sha256("abc").toLowerCase() ==
+            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
+}
+
+/*
+ * Calculate the sha256 of a raw string
+ */
+function rstr_sha256(s)
+{
+  return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8));
+}
+
+/*
+ * Calculate the HMAC-sha256 of a key and some data (raw strings)
+ */
+function rstr_hmac_sha256(key, data)
+{
+  var bkey = rstr2binb(key);
+  if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8);
+
+  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 = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
+  return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256));
+}
+
+/*
+ * Convert a raw string to a hex string
+ */
+function rstr2hex(input)
+{
+  try { hexcase } catch(e) { hexcase=0; }
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var output = "";
+  var x;
+  for(var i = 0; i < input.length; i++)
+  {
+    x = input.charCodeAt(i);
+    output += hex_tab.charAt((x >>> 4) & 0x0F)
+           +  hex_tab.charAt( x        & 0x0F);
+  }
+  return output;
+}
+
+/*
+ * Convert a raw string to a base-64 string
+ */
+function rstr2b64(input)
+{
+  try { b64pad } catch(e) { b64pad=''; }
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var output = "";
+  var len = input.length;
+  for(var i = 0; i < len; i += 3)
+  {
+    var triplet = (input.charCodeAt(i) << 16)
+                | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
+                | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > input.length * 8) output += b64pad;
+      else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
+    }
+  }
+  return output;
+}
+
+/*
+ * Convert a raw string to an arbitrary string encoding
+ */
+function rstr2any(input, encoding)
+{
+  var divisor = encoding.length;
+  var remainders = Array();
+  var i, q, x, quotient;
+
+  /* Convert to an array of 16-bit big-endian values, forming the dividend */
+  var dividend = Array(Math.ceil(input.length / 2));
+  for(i = 0; i < dividend.length; i++)
+  {
+    dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
+  }
+
+  /*
+   * Repeatedly perform a long division. The binary array forms the dividend,
+   * the length of the encoding is the divisor. Once computed, the quotient
+   * forms the dividend for the next step. We stop when the dividend is zero.
+   * All remainders are stored for later use.
+   */
+  while(dividend.length > 0)
+  {
+    quotient = Array();
+    x = 0;
+    for(i = 0; i < dividend.length; i++)
+    {
+      x = (x << 16) + dividend[i];
+      q = Math.floor(x / divisor);
+      x -= q * divisor;
+      if(quotient.length > 0 || q > 0)
+        quotient[quotient.length] = q;
+    }
+    remainders[remainders.length] = x;
+    dividend = quotient;
+  }
+
+  /* Convert the remainders to the output string */
+  var output = "";
+  for(i = remainders.length - 1; i >= 0; i--)
+    output += encoding.charAt(remainders[i]);
+
+  /* Append leading zero equivalents */
+  var full_length = Math.ceil(input.length * 8 /
+                                    (Math.log(encoding.length) / Math.log(2)))
+  for(i = output.length; i < full_length; i++)
+    output = encoding[0] + output;
+
+  return output;
+}
+
+/*
+ * Encode a string as utf-8.
+ * For efficiency, this assumes the input is valid utf-16.
+ */
+function str2rstr_utf8(input)
+{
+  var output = "";
+  var i = -1;
+  var x, y;
+
+  while(++i < input.length)
+  {
+    /* Decode utf-16 surrogate pairs */
+    x = input.charCodeAt(i);
+    y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
+    if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
+    {
+      x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
+      i++;
+    }
+
+    /* Encode output as utf-8 */
+    if(x <= 0x7F)
+      output += String.fromCharCode(x);
+    else if(x <= 0x7FF)
+      output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
+                                    0x80 | ( x         & 0x3F));
+    else if(x <= 0xFFFF)
+      output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
+                                    0x80 | ((x >>> 6 ) & 0x3F),
+                                    0x80 | ( x         & 0x3F));
+    else if(x <= 0x1FFFFF)
+      output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
+                                    0x80 | ((x >>> 12) & 0x3F),
+                                    0x80 | ((x >>> 6 ) & 0x3F),
+                                    0x80 | ( x         & 0x3F));
+  }
+  return output;
+}
+
+/*
+ * Encode a string as utf-16
+ */
+function str2rstr_utf16le(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length; i++)
+    output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
+                                  (input.charCodeAt(i) >>> 8) & 0xFF);
+  return output;
+}
+
+function str2rstr_utf16be(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length; i++)
+    output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
+                                   input.charCodeAt(i)        & 0xFF);
+  return output;
+}
+
+/*
+ * Convert a raw string to an array of big-endian words
+ * Characters >255 have their high-byte silently ignored.
+ */
+function rstr2binb(input)
+{
+  var output = Array(input.length >> 2);
+  for(var i = 0; i < output.length; i++)
+    output[i] = 0;
+  for(var i = 0; i < input.length * 8; i += 8)
+    output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
+  return output;
+}
+
+/*
+ * Convert an array of big-endian words to a string
+ */
+function binb2rstr(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length * 32; i += 8)
+    output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
+  return output;
+}
+
+/*
+ * Main sha256 function, with its support functions
+ */
+function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
+function sha256_R (X, n) {return ( X >>> n );}
+function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
+function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
+function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
+function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
+function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
+function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
+function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
+function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
+function sha256_Gamma0512(x) {return (sha256_S(x, 1)  ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
+function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
+
+var sha256_K = new Array