$(document).ready(function () {
	//AuthBlock.init();
	Global.init();
	PlaceHolder.init();
	//SlideNavigation.init();
	Auth.init();
});

$.postJSON = function(url, data, callback) {
	$.post(url, data, callback, "json");
};
$.formPOST = function(oForm, callback){
	$.postJSON($(oForm).attr('action'), $(oForm).serialize(), callback);
};


var Global = {
	
	init: function(){
		this.Pseudo.init();
	}
	, Pseudo: {
		init: function(oElement){
			var pseudo = !oElement ? $('.pseudo') : $('.pseudo', oElement);
			$(pseudo).mouseover(function(){
				$(this).addClass('pseudo_hover');
			});
			$(pseudo).mouseout(function(){
				$(this).removeClass('pseudo_hover');
			});
		}
	}
	/* events */
	, E: {
		change: function(o,e){
			$(o).keyup(e).mouseup(e).blur(e).change(e);
		}
	}
	/* sets */
	, S: {
		url: function(s){
			return encodeURIComponent(s);
		}
	}
	, Check: {
		email: function(email){
			var regexp = /^[\w-](\.?[\w-])*(\+?\w*)?@[\w-](\.?[\w-])*\.[a-z]{2,}$/i;
			if(!$.trim(email).length)
				return false;
			
			if(!regexp.test(email))
				return false;
			
			return true;
		}
		, password: function(pass1){
			if(!pass1.length || pass1.length < 3)
				return false;
			
			return true;
		}
		, password_confirm: function(pass1, pass2){
			if(!this.password(pass1))
				return false;
			
			if(pass1 != pass2)
				return false;
			
			return true;
		}
	}
	, URL: {
		removeHASH: function(){
			window.location = window.location.href.replace( /#.*/, "");
		}
	}
};


var PlaceHolder = {
	init: function(){
		this.ClassEmpty = 'empty';
		this.setParams($('input[title]'));
		this.setParams($('textarea[title]'));
		this.isInit = true;
	}
	, setParams: function(aEl){
		var me = this;
		if(!aEl || !aEl.length)
			return;
		for(var i = 0, l = aEl.length; i < l; i++){
			aEl[i].d_value = aEl[i].title;
			aEl[i].d_type = aEl[i].type;
			aEl[i].d_name = aEl[i].name;
			aEl[i].d_class = aEl[i].className;
			aEl[i].e_class = this.ClassEmpty;
			aEl[i].SaveOriginal = (aEl[i].value == aEl[i].title);
			
			$(aEl[i]).focus(function(){ return me.focus(this) });
			$(aEl[i]).blur(function(){ return me.blur(this) });
			$(aEl[i]).keydown(function(){ return me.keydown(this) });
			if(!aEl[i].value)
				this.blur(aEl[i]);
		}
	}
	, focus: function(oEl){
		if (!oEl.SaveOriginal && oEl.d_value == oEl.value){
			oEl.value = '';
			oEl.name = oEl.d_name;
			if(oEl.type != 'textarea' && !$.browser.msie){
				oEl.focus();
			}
		} else {
			this.keydown(oEl);
		}
	}
	, keydown: function(oEl){
		$(oEl).removeClass(this.ClassEmpty);
	}
	, blur: function(oEl){
		var me = this;
		if (oEl.value == '' || oEl.d_value == oEl.value){
			if(oEl.type == 'password' && !oEl.value){
				if($.browser.msie){
					var el = document.createElement('<input type="text" name="name">');
				} else {
					var el = document.createElement('input');
					el.type = 'text';
					el.name = 'name';
				}
				var parent = oEl;
				parent.name = '';
				el.value = parent.d_value;
				el.d_value = parent.d_value;
				el.d_name = parent.d_name;
				el.d_class = parent.d_class;
				el.className = parent.d_class;
				el.parent = parent;
				var evtFocus = function(){
					parent.style.display = '';
					parent.name = this.d_name;
					this.style.display = 'none';
					parent.parentNode.removeChild(this);
					parent.focus();
				};
				$(el).focus(evtFocus).addClass(this.ClassEmpty);
				oEl.parentNode.insertBefore(el, parent);
				parent.style.display = 'none';
			} else {
				if(oEl.type != 'textarea' && oEl.type == 'password')
					oEl.type = 'text';
				oEl.value = oEl.d_value;
				oEl.name = '';
				$(oEl).addClass(this.ClassEmpty);
			}
		} else {
			this.keydown(oEl);
		}
	}
};

var Auth = {
	init: function(){
		this.$Content = $('#auth');
		if(!this.$Content.length)
			return false;
		
		var me = this;
		this.$Switch = $('.switch i.pseudo', this.$Content);
		this.$Switch.click(function(){
			var type = $(this).attr('type');
			if(!type)
				return false;
			type = $(this).attr('type') == 'login' ? 'registration' : 'login';
			me.$Content.removeAttr('class').addClass('block-auth block-auth-'+type);
		});
		this.Login.init();
		this.Registration.init();
		this.Logout.init();
		this.Remember.init();
		this.ChangePass.init();
		
	}
	, Registration: {
		init: function(){
			this.parent = Auth;
			this.$Form = $('form.f-registration', this.parent.$Content);
			if(!this.$Form.length)
				return;
			
			var me = this;
			
			this.$Email = $('input.email', this.$Form);
			this.$Pass = $('input.password', this.$Form);
			this.$Submit = $('.submit .pseudo', this.$Form);
			
			this.$error_main = $('.error-main', this.$Form);
			
			this.bSubmit = this.bError = false;
			
			this.$Submit.click(function(){
				me.submit();
				return false;
			});
			
			this.$Form.submit(function(){
				me.submit();
				return false;
			});
		}
		, submit: function(){
			if(this.bSubmit || this.bError)
				return false;
			
			this.error_hide(this.$error_main);
			this.bSubmit = true;
			
			var e =  '';
			var me = this;
			var ae = $(this.$Form).serializeArray();
			$.each(ae, function(i, field){
				if(field.name == 'password'){
					field.value = $.trim(field.value);
				}
				e += (i ? '&' : '') + (Global.S.url(field.name) + '=' + Global.S.url(field.value));
			});
			var inputs = $(':input',this.$Form);
			$(inputs).attr('disabled', 'disabled');
				
			$.postJSON('/registration/', e, function(response){
				try {
					me.bSubmit = false;
					if(response.response.error){
						if(server_messages.text[response.response.error]){
							me.error_show(me.$error_main, server_messages.text[response.response.error]);
						} else {
							me.error_show(me.$error_main, server_messages.text.registration_error);
						}
					}
					if(response.response.result == 'true'){
						Global.URL.removeHASH();
						//document.location = 'http://'+global.root_domain;
						document.location = document.location;
					} else {
						$(inputs).removeAttr('disabled');
					}
				} catch (e) {
					me.bSubmit = false;
					// catch
				}
			});
			return false;
		}
		, error_show: function(o, text){
			this.$error_main.css('display','block').text(text);
		}
		, error_hide: function(o, text){
			this.$error_main.css('display','none').text('');
		}
	}
	, Login: {
		init: function(){
			this.parent = Auth;
			this.$Form = $('form.f-login', this.parent.$Content);
			if(!this.$Form.length)
				return;
			
			var me = this;
			
			this.$Email = $('input.email', this.$Form);
			this.$Pass = $('input.password', this.$Form);
			this.$Submit = $('.submit .pseudo', this.$Form);
			
			this.$error_main = $('.error-main', this.$Form);
			
			this.bSubmit = this.bError = false;
			
			this.$Submit.click(function(){
				me.submit();
				return false;
			});
			
			this.$Form.submit(function(){
				me.submit();
				return false;
			});
		}
		, submit: function(){
			if(this.bSubmit || this.bError)
				return false;
			
			this.error_hide(this.$error_main);
			this.bSubmit = true;
			
			var me = this;
			var ae = $(this.$Form).serializeArray();
			var e =  '';
			var salt = '';
			var challenge = '';
			$.each(ae, function(i, field){
				if(field.name == 'salt'){
					salt = field.value;
					return;
				}
				if(field.name == 'challenge'){
					challenge = field.value;
					return;
				}
			});
			e = '';
			$.each(ae, function(i, field){
				if(field.name == 'salt'){
					return;
				}
				if(field.name == 'password'){
					e += '&' + (Global.S.url(field.name) + '=' + md5(salt + $.trim(field.value)));
					e += '&challengep=' + md5(challenge + md5($.trim(field.value)));
				} else {
					e += '&' + (Global.S.url(field.name) + '=' + Global.S.url(field.value));
				}
			});
			
			
			var inputs = $(':input',this.$Form);
			$(inputs).attr('disabled', 'disabled');
			$.postJSON('/login/', e, function(response){
				try {
					me.bSubmit = false;
					if(response.response.error){
						if(server_messages.text[response.response.error]){
							me.error_show(me.$error_main, server_messages.text[response.response.error]);
						} else {
							me.error_show(me.$error_main, server_messages.text.login_error);
						}
					}
					if(response.response.result == 'true'){
						Global.URL.removeHASH();
						//document.location = 'http://'+global.root_domain;
						document.location = document.location;
					}
					
					$(inputs).removeAttr('disabled');
				} catch (e) {
					me.bSubmit = false;
					// catch
				}
			});
			return false;
		}
		, error_show: function(o, text){
			this.$error_main.css('display','block').text(text);
		}
		, error_hide: function(o, text){
			this.$error_main.css('display','none').text('');
		}
	}
	, Logout: {
		init: function(){
			this.parent = Auth;
			this.$Form = $('.c-user', this.parent.$Content);
			if(!this.$Form.length)
				return;
			
			this.$Submit = $('.submit .pseudo', this.$Form);
			this.$Submit.click(function(){
				$.postJSON('/login/', 'faction=logout', function(response){
					try {
						Global.URL.removeHASH();
						document.location = '/';
					} catch (e) {
						// catch
					}
				});
				return false;
			});
		}
	}
	, Remember: {
		init: function(){
			this.$Content = $('.e-remember .form');
			if(!this.$Content.length)
				return;
			
			var me = this;
			this.bSubmit = false;
			var submit = function(){
				me.submit();
				return false;
			};
			this.$Form = $('form',this.$Content);
			this.$Submit = $('input[type=submit]', this.$Form);
			this.$error_main = $('.error', this.$Form);
			$(this.$Submit).submit(submit).click(submit);
			$(this.$Form).submit(submit);
		}
		, submit: function(){
			if(this.bSubmit)
				return false;
			this.bSubmit = true;
			
			var me = this;
			$.formPOST(this.$Form,function(response){
				try {
					me.bSubmit = false;
					if(response.response.error){
						me.error_show(me.oRemember, server_messages.text[response.response.error]);
						return false;
					}
					if(response.response.result == 'true'){
						$(me.$Form).css('display','none');
						$('.send', me.$Content).fadeIn(250);
					}
				} catch (e) {
					me.bSubmit = false;
					// catch
				}
			});
			return false;
		}
		, error_show: function(o, text){
			this.$error_main.css('display','block').text(text);
		}
		, error_hide: function(o, text){
			this.$error_main.css('display','none').text('');
		}
	}
	, ChangePass: {
		init: function(){
			this.$Content = $('.e-changepassword .form');
			if(!this.$Content.length)
				return;
			
			var me = this;
			this.bSubmit = false;
			var submit = function(){
				me.submit();
				return false;
			};
			this.$Form = $('form',this.$Content);
			this.$Submit = $('input[type=submit]', this.$Form);
			this.$error_main = $('.error', this.$Form);
			$(this.$Submit).submit(submit).click(submit);
			$(this.$Form).submit(submit);
		}
		, submit: function(){
			if(this.bSubmit)
				return false;
			this.bSubmit = true;
			
			var me = this;
			$.formPOST(this.$Form,function(response){
				try {
					me.bSubmit = false;
					if(response.response.error){
						me.error_show(me.oRemember, server_messages.text[response.response.error]);
						return false;
					}
					if(response.response.result == 'true'){
						$(me.$Form).css('display','none');
						$('.send', me.$Content).fadeIn(250);
					}
				} catch (e) {
					me.bSubmit = false;
					// catch
				}
			});
			return false;
		}
		, error_show: function(o, text){
			this.$error_main.css('display','block').text(text);
		}
		, error_hide: function(o, text){
			this.$error_main.css('display','none').text('');
		}
	}
};

var AuthBlock = {
	
	init: function(){
		this.oContent = $('#block-auth');
		if(!this.oContent.length)
			return false;
		
		var me = this;
		this.oMenu = $('.emenu .pseudo', this.oContent);
		
		
		var lastSelect = false;
		$(this.oMenu).click(function(){
			$(me.oContent).removeClass('block-login').removeClass('block-registration');
			
			var parentNode = this.parentNode;
			if($(parentNode).hasClass('emenu-login') || $(parentNode).hasClass('emenu-registration')){
				if($(parentNode).hasClass('emenu-login'))
					$(me.oContent).addClass('block-login');
				else
					$(me.oContent).addClass('block-registration');
				$(lastSelect).removeClass('pseudo_default');
				$(this).addClass('pseudo_default');
				lastSelect = this;
			}
		});
		$(me.oContent).removeClass('block-login').removeClass('block-registration');
		this.FormAuth.init();
	}
	
	, FormAuth: {
		init: function(){
			this.parent = AuthBlock;
			this.oContent = this.parent.oContent;
			if(!this.oContent.length)
				return false;
			
			var me = this;
			
			this.bSubmitLogin = false;
			this.bSubmitRegistration = false;
			this.bSubmitLogout = false;
			
			/*this.bSubmitRemember = false;
			this.bSubmitChangePass = false;
			*/
			
			this.oLogin = $('.form-login', this.parent.oContent);
			if(this.oLogin.length) {
				var submit = function(){
					me.login();
					return false;
				};
				var clickSubmit = function(){
					$(this.parentNode).css({'margin-top': '1px'});
				};
				var clickUpSubmit = function(){
					$(this.parentNode).css({'margin-top': '0px'});
				};
				this.oLoginForm = $('form',this.oLogin);
				this.oLoginSubmit = $('.mask-submit .pseudo', this.oLogin);
				$(this.oLoginSubmit).submit(submit).click(submit).mouseup(clickUpSubmit).mousedown(clickSubmit);
				$(this.oLoginForm).submit(submit);
			}
			
			this.oRegistration = $('.form-registration', this.parent.oContent);
			if(this.oRegistration.length) {
				var submit = function(){
					me.registration();
					return false;
				};
				var clickSubmit = function(){
					$(this.parentNode).css({'margin-top': '1px'});
				};
				var clickUpSubmit = function(){
					$(this.parentNode).css({'margin-top': '0px'});
				};
				this.oRegistrationForm = $('form',this.oRegistration);
				this.oRegistrationSubmit = $('.mask-submit .pseudo', this.oRegistration);
				$(this.oRegistrationSubmit).submit(submit).click(submit).mouseup(clickUpSubmit).mousedown(clickSubmit);
				$(this.oRegistrationForm).submit(submit);
			}
			
			this.oLogout = $('#auth-logout');
			if(this.oLogout.length) {
				var submit = function(){
					me.logout();
					return false;
				};
				var clickSubmit = function(){
					$(this.parentNode).css({'margin-top': '1px'});
				};
				var clickUpSubmit = function(){
					$(this.parentNode).css({'margin-top': '0px'});
				};
				$(this.oLogout).click(submit).mouseup(clickUpSubmit).mousedown(clickSubmit);
			}
			
			
			this.oRemember = $('.e-remember .form');
			if(this.oRemember.length) {
				var submit = function(){
					me.remember();
					return false;
				};
				this.oRememberForm = $('form',this.oRemember);
				this.oRememberSubmit = $('input[type=submit]', this.oRemember);
				$(this.oRememberSubmit).submit(submit).click(submit);
				$(this.oRememberForm).submit(submit);
			}
			this.oChangePass = $('.e-changepassword .form');
			if(this.oChangePass.length) {
				var submit = function(){
					me.changepass();
					return false;
				};
				this.oChangePassForm = $('form',this.oChangePass);
				this.oChangePassSubmit = $('input[type=submit]', this.oChangePass);
				$(this.oChangePassSubmit).submit(submit).click(submit);
				$(this.oChangePassForm).submit(submit);
			}
			var HideError = function(){
				me.error_hidden();
			};
			$(this.oContent).click(HideError);
		}
		, login: function(){
			if(this.bSubmitLogin)
				return false;
			this.bSubmitLogin = true;
			
			var me = this;
			var ae = $(this.oLoginForm).serializeArray();
			var e =  '';
			var salt = '';
			var challenge = '';
			$.each(ae, function(i, field){
				if(field.name == 'salt'){
					salt = field.value;
					return;
				}
				if(field.name == 'challenge'){
					challenge = field.value;
					return;
				}
			});
			e = '';
			$.each(ae, function(i, field){
				if(field.name == 'salt'){
					return;
				}
				if(field.name == 'password'){
					e += '&' + (Global.S.url(field.name) + '=' + md5(salt + $.trim(field.value)));
					e += '&challengep=' + md5(challenge + md5($.trim(field.value)));
				} else {
					e += '&' + (Global.S.url(field.name) + '=' + Global.S.url(field.value));
				}
			});
			$.postJSON($(this.oLoginForm).attr('action'), e, function(response){
				try {
					me.bSubmitLogin = false;
					if(response.response.error){
						me.error_show(server_messages.text.login_error);
						return false;
					}
					if(response.response.result == 'true'){
						//document.location = 'http://'+global.root_domain;
						document.location = document.location;
					}
				} catch (e) {
					me.bSubmitLogin = false;
					// catch
				}
			});
			return false;
		}
		, registration: function(){
			if(this.bSubmitRegistration)
				return false;
			this.bSubmitRegistration = true;
			
			var e =  '';
			var me = this;
			var ae = $(this.oRegistrationForm).serializeArray();
			$.each(ae, function(i, field){
				if(field.name == 'password'){
					field.value = $.trim(field.value);
				}
				e += (i ? '&' : '') + (Global.S.url(field.name) + '=' + Global.S.url(field.value));
			});
			$.postJSON($(this.oRegistrationForm).attr('action'), e, function(response){
				try {
					me.bSubmitRegistration = false;
					if(response.response.error){
						if(server_messages.text[response.response.error]){
							me.error_show(server_messages.text[response.response.error]);
						} else {
							me.error_show(server_messages.text.email_error);
						}
						return false;
					}
					if(response.response.result == 'true'){
						document.location = 'http://'+global.root_domain;
					}
				} catch (e) {
					me.bSubmitRegistration = false;
					// catch
				}
			});
			return false;
		}
		, logout: function(){
			if(this.bSubmitLogout)
				return false;
			var me = this; 
			this.bSubmitLogout = true;
			$.postJSON('/login/', 'faction=logout', function(response){
				try {
					me.bSubmitLogout = false;
					document.location = '/';
				} catch (e) {
					me.bSubmitLogout = false;
					// catch
				}
			});
			return false;
		}
		, remember: function(){
			if(this.bSubmitRemember)
				return false;
			this.bSubmitRemember = true;
			
			var me = this;
			$.formPOST(this.oRememberForm,function(response){
				try {
					me.bSubmitRemember = false;
					if(response.response.error){
						me.error_show2(me.oRemember, server_messages.text[response.response.error]);
						return false;
					}
					if(response.response.result == 'true'){
						$(me.oRememberForm).css('display','none');
						$('.send', me.oRemember).fadeIn(250);
					}
				} catch (e) {
					me.bSubmitRemember = false;
					// catch
				}
			});
			return false;
		}
		, changepass: function(){
			if(this.bSubmitChangePass)
				return false;
			this.bSubmitChangePass = true;
			
			var me = this;
			$.formPOST(this.oChangePassForm,function(response){
				try {
					me.bSubmitChangePass = false;
					if(response.response.error){
						me.error_show2(me.oChangePass, server_messages.text[response.response.error]);
						return false;
					}
					if(response.response.result == 'true'){
						$(me.oChangePassForm).css('display','none');
						$('.send', me.oChangePass).fadeIn(250);
					}
				} catch (e) {
					me.bSubmitChangePass = false;
					// catch
				}
			});
			return false;
		}
		, error_show: function(message){
			if(!message.length)
				return false;
			var oError = $('.mask-error', this.oContent);
			if(!oError.length)
				return;
			$(oError).css('display','block');
			$('b',oError).html(message);
			
		}
		, error_hidden: function(){
			$('.mask-error', this.oContent).css('display','none');
		}
		, error_show2: function(oContent, message){
			if(!message.length)
				return false;
			var oError = $('.error', oContent);
			if(!oError.length)
				return;
			$(oError).html(message).css('display','block');
			
		}
		, error_hidden2: function(oContent){
			$(oContent).css('display','none');
		}
	}
};

var SlideNavigation = {
	init: function(){
		this.$oSubject = $('.slide-navigation dl.navigation dt');
		var slide = function(){
			$(this.parentNode).toggleClass('visible');
			return false;
		};
		this.$oSubject.click(slide).mousedown(function(){ return false; });
		
		this.$oSubject = $('.slide-navigation dl.navigation dd.selected');
		$.each(this.$oSubject, slide);
	}
};


(function ($) {
	$.browserTest = function (a, z) {
		var u = 'unknown', x = 'X', m = function (r, h) {
			for (var i = 0; i < h.length; i = i + 1) {
				r = r.replace(h[i][0], h[i][1]);
			}

			return r;
		}, c = function (i, a, b, c) {
			var r = {
				name: m((a.exec(i) || [u, u])[1], b)
			};

			r[r.name] = true;

			r.version = (c.exec(i) || [x, x, x, x])[3];

			if (r.name.match(/safari/) && r.version > 400) {
				r.version = '2.0';
			}

			if (r.name === 'presto') {
				r.version = ($.browser.version > 9.27) ? 'futhark' : 'linear_b';
			}
			r.versionNumber = parseFloat(r.version, 10) || 0;
			r.versionX = (r.version !== x) ? (r.version + '').substr(0, 1) : x;
			r.className = r.name + r.versionX;

			return r;
		};

		a = (a.match(/Opera|Navigator|Minefield|KHTML|Chrome/) ? m(a, [
			[/(Firefox|MSIE|KHTML,\slike\sGecko|Konqueror)/, ''],
			['Chrome Safari', 'Chrome'],
			['KHTML', 'Konqueror'],
			['Minefield', 'Firefox'],
			['Navigator', 'Netscape']
		]) : a).toLowerCase();

		$.browser = $.extend((!z) ? $.browser : {}, c(a, /(camino|chrome|firefox|netscape|konqueror|lynx|msie|opera|safari)/, [], /(camino|chrome|firefox|netscape|netscape6|opera|version|konqueror|lynx|msie|safari)(\/|\s)([a-z0-9\.\+]*?)(\;|dev|rel|\s|$)/));

		$.layout = c(a, /(gecko|konqueror|msie|opera|webkit)/, [
			['konqueror', 'khtml'],
			['msie', 'trident'],
			['opera', 'presto']
		], /(applewebkit|rv|konqueror|msie)(\:|\/|\s)([a-z0-9\.]*?)(\;|\)|\s)/);

		$.os = {
			name: (/(win|mac|linux|sunos|solaris|iphone)/.exec(navigator.platform.toLowerCase()) || [u])[0].replace('sunos', 'solaris')
		};

		if (!z) {
			$('html').addClass([$.os.name, $.browser.name, $.browser.className, $.layout.name, $.layout.className].join(' '));
		}
	};

	$.browserTest(navigator.userAgent);
})(jQuery);



function md5(string){
	function RotateLeft(lValue, iShiftBits) { return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits)); }
	function AddUnsigned(lX,lY){
		var lX4,lY4,lX8,lY8,lResult;
		lX8 = (lX & 0x80000000);
		lY8 = (lY & 0x80000000);
		lX4 = (lX & 0x40000000);
		lY4 = (lY & 0x40000000);
		lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
		if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
		if (lX4 | lY4){
			if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
			else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
		}
		else return (lResult ^ lX8 ^ lY8);
	}
	function F(x,y,z) { return (x & y) | ((~x) & z); }
	function G(x,y,z) { return (x & z) | (y & (~z)); }
	function H(x,y,z) { return (x ^ y ^ z); }
	function I(x,y,z) { return (y ^ (x | (~z))); }
	function FF(a,b,c,d,x,s,ac){
		a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
		return AddUnsigned(RotateLeft(a, s), b);
	};
	function GG(a,b,c,d,x,s,ac)
	{
		a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
		return AddUnsigned(RotateLeft(a, s), b);
	};
	function HH(a,b,c,d,x,s,ac)
	{
		a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
		return AddUnsigned(RotateLeft(a, s), b);
	};
	function II(a,b,c,d,x,s,ac)
	{
		a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
		return AddUnsigned(RotateLeft(a, s), b);
	};
	function ConvertToWordArray(string)
	{
		var lWordCount;
		var lMessageLength = string.length;
		var lNumberOfWords_temp1=lMessageLength + 8;
		var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
		var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
		var lWordArray=Array(lNumberOfWords-1);
		var lBytePosition = 0;
		var lByteCount = 0;
		while ( lByteCount < lMessageLength )
		{
			lWordCount = (lByteCount-(lByteCount % 4))/4;
			lBytePosition = (lByteCount % 4)*8;
			lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
			lByteCount++;
		}
		lWordCount = (lByteCount-(lByteCount % 4))/4;
		lBytePosition = (lByteCount % 4)*8;
		lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
		lWordArray[lNumberOfWords-2] = lMessageLength<<3;
		lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
		return lWordArray;
	};
	function WordToHex(lValue)
	{
		var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
		for (lCount = 0;lCount<=3;lCount++)
		{
			lByte = (lValue>>>(lCount*8)) & 255;
			WordToHexValue_temp = "0" + lByte.toString(16);
			WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
		}
		return WordToHexValue;
	};
	function Utf8Encode(string)
	{
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";

		for (var n = 0; n < string.length; n++)
		{
			var c = string.charCodeAt(n);
			if (c < 128) utftext += String.fromCharCode(c);
			else if((c > 127) && (c < 2048))
			{
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else
			{
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
		}
		return utftext;
	};
	var x=Array();
	var k,AA,BB,CC,DD,a,b,c,d;
	var S11=7, S12=12, S13=17, S14=22;
	var S21=5, S22=9 , S23=14, S24=20;
	var S31=4, S32=11, S33=16, S34=23;
	var S41=6, S42=10, S43=15, S44=21;
	string = Utf8Encode(string);
	x = ConvertToWordArray(string);
	a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
	for (k=0;k<x.length;k+=16){
		AA=a; BB=b; CC=c; DD=d;
		a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
		d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
		c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
		b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
		a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
		d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
		c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
		b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
		a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
		d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
		c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
		b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
		a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
		d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
		c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
		b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
		a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
		d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
		c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
		b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
		a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
		d=GG(d,a,b,c,x[k+10],S22,0x2441453);
		c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
		b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
		a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
		d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
		c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
		b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
		a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
		d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
		c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
		b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
		a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
		d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
		c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
		b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
		a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
		d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
		c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
		b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
		a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
		d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
		c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
		b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
		a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
		d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
		c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
		b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
		a=II(a,b,c,d,x[k+0], S41,0xF4292244);
		d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
		c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
		b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
		a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
		d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
		c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
		b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
		a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
		d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
		c=II(c,d,a,b,x[k+6], S43,0xA3014314);
		b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
		a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
		d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
		c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
		b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
		a=AddUnsigned(a,AA);
		b=AddUnsigned(b,BB);
		c=AddUnsigned(c,CC);
		d=AddUnsigned(d,DD);
	}
	var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
	return temp.toLowerCase();
}
