diff --git a/README b/README
index ca9123bcbda591c4de4139c5ca8483a3aa2eca57..f78362f2e5b13437bac2b4adfc15b5f2565b9bab 100644
--- a/README
+++ b/README
@@ -1,3 +1,28 @@
+Install
+=======
+1- copy paste the javascript code found in log.htm into your website
+2- launch index.php
 
-Listing all the plugins API 
+Some modules
+============
+Login
+?module=Login
+
+Logout
+?module=Login
+
+User manager admin UI 
+?module=UsersManager
+
+Sites manager admin UI 
+?module=SitesManager
+
+All the data is available via APIs for example to get todays keywords in XML
+?module=API&method=Referers.getKeywords&idSite=1&period=month&date=today&format=xml
+
+or yesterday visits information in JSON
+?module=API&method=VisitsSummary.get&idSite=1&period=month&date=yesterday&format=json
+
+You can find the full listing of the APIs provided by the plugins on
 ?module=API&action=listAllAPI
+
diff --git a/config/config.ini.php b/config/config.ini.php
index 2b9fe1f5d394b4b7c71746ae120e07fea8d2c082..b9cb7b505087ab6a9308cb05fcad902751e91e4a 100755
--- a/config/config.ini.php
+++ b/config/config.ini.php
@@ -95,7 +95,7 @@ cookie_name	= piwik_visitor
 [log]
 
 ; normal messages
-;logger_message[]		= screen
+logger_message[]		= screen
 ;logger_message[]		= database
 ;logger_message[]		= file
 
diff --git a/libs/jquery/jquery-calendar.css b/libs/jquery/jquery-calendar.css
new file mode 100644
index 0000000000000000000000000000000000000000..2904cac01cca995214cfb8cffd6357bb2d64d839
--- /dev/null
+++ b/libs/jquery/jquery-calendar.css
@@ -0,0 +1,165 @@
+/* Main Style Sheet for jQuery Calendar */
+#calendar_div, .calendar_inline {
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 14px;
+	padding: 0;
+	margin: 0;
+}
+#calendar_div {
+	display: none;
+	border: 1px solid #777;
+	z-index: 10; /*must have*/ 
+}
+#calendar_div, .calendar_control, .calendar_links, .calendar_header, .calendar {
+	width: 185px;
+}
+.calendar_inline {
+	float: left;
+	display: block;
+	border: 0;
+}
+.calendar_dialog {
+	padding: 5px !important;
+	border: 4px ridge #ddd !important;
+}
+button.calendar_trigger {
+	width: 25px;
+}
+img.calendar_trigger {
+	margin: 2px;
+	vertical-align: middle;
+}
+.calendar_prompt {
+	float: left;
+	width: 181px;
+	padding: 2px;
+	background: #ddd;
+	color: #000;
+}
+* html .calendar_prompt {
+	width: 185px;
+}
+.calendar_control, .calendar_links, .calendar_header, .calendar {
+	clear: both;
+	float: left;
+	color: #fff;
+}
+.calendar_control {
+	background: #400;
+}
+.calendar_links {
+	background: #000;
+}
+.calendar_control, .calendar_links {
+	font-weight: bold;
+	font-size: 80%;
+	letter-spacing: 1px;
+}
+.calendar_links label { /* disabled links */
+	padding: 2px 5px;
+	color: #888;
+}
+.calendar_clear, .calendar_prev {
+	float: left;
+}
+.calendar_current {
+	float: left;
+	width: 35%;
+	text-align: center;
+}
+.calendar_close, .calendar_next {
+	float: right;
+}
+.calendar_header {
+	background: #333;
+	text-align: center;
+	font-weight: bold;
+}
+.calendar_header select {
+	background: #333;
+	color: #fff;
+	border: 0px;
+	font-weight: bold;
+}
+.calendar {
+	background: #ccc;
+	text-align: center;
+	font-size: 100%;
+}
+.calendar a {
+	display: block;
+	width: 100%;
+}
+.calendar .calendar_titleRow {
+	background: #777;
+}
+.calendar .calendar_daysRow {
+	background: #eee;
+	color: #666;
+}
+.calendar .calendar_daysCell {
+	color: #000;
+	border: 1px solid #ddd;
+}
+#calendar .calendar_daysCell a{
+	display: block;
+}
+.calendar .calendar_weekEndCell {
+	background: #ddd;
+}
+.calendar .calendar_daysCellOver {
+	background: #fff;
+	border: 1px solid #777;
+}
+.calendar .calendar_unselectable {
+	color: #888;
+}
+.calendar_today {
+	background: #fcc !important;
+}
+.calendar_currentDay {
+	background: #999 !important;
+}
+
+/* ________ CALENDAR LINKS _______
+
+** Reset link properties and then override them with !important */
+#calendar_div a, .calendar_inline a {
+	cursor: pointer;
+	margin: 0;
+	padding: 0;
+	background: none;
+	color: #000;
+}
+.calendar_inline .calendar_links a {
+	padding: 0 5px !important;
+}
+.calendar_control a, .calendar_links a {
+	padding: 2px 5px !important;
+	color: #eee !important;
+}
+.calendar_titleRow a {
+	color: #eee !important;
+}
+.calendar_control a:hover {
+	background: #fdd !important;
+	color: #333 !important;
+}
+.calendar_links a:hover, .calendar_titleRow a:hover {
+	background: #ddd !important;
+	color: #333 !important;
+}
+
+/* ___________ IE6 IFRAME FIX ________ */
+
+.calendar_cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 193px; /*must have to match width and borders*/
+    height: 200px; /*must have to match maximum height*/ 
+}
\ No newline at end of file
diff --git a/libs/jquery/jquery-calendar.js b/libs/jquery/jquery-calendar.js
new file mode 100644
index 0000000000000000000000000000000000000000..a0a624e091e49f16fa75a3fa67148e7e7fe91734
--- /dev/null
+++ b/libs/jquery/jquery-calendar.js
@@ -0,0 +1,813 @@
+/* jQuery Calendar v2.7
+   Written by Marc Grabanski (m@marcgrabanski.com) and enhanced by Keith Wood (kbwood@iprimus.com.au).
+
+   Copyright (c) 2007 Marc Grabanski (http://marcgrabanski.com/code/jquery-calendar)
+   Dual licensed under the GPL (http://www.gnu.org/licenses/gpl-3.0.txt) and 
+   CC (http://creativecommons.org/licenses/by/3.0/) licenses. "Share or Remix it but please Attribute the authors."
+   Date: 09-03-2007  */
+
+/* PopUp Calendar manager.
+   Use the singleton instance of this class, popUpCal, to interact with the calendar.
+   Settings for (groups of) calendars are maintained in an instance object
+   (PopUpCalInstance), allowing multiple different settings on the same page. */
+function PopUpCal() {
+	this._nextId = 0; // Next ID for a calendar instance
+	this._inst = []; // List of instances indexed by ID
+	this._curInst = null; // The current instance in use
+	this._disabledInputs = []; // List of calendar inputs that have been disabled
+	this._popUpShowing = false; // True if the popup calendar is showing , false if not
+	this._inDialog = false; // True if showing within a "dialog", false if not
+	this.regional = []; // Available regional settings, indexed by language code
+	this.regional[''] = { // Default regional settings
+		clearText: 'Clear', // Display text for clear link
+		closeText: 'Close', // Display text for close link
+		prevText: '<Prev', // Display text for previous month link
+		nextText: 'Next>', // Display text for next month link
+		currentText: 'Today', // Display text for current month link
+		dayNames: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Names of days starting at Sunday
+		monthNames: ['January','February','March','April','May','June',
+			'July','August','September','October','November','December'], // Names of months
+		dateFormat: 'DMY/' // First three are day, month, year in the required order,
+			// fourth (optional) is the separator, e.g. US would be 'MDY/', ISO would be 'YMD-'
+	};
+	this._defaults = { // Global defaults for all the calendar instances
+		autoPopUp: 'focus', // 'focus' for popup on focus,
+			// 'button' for trigger button, or 'both' for either
+		appendText: '', // Display text following the input box, e.g. showing the format
+		buttonText: '...', // Text for trigger button
+		buttonImage: '', // URL for trigger button image
+		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
+		closeAtTop: true, // True to have the clear/close at the top,
+			// false to have them at the bottom
+		hideIfNoPrevNext: false, // True to hide next/previous month links
+			// if not applicable, false to just disable them
+		changeMonth: true, // True if month can be selected directly, false if only prev/next
+		changeYear: true, // True if year can be selected directly, false if only prev/next
+		yearRange: '-10:+10', // Range of years to display in drop-down,
+			// either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
+		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
+		changeFirstDay: true, // True to click on day name to change, false to remain as set
+		showOtherMonths: false, // True to show dates in other months, false to leave blank
+		minDate: null, // The earliest selectable date, or null for no limit
+		maxDate: null, // The latest selectable date, or null for no limit
+		speed: 'medium', // Speed of display/closure
+		customDate: null, // Function that takes a date and returns an array with
+			// [0] = true if selectable, false if not,
+			// [1] = custom CSS class name(s) or '', e.g. popUpCal.noWeekends
+		fieldSettings: null, // Function that takes an input field and
+			// returns a set of custom settings for the calendar
+		onSelect: null // Define a callback function when a date is selected
+	};
+	$.extend(this._defaults, this.regional['']);
+	this._calendarDiv = $('<div id="calendar_div"></div>');
+	$(document.body).append(this._calendarDiv);
+	$(document.body).mousedown(this._checkExternalClick);
+}
+
+$.extend(PopUpCal.prototype, {
+	/* Register a new calendar instance - with custom settings. */
+	_register: function(inst) {
+		var id = this._nextId++;
+		this._inst[id] = inst;
+		return id;
+	},
+
+	/* Retrieve a particular calendar instance based on its ID. */
+	_getInst: function(id) {
+		return this._inst[id] || id;
+	},
+
+	/* Override the default settings for all instances of the calendar. 
+	   @param  settings  object - the new settings to use as defaults (anonymous object)
+	   @return void */
+	setDefaults: function(settings) {
+		$.extend(this._defaults, settings || {});
+	},
+
+	/* Handle keystrokes. */
+	_doKeyDown: function(e) {
+		var inst = popUpCal._getInst(this._calId);
+		if (popUpCal._popUpShowing) {
+			switch (e.keyCode) {
+				case 9:  popUpCal.hideCalendar(inst, '');
+						break; // hide on tab out
+				case 13: popUpCal._selectDate(inst);
+						break; // select the value on enter
+				case 27: popUpCal.hideCalendar(inst, inst._get('speed'));
+						break; // hide on escape
+				case 33: popUpCal._adjustDate(inst, -1, (e.ctrlKey ? 'Y' : 'M'));
+						break; // previous month/year on page up/+ ctrl
+				case 34: popUpCal._adjustDate(inst, +1, (e.ctrlKey ? 'Y' : 'M'));
+						break; // next month/year on page down/+ ctrl
+				case 35: if (e.ctrlKey) popUpCal._clearDate(inst);
+						break; // clear on ctrl+end
+				case 36: if (e.ctrlKey) popUpCal._gotoToday(inst);
+						break; // current on ctrl+home
+				case 37: if (e.ctrlKey) popUpCal._adjustDate(inst, -1, 'D');
+						break; // -1 day on ctrl+left
+				case 38: if (e.ctrlKey) popUpCal._adjustDate(inst, -7, 'D');
+						break; // -1 week on ctrl+up
+				case 39: if (e.ctrlKey) popUpCal._adjustDate(inst, +1, 'D');
+						break; // +1 day on ctrl+right
+				case 40: if (e.ctrlKey) popUpCal._adjustDate(inst, +7, 'D');
+						break; // +1 week on ctrl+down
+			}
+		}
+		else if (e.keyCode == 36 && e.ctrlKey) { // display the calendar on ctrl+home
+			popUpCal.showFor(this);
+		}
+	},
+
+	/* Filter entered characters. */
+	_doKeyPress: function(e) {
+		var inst = popUpCal._getInst(this._calId);
+		var chr = String.fromCharCode(e.charCode == undefined ? e.keyCode : e.charCode);
+		return (chr < ' ' || chr == inst._get('dateFormat').charAt(3) ||
+			(chr >= '0' && chr <= '9')); // only allow numbers and separator
+	},
+
+	/* Attach the calendar to an input field. */
+	_connectCalendar: function(target, inst) {
+		var $input = $(target);
+		var appendText = inst._get('appendText');
+		if (appendText) {
+			$input.after('<span class="calendar_append">' + appendText + '</span>');
+		}
+		var autoPopUp = inst._get('autoPopUp');
+		if (autoPopUp == 'focus' || autoPopUp == 'both') { // pop-up calendar when in the marked field
+			$input.focus(this.showFor);
+		}
+		if (autoPopUp == 'button' || autoPopUp == 'both') { // pop-up calendar when button clicked
+			var buttonText = inst._get('buttonText');
+			var buttonImage = inst._get('buttonImage');
+			var buttonImageOnly = inst._get('buttonImageOnly');
+			var trigger = $(buttonImageOnly ? '<img class="calendar_trigger" src="' +
+				buttonImage + '" alt="' + buttonText + '" title="' + buttonText + '"/>' :
+				'<button type="button" class="calendar_trigger">' + (buttonImage != '' ?
+				'<img src="' + buttonImage + '" alt="' + buttonText + '" title="' + buttonText + '"/>' :
+				buttonText) + '</button>');
+			$input.wrap('<span class="calendar_wrap"></span>').after(trigger);
+			trigger.click(this.showFor);
+		}
+		$input.keydown(this._doKeyDown).keypress(this._doKeyPress);
+		$input[0]._calId = inst._id;
+	},
+
+	/* Attach an inline calendar to a div. */
+	_inlineCalendar: function(target, inst) {
+		$(target).append(inst._calendarDiv);
+		target._calId = inst._id;
+		var date = new Date();
+		inst._selectedDay = date.getDate();
+		inst._selectedMonth = date.getMonth();
+		inst._selectedYear = date.getFullYear();
+		popUpCal._adjustDate(inst);
+	},
+
+	/* Pop-up the calendar in a "dialog" box.
+	   @param  dateText  string - the initial date to display (in the current format)
+	   @param  onSelect  function - the function(dateText) to call when a date is selected
+	   @param  settings  object - update the dialog calendar instance's settings (anonymous object)
+	   @param  pos       int[2] - coordinates for the dialog's position within the screen
+			leave empty for default (screen centre)
+	   @return void */
+	dialogCalendar: function(dateText, onSelect, settings, pos) {
+		var inst = this._dialogInst; // internal instance
+		if (!inst) {
+			inst = this._dialogInst = new PopUpCalInstance({}, false);
+			this._dialogInput = $('<input type="text" size="1" style="position: absolute; top: -100px;"/>');
+			this._dialogInput.keydown(this._doKeyDown);
+			$('body').append(this._dialogInput);
+			this._dialogInput[0]._calId = inst._id;
+		}
+		$.extend(inst._settings, settings || {});
+		this._dialogInput.val(dateText);
+		
+		/*	Cross Browser Positioning */
+		if (self.innerHeight) { // all except Explorer
+			windowWidth = self.innerWidth;
+			windowHeight = self.innerHeight;
+		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
+			windowWidth = document.documentElement.clientWidth;
+			windowHeight = document.documentElement.clientHeight;
+		} else if (document.body) { // other Explorers
+			windowWidth = document.body.clientWidth;
+			windowHeight = document.body.clientHeight;
+		} 
+		this._pos = pos || // should use actual width/height below
+			[(windowWidth / 2) - 100, (windowHeight / 2) - 100];
+
+		// move input on screen for focus, but hidden behind dialog
+		this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
+		inst._settings.onSelect = onSelect;
+		this._inDialog = true;
+		this._calendarDiv.addClass('calendar_dialog');
+		this.showFor(this._dialogInput[0]);
+		if ($.blockUI) {
+			$.blockUI(this._calendarDiv);
+		}
+	},
+
+	/* Enable the input field(s) for entry.
+	   @param  inputs  element/object - single input field or jQuery collection of input fields
+	   @return void */
+	enableFor: function(inputs) {
+		inputs = (inputs.jquery ? inputs : $(inputs));
+		inputs.each(function() {
+			this.disabled = false;
+			$('../button.calendar_trigger', this).each(function() { this.disabled = false; });
+			$('../img.calendar_trigger',
+this).css({opacity:'1.0',cursor:''});
+			var $this = this;
+			popUpCal._disabledInputs = $.map(popUpCal._disabledInputs,
+				function(value) { return (value == $this ? null : value); }); // delete entry
+		});
+	},
+
+	/* Disable the input field(s) from entry.
+	   @param  inputs  element/object - single input field or jQuery collection of input fields
+	   @return void */
+	disableFor: function(inputs) {
+		inputs = (inputs.jquery ? inputs : $(inputs));
+		inputs.each(function() {
+			this.disabled = true;
+			$('../button.calendar_trigger', this).each(function() { this.disabled = true; });
+			$('../img.calendar_trigger', this).css({opacity:'0.5',cursor:'default'});
+			var $this = this;
+			popUpCal._disabledInputs = $.map(popUpCal._disabledInputs,
+				function(value) { return (value == $this ? null : value); }); // delete entry
+			popUpCal._disabledInputs[popUpCal._disabledInputs.length] = this;
+		});
+	},
+
+	/* Update the settings for a calendar attached to an input field or division.
+	   @param  control   element - the input field or div/span attached to the calendar
+	   @param  settings  object - the new settings to update
+	   @return void */
+	reconfigureFor: function(control, settings) {
+		var inst = this._getInst(control._calId);
+		if (inst) {
+			$.extend(inst._settings, settings || {});
+			this._updateCalendar(inst);
+		}
+	},
+
+	/* Set the date for a calendar attached to an input field or division.
+	   @param  control  element - the input field or div/span attached to the calendar
+	   @param  date     Date - the new date
+	   @return void */
+	setDateFor: function(control, date) {
+		var inst = this._getInst(control._calId);
+		if (inst) {
+			inst._setDate(date);
+		}
+	},
+
+	/* Retrieve the date for a calendar attached to an input field or division.
+	   @param  control  element - the input field or div/span attached to the calendar
+	   @return Date - the current date */
+	getDateFor: function(control) {
+		var inst = this._getInst(control._calId);
+		return (inst ? inst._getDate() : null);
+	},
+
+	/* Pop-up the calendar for a given input field.
+	   @param  target  element - the input field attached to the calendar
+	   @return void */
+	showFor: function(target) {
+		var input = (target.nodeName && target.nodeName.toLowerCase() == 'input' ? target : this);
+		if (input.nodeName.toLowerCase() != 'input') { // find from button/image trigger
+			input = $('input', input.parentNode)[0];
+		}
+		if (popUpCal._lastInput == input) { // already here
+			return;
+		}
+		for (var i = 0; i < popUpCal._disabledInputs.length; i++) {  // check not disabled
+			if (popUpCal._disabledInputs[i] == input) {
+				return;
+			}
+		}
+		var inst = popUpCal._getInst(input._calId);
+		popUpCal.hideCalendar(inst, '');
+		popUpCal._lastInput = input;
+		inst._setDateFromField(input);
+		if (popUpCal._inDialog) { // hide cursor
+			input.value = '';
+		}
+		if (!popUpCal._pos) { // position below input
+			popUpCal._pos = popUpCal._findPos(input);
+			popUpCal._pos[1] += input.offsetHeight;
+		}
+		inst._calendarDiv.css('position', (popUpCal._inDialog && $.blockUI ? 'static' : 'absolute')).
+			css('left', popUpCal._pos[0] + 'px').css('top', popUpCal._pos[1] + 'px');
+		popUpCal._pos = null;
+		var fieldSettings = inst._get('fieldSettings');
+		$.extend(inst._settings, (fieldSettings ? fieldSettings(input) : {}));
+		popUpCal._showCalendar(inst);
+	},
+
+	/* Construct and display the calendar. */
+	_showCalendar: function(id) {
+		var inst = this._getInst(id);
+		popUpCal._updateCalendar(inst);
+		if (!inst._inline) {
+			var speed = inst._get('speed');
+			inst._calendarDiv.show(speed, function() {
+				popUpCal._popUpShowing = true;
+				popUpCal._afterShow(inst);
+			});
+			if (speed == '') {
+				popUpCal._popUpShowing = true;
+				popUpCal._afterShow(inst);
+			}
+			if (inst._input[0].type != 'hidden') {
+				inst._input[0].focus();
+			}
+			this._curInst = inst;
+		}
+	},
+
+	/* Generate the calendar content. */
+	_updateCalendar: function(inst) {
+		inst._calendarDiv.empty().append(inst._generateCalendar());
+		if (inst._input && inst._input != 'hidden') {
+			inst._input[0].focus();
+		}
+	},
+
+	/* Tidy up after displaying the calendar. */
+	_afterShow: function(inst) {
+		if ($.browser.msie) { // fix IE < 7 select problems
+			$('#calendar_cover').css({width: inst._calendarDiv[0].offsetWidth + 4,
+				height: inst._calendarDiv[0].offsetHeight + 4});
+		}
+		/*// re-position on screen if necessary
+		var calDiv = inst._calendarDiv[0];
+		var pos = popUpCal._findPos(inst._input[0]);
+		if ((calDiv.offsetLeft + calDiv.offsetWidth) >
+				(document.body.clientWidth + document.body.scrollLeft)) {
+			inst._calendarDiv.css('left', (pos[0] + inst._input[0].offsetWidth - calDiv.offsetWidth) + 'px');
+		}
+		if ((calDiv.offsetTop + calDiv.offsetHeight) >
+				(document.body.clientHeight + document.body.scrollTop)) {
+			inst._calendarDiv.css('top', (pos[1] - calDiv.offsetHeight) + 'px');
+		}*/
+	},
+
+	/* Hide the calendar from view.
+	   @param  id     string/object - the ID of the current calendar instance,
+			or the instance itself
+	   @param  speed  string - the speed at which to close the calendar
+	   @return void */
+	hideCalendar: function(id, speed) {
+		var inst = this._getInst(id);
+		if (popUpCal._popUpShowing) {
+			speed = (speed != null ? speed : inst._get('speed'));
+			inst._calendarDiv.hide(speed, function() {
+				popUpCal._tidyDialog(inst);
+			});
+			if (speed == '') {
+				popUpCal._tidyDialog(inst);
+			}
+			popUpCal._popUpShowing = false;
+			popUpCal._lastInput = null;
+			inst._settings.prompt = null;
+			if (popUpCal._inDialog) {
+				popUpCal._dialogInput.css('position', 'absolute').
+					css('left', '0px').css('top', '-100px');
+				if ($.blockUI) {
+					$.unblockUI();
+					$('body').append(this._calendarDiv);
+				}
+			}
+			popUpCal._inDialog = false;
+		}
+		popUpCal._curInst = null;
+	},
+
+	/* Tidy up after a dialog display. */
+	_tidyDialog: function(inst) {
+		inst._calendarDiv.removeClass('calendar_dialog');
+		$('.calendar_prompt', inst._calendarDiv).remove();
+	},
+
+	/* Close calendar if clicked elsewhere. */
+	_checkExternalClick: function(event) {
+		if (!popUpCal._curInst) {
+			return;
+		}
+		var target = $(event.target);
+		if( (target.parents("#calendar_div").length == 0)
+			&& (target.attr('class') != 'calendar_trigger')
+			&& popUpCal._popUpShowing 
+			&& !(popUpCal._inDialog && $.blockUI) )
+		{
+			popUpCal.hideCalendar(popUpCal._curInst, '');
+		}
+	},
+
+	/* Adjust one of the date sub-fields. */
+	_adjustDate: function(id, offset, period) {
+		var inst = this._getInst(id);
+		inst._adjustDate(offset, period);
+		this._updateCalendar(inst);
+	},
+
+	/* Action for current link. */
+	_gotoToday: function(id) {
+		var date = new Date();
+		var inst = this._getInst(id);
+		inst._selectedDay = date.getDate();
+		inst._selectedMonth = date.getMonth();
+		inst._selectedYear = date.getFullYear();
+		this._adjustDate(inst);
+	},
+
+	/* Action for selecting a new month/year. */
+	_selectMonthYear: function(id, select, period) {
+		var inst = this._getInst(id);
+		inst._selectingMonthYear = false;
+		inst[period == 'M' ? '_selectedMonth' : '_selectedYear'] =
+			select.options[select.selectedIndex].value - 0;
+		this._adjustDate(inst);
+	},
+
+	/* Restore input focus after not changing month/year. */
+	_clickMonthYear: function(id) {
+		var inst = this._getInst(id);
+		if (inst._input && inst._selectingMonthYear && !$.browser.msie) {
+			inst._input[0].focus();
+		}
+		inst._selectingMonthYear = !inst._selectingMonthYear;
+	},
+
+	/* Action for changing the first week day. */
+	_changeFirstDay: function(id, a) {
+		var inst = this._getInst(id);
+		var dayNames = inst._get('dayNames');
+		var value = a.firstChild.nodeValue;
+		for (var i = 0; i < 7; i++) {
+			if (dayNames[i] == value) {
+				inst._settings.firstDay = i;
+				break;
+			}
+		}
+		this._updateCalendar(inst);
+	},
+
+	/* Action for selecting a day. */
+	_selectDay: function(id, td) {
+		var inst = this._getInst(id);
+		inst._selectedDay = $("a", td).html();
+		this._selectDate(id);
+	},
+
+	/* Erase the input field and hide the calendar. */
+	_clearDate: function(id) {
+		this._selectDate(id, '');
+	},
+
+	/* Update the input field with the selected date. */
+	_selectDate: function(id, dateStr) {
+		var inst = this._getInst(id);
+		dateStr = (dateStr != null ? dateStr : inst._formatDate());
+		if (inst._input) {
+			inst._input.val(dateStr);
+		}
+		var onSelect = inst._get('onSelect');
+		if (onSelect) {
+			onSelect(dateStr);  // trigger custom callback
+		}
+		else {
+			inst._input.trigger('change'); // fire the change event
+		}
+		if (inst._inline) {
+			this._updateCalendar(inst);
+		}
+		else {
+			this.hideCalendar(inst, inst._get('speed'));
+		}
+	},
+
+	/* Set as customDate function to prevent selection of weekends.
+	   @param  date  Date - the date to customise
+	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
+	noWeekends: function(date) {
+		var day = date.getDay();
+		return [(day > 0 && day < 6), ''];
+	},
+
+	/* Find an object's position on the screen. */
+	_findPos: function(obj) {
+		if (obj.type == 'hidden') {
+			obj = obj.nextSibling;
+		}
+		var curleft = curtop = 0;
+		if (obj.offsetParent) {
+			curleft = obj.offsetLeft;
+			curtop = obj.offsetTop;
+			while (obj = obj.offsetParent) {
+				var origcurleft = curleft;
+				curleft += obj.offsetLeft;
+				if (curleft < 0) {
+					curleft = origcurleft;
+				}
+				curtop += obj.offsetTop;
+			}
+		}
+		return [curleft,curtop];
+	}
+});
+
+/* Individualised settings for calendars applied to one or more related inputs.
+   Instances are managed and manipulated through the PopUpCal manager. */
+function PopUpCalInstance(settings, inline) {
+	this._id = popUpCal._register(this);
+	this._selectedDay = 0;
+	this._selectedMonth = 0; // 0-11
+	this._selectedYear = 0; // 4-digit year
+	this._input = null; // The attached input field
+	this._inline = inline; // True if showing inline, false if used in a popup
+	this._calendarDiv = (!inline ? popUpCal._calendarDiv :
+		$('<div id="calendar_div_' + this._id + '" class="calendar_inline"></div>'));
+	if (inline) {
+		var date = new Date();
+		this._currentDay = date.getDate();
+		this._currentMonth = date.getMonth();
+		this._currentYear = date.getFullYear();
+	}
+	// customise the calendar object - uses manager defaults if not overridden
+	this._settings = $.extend({}, settings || {}); // clone
+}
+
+$.extend(PopUpCalInstance.prototype, {
+	/* Get a setting value, defaulting if necessary. */
+	_get: function(name) {
+		return (this._settings[name] != null ? this._settings[name] : popUpCal._defaults[name]);
+	},
+
+	/* Parse existing date and initialise calendar. */
+	_setDateFromField: function(input) {
+		this._input = $(input);
+		var dateFormat = this._get('dateFormat');
+		var currentDate = this._input.val().split(dateFormat.charAt(3));
+		if (currentDate.length == 3) {
+			this._currentDay = parseInt(currentDate[dateFormat.indexOf('D')], 10);
+			this._currentMonth = parseInt(currentDate[dateFormat.indexOf('M')], 10) - 1;
+			this._currentYear = parseInt(currentDate[dateFormat.indexOf('Y')], 10);
+		}
+		else {
+			var date = new Date();
+			this._currentDay = date.getDate();
+			this._currentMonth = date.getMonth();
+			this._currentYear = date.getFullYear();
+		}
+		this._selectedDay = this._currentDay;
+		this._selectedMonth = this._currentMonth;
+		this._selectedYear = this._currentYear;
+		this._adjustDate();
+	},
+
+	/* Set the date directly. */
+	_setDate: function(date) {
+		this._selectedDay = this._currentDay = date.getDate();
+		this._selectedMonth = this._currentMonth = date.getMonth();
+		this._selectedYear = this._currentYear = date.getFullYear();
+		this._adjustDate();
+	},
+
+	/* Retrieve the date directly. */
+	_getDate: function() {
+		return new Date(this._currentYear, this._currentMonth, this._currentDay);
+	},
+
+	/* Generate the HTML for the current state of the calendar. */
+	_generateCalendar: function() {
+		var today = new Date();
+		today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // clear time
+		// build the calendar HTML
+		var controls = '<div class="calendar_control">' +
+			'<a class="calendar_clear" onclick="popUpCal._clearDate(' + this._id + ');">' +
+			this._get('clearText') + '</a>' +
+			'<a class="calendar_close" onclick="popUpCal.hideCalendar(' + this._id + ');">' +
+			this._get('closeText') + '</a></div>';
+		var prompt = this._get('prompt');
+		var closeAtTop = this._get('closeAtTop');
+		var hideIfNoPrevNext = this._get('hideIfNoPrevNext');
+		// controls and links
+		var html = (prompt ? '<div class="calendar_prompt">' + prompt + '</div>' : '') +
+			(closeAtTop && !this._inline ? controls : '') + '<div class="calendar_links">' +
+			(this._canAdjustMonth(-1) ? '<a class="calendar_prev" ' +
+			'onclick="popUpCal._adjustDate(' + this._id + ', -1, \'M\');">' + this._get('prevText') + '</a>' :
+			(hideIfNoPrevNext ? '' : '<label class="calendar_prev">' + this._get('prevText') + '</label>')) +
+			(this._isInRange(today) ? '<a class="calendar_current" ' +
+			'onclick="popUpCal._gotoToday(' + this._id + ');">' + this._get('currentText') + '</a>' : '') +
+			(this._canAdjustMonth(+1) ? '<a class="calendar_next" ' +
+			'onclick="popUpCal._adjustDate(' + this._id + ', +1, \'M\');">' + this._get('nextText') + '</a>' :
+			(hideIfNoPrevNext ? '' : '<label class="calendar_next">' + this._get('nextText') + '</label>')) +
+			'</div><div class="calendar_header">';
+		var minDate = this._get('minDate');
+		var maxDate = this._get('maxDate');
+		// month selection
+		var monthNames = this._get('monthNames');
+		if (!this._get('changeMonth')) {
+			html += monthNames[this._selectedMonth] + '&nbsp;';
+		}
+		else {
+			var inMinYear = (minDate && minDate.getFullYear() == this._selectedYear);
+			var inMaxYear = (maxDate && maxDate.getFullYear() == this._selectedYear);
+			html += '<select class="calendar_newMonth" ' +
+				'onchange="popUpCal._selectMonthYear(' + this._id + ', this, \'M\');" ' +
+				'onclick="popUpCal._clickMonthYear(' + this._id + ');">';
+			for (var month = 0; month < 12; month++) {
+				if ((!inMinYear || month >= minDate.getMonth()) &&
+						(!inMaxYear || month <= maxDate.getMonth())) {
+					html += '<option value="' + month + '"' +
+						(month == this._selectedMonth ? ' selected="selected"' : '') +
+						'>' + monthNames[month] + '</option>';
+				}
+			}
+			html += '</select>';
+		}
+		// year selection
+		if (!this._get('changeYear')) {
+			html += this._selectedYear;
+		}
+		else {
+			// determine range of years to display
+			var years = this._get('yearRange').split(':');
+			var year = 0;
+			var endYear = 0;
+			if (years.length != 2) {
+				year = this._selectedYear - 10;
+				endYear = this._selectedYear + 10;
+			}
+			else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
+				year = this._selectedYear + parseInt(years[0], 10);
+				endYear = this._selectedYear + parseInt(years[1], 10);
+			}
+			else {
+				year = parseInt(years[0], 10);
+				endYear = parseInt(years[1], 10);
+			}
+			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+			html += '<select class="calendar_newYear" onchange="popUpCal._selectMonthYear(' +
+				this._id + ', this, \'Y\');" ' + 'onclick="popUpCal._clickMonthYear(' +
+				this._id + ');">';
+			for (; year <= endYear; year++) {
+				html += '<option value="' + year + '"' +
+					(year == this._selectedYear ? ' selected="selected"' : '') +
+					'>' + year + '</option>';
+			}
+			html += '</select>';
+		}
+		html += '</div><table class="calendar" cellpadding="0" cellspacing="0"><thead>' +
+			'<tr class="calendar_titleRow">';
+		var firstDay = this._get('firstDay');
+		var changeFirstDay = this._get('changeFirstDay');
+		var dayNames = this._get('dayNames');
+		for (var dow = 0; dow < 7; dow++) { // days of the week
+			html += '<td>' + (!changeFirstDay ? '' : '<a onclick="popUpCal._changeFirstDay(' +
+				this._id + ', this);">') + dayNames[(dow + firstDay) % 7] +
+				(changeFirstDay ? '</a>' : '') + '</td>';
+		}
+		html += '</tr></thead><tbody>';
+		var daysInMonth = this._getDaysInMonth(this._selectedYear, this._selectedMonth);
+		this._selectedDay = Math.min(this._selectedDay, daysInMonth);
+		var leadDays = (this._getFirstDayOfMonth(this._selectedYear, this._selectedMonth) - firstDay + 7) % 7;
+		var currentDate = new Date(this._currentYear, this._currentMonth, this._currentDay);
+		var selectedDate = new Date(this._selectedYear, this._selectedMonth, this._selectedDay);
+		var printDate = new Date(this._selectedYear, this._selectedMonth, 1 - leadDays);
+		var numRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
+		var customDate = this._get('customDate');
+		var showOtherMonths = this._get('showOtherMonths');
+		for (var row = 0; row < numRows; row++) { // create calendar rows
+			html += '<tr class="calendar_daysRow">';
+			for (var dow = 0; dow < 7; dow++) { // create calendar days
+				var customSettings = (customDate ? customDate(printDate) : [true, '']);
+				var otherMonth = (printDate.getMonth() != this._selectedMonth);
+				var unselectable = otherMonth || !customSettings[0] ||
+					(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
+				html += '<td class="calendar_daysCell' +
+					((dow + firstDay + 6) % 7 >= 5 ? ' calendar_weekEndCell' : '') + // highlight weekends
+					(otherMonth ? ' calendar_otherMonth' : '') + // highlight days from other months
+					(printDate.getTime() == selectedDate.getTime() ? ' calendar_daysCellOver' : '') + // highlight selected day
+					(unselectable ? ' calendar_unselectable' : '') +  // highlight unselectable days
+					(!otherMonth || showOtherMonths ? ' ' + customSettings[1] : '') + // highlight custom dates
+					(printDate.getTime() == currentDate.getTime() ? ' calendar_currentDay' : // highlight current day
+					(printDate.getTime() == today.getTime() ? ' calendar_today' : '')) + '"' + // highlight today (if different)
+					(unselectable ? '' : ' onmouseover="$(this).addClass(\'calendar_daysCellOver\');"' +
+					' onmouseout="$(this).removeClass(\'calendar_daysCellOver\');"' +
+					' onclick="popUpCal._selectDay(' + this._id + ', this);"') + '>' + // actions
+					(otherMonth ? (showOtherMonths ? printDate.getDate() : '&nbsp;') : // display for other months
+					(unselectable ? printDate.getDate() : '<a>' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
+				printDate.setDate(printDate.getDate() + 1);
+			}
+			html += '</tr>';
+		}
+		html += '</tbody></table>' + (!closeAtTop && !this._inline ? controls : '') +
+			'<div style="clear: both;"></div>' + (!$.browser.msie ? '' :
+			'<!--[if lte IE 6.5]><iframe src="javascript:false;" class="calendar_cover"></iframe><![endif]-->');
+		return html;
+	},
+
+	/* Adjust one of the date sub-fields. */
+	_adjustDate: function(offset, period) {
+		var date = new Date(this._selectedYear + (period == 'Y' ? offset : 0),
+			this._selectedMonth + (period == 'M' ? offset : 0),
+			this._selectedDay + (period == 'D' ? offset : 0));
+		// ensure it is within the bounds set
+		var minDate = this._get('minDate');
+		var maxDate = this._get('maxDate');
+		date = (minDate && date < minDate ? minDate : date);
+		date = (maxDate && date > maxDate ? maxDate : date);
+		this._selectedDay = date.getDate();
+		this._selectedMonth = date.getMonth();
+		this._selectedYear = date.getFullYear();
+	},
+
+	/* Find the number of days in a given month. */
+	_getDaysInMonth: function(year, month) {
+		return 32 - new Date(year, month, 32).getDate();
+	},
+
+	/* Find the day of the week of the first of a month. */
+	_getFirstDayOfMonth: function(year, month) {
+		return new Date(year, month, 1).getDay();
+	},
+
+	/* Determines if we should allow a "next/prev" month display change. */
+	_canAdjustMonth: function(offset) {
+		var date = new Date(this._selectedYear, this._selectedMonth + offset, 1);
+		if (offset < 0) {
+			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
+		}
+		return this._isInRange(date);
+	},
+
+	/* Is the given date in the accepted range? */
+	_isInRange: function(date) {
+		var minDate = this._get('minDate');
+		var maxDate = this._get('maxDate');
+		return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
+	},
+
+	/* Format the given date for display. */
+	_formatDate: function() {
+		var day = this._currentDay = this._selectedDay;
+		var month = this._currentMonth = this._selectedMonth;
+		var year = this._currentYear = this._selectedYear;
+		month++; // adjust javascript month
+		var dateFormat = this._get('dateFormat');
+		var dateString = '';
+		for (var i = 0; i < 3; i++) {
+			dateString += dateFormat.charAt(3) +
+				(dateFormat.charAt(i) == 'D' ? (day < 10 ? '0' : '') + day :
+				(dateFormat.charAt(i) == 'M' ? (month < 10 ? '0' : '') + month :
+				(dateFormat.charAt(i) == 'Y' ? year : '?')));
+		}
+		return dateString.substring(dateFormat.charAt(3) ? 1 : 0);
+	}
+});
+
+/* Attach the calendar to a jQuery selection.
+   @param  settings  object - the new settings to use for this calendar instance (anonymous)
+   @return jQuery object - for chaining further calls */
+$.fn.calendar = function(settings) {
+	return this.each(function() {
+		// check for settings on the control itself - in namespace 'cal:'
+		var inlineSettings = null;
+		for (attrName in popUpCal._defaults) {
+			var attrValue = this.getAttribute('cal:' + attrName);
+			if (attrValue) {
+				inlineSettings = inlineSettings || {};
+				try {
+					inlineSettings[attrName] = eval(attrValue);
+				}
+				catch (err) {
+					inlineSettings[attrName] = attrValue;
+				}
+			}
+		}
+		var nodeName = this.nodeName.toLowerCase();
+		if (nodeName == 'input') {
+			var instSettings = (inlineSettings ? $.extend($.extend({}, settings || {}),
+				inlineSettings || {}) : settings); // clone and customise
+			var inst = (inst && !inlineSettings ? inst :
+				new PopUpCalInstance(instSettings, false));
+			popUpCal._connectCalendar(this, inst);
+		} 
+		else if (nodeName == 'div' || nodeName == 'span') {
+			var instSettings = $.extend($.extend({}, settings || {}),
+				inlineSettings || {}); // clone and customise
+			var inst = new PopUpCalInstance(instSettings, true);
+			popUpCal._inlineCalendar(this, inst);
+		}
+	});
+};
+
+/* Initialise the calendar. */
+$(document).ready(function() {
+   popUpCal = new PopUpCal(); // singleton instance
+});
diff --git a/modules/API/Request.php b/modules/API/Request.php
index 767f2269601294aa17ffde984bc8eff32d72c72c..17397949576ac4a058c94d0d45a3390eeaf3eed4 100644
--- a/modules/API/Request.php
+++ b/modules/API/Request.php
@@ -168,7 +168,7 @@ class Piwik_API_Request
 		switch($format)
 		{
 			case 'xml':
-				header('Content-type: text/xml');
+				@header('Content-type: text/xml');
 				$return = 
 					'<?xml version="1.0" encoding="utf-8" ?>'.
 					'<result>'.
@@ -176,7 +176,7 @@ class Piwik_API_Request
 					'</result>';
 			break;
 			case 'json':
-				header( "Content-type: application/json" );
+				@header( "Content-type: application/json" );
 				$return = '{"result":"success", "message":"ok"}';
 			break;
 			case 'php':
diff --git a/modules/ArchiveProcessing.php b/modules/ArchiveProcessing.php
index 386421c454d581bee46fae9f527e9086c2b1b042..1cddc83eb84b9a5dca4dfcf000cc2e8f20ced42e 100644
--- a/modules/ArchiveProcessing.php
+++ b/modules/ArchiveProcessing.php
@@ -122,11 +122,11 @@ abstract class Piwik_ArchiveProcessing
 			$this->postCompute();
 			Piwik::printMemoryUsage('After post compute');
 			
-			Piwik::log("New archive computed, id = {$this->idArchive}");
+//			Piwik::log("New archive computed, id = {$this->idArchive}");
 		}
 		else
 		{
-			Piwik::log("Archive already available, id = {$this->idArchive}");
+			//Piwik::log("Archive already available, id = {$this->idArchive}");
 		}
 		
 		return $this->idArchive;
diff --git a/modules/ArchiveProcessing/Day.php b/modules/ArchiveProcessing/Day.php
index 14bdf8b2a40af0638b01eb7077a1501e70962355..78063b2490727ab8a8541b2eb9ef211e393a59ba 100644
--- a/modules/ArchiveProcessing/Day.php
+++ b/modules/ArchiveProcessing/Day.php
@@ -53,7 +53,6 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing
 		{
 			$record = new Piwik_ArchiveProcessing_Record_Numeric($name, $value);
 		}
-		Piwik::log($row);
 
 		Piwik_PostEvent('ArchiveProcessing_Day.compute', $this);
 	}
diff --git a/modules/Common.php b/modules/Common.php
index ed12510905dc67af4e7fd9731354bb6acfe000b5..bc91fabc29916a898c17cf33e4cb438cd71f6765 100644
--- a/modules/Common.php
+++ b/modules/Common.php
@@ -506,25 +506,51 @@ class Piwik_Common
 	*/
 	static public function getParameterFromQueryString( $urlQuery, $parameter)
 	{	
-		$refererQuery = '&amp;'.trim(str_replace(array('%20'), ' ', '&amp;'.$urlQuery));
-		$word = '&amp;'.$parameter.'=';
-				
-		if( $off = strrpos($refererQuery, $word))
+		$nameToValue = self::getArrayFromQueryString($urlQuery);
+		
+		if(isset($nameToValue[$parameter]))
 		{
-			$off += strlen($word); // &amp;q=
-			$str = substr($refererQuery, $off);
-			$len = strpos($str, '&amp;');
-			if($len === false)
-			{
-				$len = strlen($str);
-			}
-			$toReturn = substr($refererQuery, $off, $len);
-			return $toReturn;
+			return $nameToValue[$parameter];
 		}
-		else
+		return false;
+	}
+	
+	/**
+	 * Returns an URL query string in an array format
+	 * 
+	 * @param string urlQuery
+	 * @return array array( param1=> value1, param2=>value2)
+	 */
+	static public function getArrayFromQueryString( $urlQuery )
+	{
+		if(strlen($urlQuery) == 0)
 		{
-			return false;
+			return array();
+		}
+		if($urlQuery[0] == '?')
+		{
+			$urlQuery = substr($urlQuery, 1);
+		}
+		
+		$separator = '&amp;';
+		
+		$urlQuery = $separator . $urlQuery;
+//		$urlQuery = str_replace(array('%20'), ' ', $urlQuery);
+		$refererQuery = trim($urlQuery);
+		
+		$values = explode($separator, $refererQuery);
+		
+		$nameToValue = array();
+		
+		foreach($values as $value)
+		{
+			if( false !== strpos($value, '='))
+			{
+				$exploded = explode('=',$value);
+				$nameToValue[$exploded[0]] = $exploded[1];
+			}
 		}
+		return $nameToValue;
 	}
 	
 }
diff --git a/modules/DataTable/Manager.php b/modules/DataTable/Manager.php
index a7647d652d203e49031a2752b3d90c59e7f73972..9d5cf4ba53fd6bf24a937ec413836ff3fb144a86 100644
--- a/modules/DataTable/Manager.php
+++ b/modules/DataTable/Manager.php
@@ -60,7 +60,6 @@ class Piwik_DataTable_Manager
 	 */
 	public function deleteAll()
 	{
-		Piwik::log("DELETE ALL ".$this->count()." TABLES");
 		$this->tables = array();
 	}
 	
diff --git a/modules/DataTable/Renderer/XML.php b/modules/DataTable/Renderer/XML.php
index 90f03f46af0449bf19bcf91961a311dd42a0613d..2c82b251a5e9b50a5ce1bc287182c11708ace65f 100644
--- a/modules/DataTable/Renderer/XML.php
+++ b/modules/DataTable/Renderer/XML.php
@@ -51,6 +51,7 @@ class Piwik_DataTable_Renderer_XML extends Piwik_DataTable_Renderer
 			$xmlStr = str_replace(">\n", ">\n\t",$xmlStr);
 			$xmlStr = str_replace("\t</result>", "</result>",$xmlStr);
 		}
+		header('Content-type: text/xml');
 		return $xmlStr;
 	}
 }
\ No newline at end of file
diff --git a/modules/Date.php b/modules/Date.php
index 424d0357e1c18846fe9c1d13c44134227f044783..d4a21742f2c030411c79d8d1b5ee46a7f7cb3a8f 100644
--- a/modules/Date.php
+++ b/modules/Date.php
@@ -24,14 +24,17 @@ class Piwik_Date
 	{
 		return $this->timestamp;
 	}
+	
 	public function isEarlier(Piwik_Date $date)
 	{
 		return $this->getTimestamp() < $date->getTimestamp();
 	}
+	
 	public function toString($part = 'Y-m-d')
 	{
 		return date($part, $this->getTimestamp());
 	}
+	
     /**
      * Sets a new day
      * Returned is the new date object
diff --git a/modules/ErrorHandler.php b/modules/ErrorHandler.php
index e541cb2a28f1ff5f93e68fb373d9c4fc3cdf1f20..5887e071ff5cf49547863b0ccbcf8d6b021f5773 100755
--- a/modules/ErrorHandler.php
+++ b/modules/ErrorHandler.php
@@ -5,10 +5,10 @@
  */
 function Piwik_ErrorHandler($errno, $errstr, $errfile, $errline)
 {
-//    ob_start();
-//    debug_print_backtrace();
-//    $backtrace = ob_get_contents();
-//    ob_end_clean();
+    ob_start();
+    debug_print_backtrace();
+    $backtrace = ob_get_contents();
+    ob_end_clean();
     Zend_Registry::get('logger_error')->log($errno, $errstr, $errfile, $errline, $backtrace);
     
 	switch($errno)
diff --git a/modules/FrontController.php b/modules/FrontController.php
index 32f92b5e0715ac164a05fad286c387d021af8fb8..bf94afb38409cb2cfd55dc63e9ad8aa5649ca545 100644
--- a/modules/FrontController.php
+++ b/modules/FrontController.php
@@ -69,19 +69,16 @@ class Piwik_FrontController
 	
 	function end()
 	{
-		
-		Piwik::printZendProfiler();
-		Piwik::printMemoryUsage();
-		Piwik::printQueryCount();		
+//		Piwik::printZendProfiler();
+//		Piwik::printMemoryUsage();
+//		Piwik::printQueryCount();
 //		Piwik::uninstall();
-
-		Piwik::log($this->timer);
-		
+//
 	}
 	
 	function init()
 	{
-		$this->timer = new Piwik_Timer;
+		Zend_Registry::set('timer', new Piwik_Timer);
 		
 		//move into a init() method
 		Piwik::createConfigObject();
@@ -107,6 +104,10 @@ class Piwik_FrontController
 				Piwik::prefixTable('log_action'),
 				Piwik::prefixTable('log_profiling'),
 				Piwik::prefixTable('archive'),
+				Piwik::prefixTable('logger_api_call'),
+				Piwik::prefixTable('logger_error'),
+				Piwik::prefixTable('logger_exception'),
+				Piwik::prefixTable('logger_message'),
 		);
 		
 		Piwik::dropTables($doNotDrop);
diff --git a/modules/Piwik.php b/modules/Piwik.php
index 6d10c4daf342b64b78002ac14dd8323ffa7ebb00..d0e93960ed2064f2401fd6669438fee5b7655955 100755
--- a/modules/Piwik.php
+++ b/modules/Piwik.php
@@ -573,7 +573,7 @@ class Piwik
 				//create tables
 		$db = Zend_Registry::get('db');
 		
-		Piwik::log("Droping ". implode(", ", self::getTablesNames()));
+//		Piwik::log("Droping ". implode(", ", self::getTablesNames()));
 		
 		$db->query( "DROP TABLE IF EXISTS ". implode(", ", self::getTablesNames()) );
 	}
diff --git a/modules/SmartyPlugins/function.url.php b/modules/SmartyPlugins/function.url.php
new file mode 100644
index 0000000000000000000000000000000000000000..0fbb5726ab1e73d61aa3c81ed654672f07f4a943
--- /dev/null
+++ b/modules/SmartyPlugins/function.url.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {mailto} function plugin
+ *
+ * Examples:
+ * <pre>
+ * {mailto address="me@domain.com"}
+ * {mailto address="me@domain.com" encode="javascript"}
+ * {mailto address="me@domain.com" encode="hex"}
+ * {mailto address="me@domain.com" subject="Hello to you!"}
+ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
+ * {mailto address="me@domain.com" extra='class="mailto"'}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto}
+ *          (Smarty online manual)
+ * @version  1.2
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author   credits to Jason Sweat (added cc, bcc and subject functionality)
+ * @param    array
+ * @param    Smarty
+ * @return   string
+ */
+function smarty_function_url($params, &$smarty)
+{
+	$queryString = Piwik_Url::getCurrentQueryString();
+	$queryString = htmlspecialchars($queryString);
+	$urlValues = Piwik_Common::getArrayFromQueryString($queryString);
+//	var_dump($urlValues);
+	foreach($params as $key => $value)
+	{
+		$urlValues[$key] = $value;
+	}
+	
+	return '?' . http_build_query($urlValues);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/modules/View.php b/modules/View.php
index 3ae6b96baac7d86571c4c960536dca9e16d7fc59..2641c95a703cf67ebc90826a01416e9ff9ad50bd 100644
--- a/modules/View.php
+++ b/modules/View.php
@@ -52,6 +52,7 @@ class Piwik_View
 
 	public function render()
 	{
+		$this->totalTimeGeneration = Zend_Registry::get('timer')->getTime();
 //		$this->smarty->assign('smarty', $this);
 		return $this->smarty->fetch($this->template);
 	}
diff --git a/plugins/Actions.php b/plugins/Actions.php
index 48c55d7d9d63ffbaae2c8e233bddda26abaa4e0a..526410d88a92dfc1123ae86ab83b1416eff38f73 100644
--- a/plugins/Actions.php
+++ b/plugins/Actions.php
@@ -81,7 +81,6 @@ class Piwik_Actions extends Piwik_Plugin
 		
 		$timer = new Piwik_Timer;
 				
-		Piwik::printMemoryUsage();
 		
 		//TODO map nb_visits etc. with numeric indexes to save space, memor and time
 		/*
@@ -101,9 +100,6 @@ class Piwik_Actions extends Piwik_Plugin
 				
 		$modified = $this->updateActionsTableWithRowQuery($query);
 
-		Piwik::log("$modified rows for all actions");
-		
-		Piwik::printMemoryUsage();
 		
 		/*
 		 * Entry actions
@@ -126,9 +122,6 @@ class Piwik_Actions extends Piwik_Plugin
 				
 		$modified = $this->updateActionsTableWithRowQuery($query);
 		
-		Piwik::log("$modified rows for entry actions");
-		
-//		Piwik::printMemoryUsage();
 
 		/*
 		 * Exit actions
@@ -149,9 +142,6 @@ class Piwik_Actions extends Piwik_Plugin
 				
 		$modified = $this->updateActionsTableWithRowQuery($query);
 		
-		Piwik::log("$modified rows for exit actions");
-
-//		Piwik::printMemoryUsage();
 		/*
 		 * Time per action
 		 */
@@ -169,29 +159,22 @@ class Piwik_Actions extends Piwik_Plugin
 				
 		$modified = $this->updateActionsTableWithRowQuery($query);
 		
-		Piwik::log("$modified rows for sum time per action");
-
-		Piwik::printMemoryUsage("Middle of ".get_class($this)." "); 
 		
 		$dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_LogStats_Action::TYPE_ACTION]);
 		$s = $dataTable->getSerialized();
 		$record = new Piwik_ArchiveProcessing_Record_Blob_Array('Actions_actions', $s);
-		Piwik::log(" Action serialized has ".count($s)." elements");
 		
 		
 		$dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_LogStats_Action::TYPE_DOWNLOAD]);
 		$s = $dataTable->getSerialized();
 		$record = new Piwik_ArchiveProcessing_Record_Blob_Array('Actions_downloads', $s);
-		Piwik::log(" Download serialized has ".count($s)." elements");
 		
 		
 		$dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_LogStats_Action::TYPE_OUTLINK]);
 		$s = $dataTable->getSerialized();
 		$record = new Piwik_ArchiveProcessing_Record_Blob_Array('Actions_outlink', $s);
-		Piwik::log(" Outlink serialized has ".count($s)." elements");
 		
 		unset($this->actionsTablesByType);
-		Piwik::printMemoryUsage("End of ".get_class($this)." "); 
 	}
 	
 	static public function getActionCategoryFromName($name)
diff --git a/plugins/Referers/API.php b/plugins/Referers/API.php
index ba0116b6504e6118917ad7905e5499dd4596d130..bde0c697f55252b686587972e7c26fc13c6264b6 100644
--- a/plugins/Referers/API.php
+++ b/plugins/Referers/API.php
@@ -88,6 +88,7 @@ class Piwik_Referers_API extends Piwik_Apiable
 		$dataTable = $this->getDataTable('Referers_urlByWebsite',$idSite, $period, $date, $idSubtable);
 		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array( 'label', 'url', create_function('$label', 'return $label;')) );
 		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getPathFromUrl'));
+		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_truncatePath'));
 		return $dataTable;		
 	}
 	
@@ -153,6 +154,17 @@ function Piwik_getPathFromUrl($url)
 	return $path;
 }
 
+function Piwik_truncatePath( $path )
+{
+	$limit = 27;
+	$path = htmlspecialchars_decode($path);
+	$len = strlen($path);
+	if($len > $limit)
+	{
+		$path = substr($path, 0, $limit-3) . "...";
+	}
+	return htmlspecialchars($path);
+}
 
 function Piwik_getSearchEngineUrlFromName($name)
 {
diff --git a/plugins/UserSettings/Controller.php b/plugins/UserSettings/Controller.php
index 2ac7cfca651acfe49b401a8ac5d4c7ad968d6112..0838bbff458030ba9772f4fff3964aec00f1c5e2 100644
--- a/plugins/UserSettings/Controller.php
+++ b/plugins/UserSettings/Controller.php
@@ -13,6 +13,10 @@ class Piwik_UserSettings_Controller extends Piwik_Controller
 		$view->period = Piwik_Common::getRequestVar('period');
 		$view->idSite = Piwik_Common::getRequestVar('idSite');
 		
+		$view->userLogin = Piwik::getCurrentUserLogin();
+		$view->sites = Piwik_SitesManager_API::getSitesWithAtLeastViewAccess();
+		$view->url = Piwik_Url::getCurrentUrl();
+		
 		$view->dataTableActions = $this->getActions( true );
 		$view->dataTableDownloads = $this->getDownloads( true );
 		$view->dataTableOutlinks = $this->getOutlinks( true );
@@ -75,7 +79,6 @@ class Piwik_UserSettings_Controller extends Piwik_Controller
 		$view->numberDistinctPartners = $this->getNumberOfDistinctPartners(true);
 		$view->numberDistinctPartnersUrls = $this->getNumberOfDistinctPartnersUrls(true);
 
-		
 		echo $view->render();		
 	}
 		
diff --git a/plugins/UserSettings/templates/index.tpl b/plugins/UserSettings/templates/index.tpl
index dd74bf02b1a93d515601bf9d27f41aa5bb35c652..9993993ca318295e809418afb3bc46230e20c14a 100644
--- a/plugins/UserSettings/templates/index.tpl
+++ b/plugins/UserSettings/templates/index.tpl
@@ -8,6 +8,12 @@
 
 <link rel="stylesheet" href="libs/jquery/tooltip/jquery.tooltip.css">
 <link rel="stylesheet" href="plugins/UserSettings/templates/datatable.css">
+
+<script>
+var period = "{$period}";
+var currentDateStr = "{$date}";
+</script>
+
 {literal}
 <style>
 tr.level0 td.label{
@@ -29,15 +35,151 @@ tr td.label img.plusMinus {
 	margin-left:-1em;
 	position:absolute;
 }
+
+
+
+
+
+.calendar td.testSelect, .calendar td.testSelect a{
+	color:red;
+	border-color:red;
+}
 </style>
+
+
+<style type="text/css">@import url(libs/jquery/jquery-calendar.css);</style>
+<script type="text/javascript" src="libs/jquery/jquery-calendar.js"></script>
+<script>
+
+Date.prototype.getWeek = function (dowOffset) {
+	/*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com */
+	
+	dowOffset = typeof(dowOffset) == 'int' ? dowOffset : 0; //default dowOffset to zero
+	var newYear = new Date(this.getFullYear(),0,1);
+	var day = newYear.getDay() - dowOffset; //the day of week the year begins on
+	day = (day >= 0 ? day : day + 7);
+	var daynum = Math.floor((this.getTime() - newYear.getTime() -
+	(this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
+	var weeknum;
+	//if the year starts before the middle of a week
+	if(day < 4) {
+	weeknum = Math.floor((daynum+day-1)/7) + 1;
+	if(weeknum > 52) {
+	nYear = new Date(this.getFullYear() + 1,0,1);
+	nday = nYear.getDay() - dowOffset;
+	nday = nday >= 0 ? nday : nday + 7;
+	/*if the next year starts before the middle of
+	the week, it is week #1 of that year*/
+	weeknum = nday < 4 ? 1 : 53;
+	}
+	}
+	else {
+	weeknum = Math.floor((daynum+day-1)/7);
+	}
+	return weeknum;
+};
+
+var splitDate = currentDateStr.split("-");
+var currentYear = splitDate[0];
+var currentMonth = splitDate[1];
+var currentDay = splitDate[2];
+
+var currentDate = new Date(currentYear, currentMonth, currentDay);
+
+
+
+function isDateSelected( date )
+{
+	var valid = false;
+	if(period == "month" || period == "year")
+	{
+		valid = true;
+	}
+	else if(period == "week" && date.getWeek(1) == currentDate.getWeek(1) )
+	{
+		valid = true;
+	}
+	else if( period == "day"  && date.getDate() == currentDate.getDate() )
+	{
+		valid = true;
+	}
+	
+	if(valid)
+	{
+		return [true, 'testSelect'];
+	}
+	return [true, ''];
+}
+
+
+function updateDate()
+{
+	var date = formatDate(popUpCal.getDateFor($('#chooseDate')[0]));
+
+	var currentUrl = window.location.href;
+	if((startStrDate = currentUrl.indexOf("date")) >= 0)
+	{
+		var dateToReplace = currentUrl.substring( 
+							startStrDate + 4+1, 
+							startStrDate +4+1 +4+1+2+1+2 
+									);
+		regDateToReplace = new RegExp(dateToReplace, 'ig');
+		currentUrl = currentUrl.replace( regDateToReplace, date );		
+	}
+	else
+	{
+		currentUrl = currentUrl + '&date=' + date;
+	}
+	
+	window.location.href = currentUrl;
+}
+
+function formatDate(date) 
+{
+	var day = date.getDate();
+	var month = date.getMonth() + 1;
+	return date.getFullYear() + '-'
+		+ (month < 10 ? '0' : '') + month + '-'
+		+ (day < 10 ? '0' : '') + day ;
+}
+
+$(document).ready(function(){
+	$("#chooseDate").calendar({
+			onSelect: updateDate,
+			dateFormat: 'DMY-',
+			firstDay: 1,
+			minDate: new Date(2007, 1 - 1, 1),
+			maxDate: new Date(2007, 12 - 1, 31),
+			changeFirstDay: false,
+			prevText: "",
+			nextText: "",
+			currentText: "",
+			customDate: isDateSelected
+			});
+	}
+);
+</script>
+
+
 {/literal}
+
+
+<div class="calendarInline" id="inlineFrom"></div>
+
+<br>
+					
 <h1>Piwik reports</h1>
+<span id="chooseDate"></span>
 <p>- Date = {$date}</p>
-<p>- Period = {$period}</p>
-<p>- IdSite = {$idSite}</p>
+<p>Url = {url}</p>
+<p>User logged = {$userLogin}</p>
+{include file="UserSettings/templates/period_select.tpl"}
+{include file="UserSettings/templates/sites_select.tpl"}
+
 
 <h2>Actions</h2>
 {$dataTableActions} 
+{*
 <h2>Downloads</h2>
 {$dataTableDownloads} 
 <h2>Outlinks</h2>
@@ -131,5 +273,6 @@ tr td.label img.plusMinus {
 {$dataTableNumberOfVisitsPerVisitDuration}
 <h3>Visits per number of pages</h3>
 {$dataTableNumberOfVisitsPerPage}
+*}
 
-	
\ No newline at end of file
+{$totalTimeGeneration} seconds to generate the page
\ No newline at end of file
diff --git a/plugins/UserSettings/templates/period_select.tpl b/plugins/UserSettings/templates/period_select.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..723cbecfe182d9379e343f366a753d23b73e7c14
--- /dev/null
+++ b/plugins/UserSettings/templates/period_select.tpl
@@ -0,0 +1,5 @@
+
+<a href="{url period=day}">Day</a> | 
+<a href="{url period=week}">Week</a> | 
+<a href="{url period=month}">Month</a> | 
+<a href="{url period=year}">Year</a>
\ No newline at end of file
diff --git a/plugins/UserSettings/templates/sites_select.tpl b/plugins/UserSettings/templates/sites_select.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..cc2e107203ef5e714a40db5f38e7e013efb55928
--- /dev/null
+++ b/plugins/UserSettings/templates/sites_select.tpl
@@ -0,0 +1,18 @@
+<!-- sites selection id="sites" -->
+<div id="sites">
+Sites: 
+<form action="{$url}" method="post">
+{*<fieldset>
+	<legend> &nbsp; Sites &nbsp; </legend>*}
+	<p>
+	<select name="idSite" onchange="javascript:this.form.submit()">
+		<optgroup label="Sites">
+		   {foreach from=$sites item=info}
+		   		<option label="{$info.name}" value="{$info.idsite}" {if $idSite==$info.idsite} selected="selected"{/if}>{$info.name}</option>
+		   {/foreach}
+		</optgroup>
+	</select>
+	</p>
+{*</fieldset>*}
+</form>
+</div>
\ No newline at end of file