Index: plugins/VisitFrequency/lang/en.php
===================================================================
--- plugins/VisitFrequency/lang/en.php	(wersja 0)
+++ plugins/VisitFrequency/lang/en.php	(wersja 0)
@@ -0,0 +1,11 @@
+<?php
+$translations = array(
+	'VisitFrequency_Evolution' => 'Evolution over the period',
+	'VisitFrequency_ReturnVisits' => '%s returning visits',
+	'VisitFrequency_ReturnActions' => '%s actions by the returning visits',
+	'VisitFrequency_ReturnMaxActions' => '%s maximum actions by a returning visit',
+	'VisitFrequency_ReturnTotalTime' => '%s total time spent by returning visits',
+	'VisitFrequency_ReturnBounces' => '%s times that a returning visit has bounced (left the site after one page)',
+
+);
+
Index: plugins/VisitFrequency/index.tpl
===================================================================
--- plugins/VisitFrequency/index.tpl	(wersja 441)
+++ plugins/VisitFrequency/index.tpl	(kopia robocza)
@@ -2,9 +2,9 @@
 <script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script>
 
 <a name="evolutionGraph" graphId="VisitFrequencygetLastVisitsReturningGraph"></a>
-<h2>Evolution over the period</h2>
+<h2>{'VisitFrequency_Evolution'|translate}</h2>
 {$graphEvolutionVisitFrequency}
 
 {include file=VisitFrequency/sparklines.tpl}
 	
-{postEvent name="template_footerVisitsFrequency"}
\ brakuje znaku końca linii na końcu pliku 
+{postEvent name="template_footerVisitsFrequency"}
Index: plugins/VisitFrequency/VisitFrequency.php
===================================================================
--- plugins/VisitFrequency/VisitFrequency.php	(wersja 441)
+++ plugins/VisitFrequency/VisitFrequency.php	(kopia robocza)
@@ -18,11 +18,12 @@
 	public function getInformation()
 	{
 		$info = array(
-			'name' => 'VisitorFrequency',
+			'name' => 'VisitFrequency',
 			'description' => 'VisitorFrequency',
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
+			'translationAvailable' => true
 		);
 		
 		return $info;
Index: plugins/VisitFrequency/sparklines.tpl
===================================================================
--- plugins/VisitFrequency/sparklines.tpl	(wersja 441)
+++ plugins/VisitFrequency/sparklines.tpl	(kopia robocza)
@@ -1,6 +1,12 @@
 
-	<p><img class="sparkline" src="{$urlSparklineNbVisitsReturning}" /> <span><strong>{$nbVisitsReturning} </strong> returning visits</span></p>
-	<p><img class="sparkline" src="{$urlSparklineNbActionsReturning}" /> <span><strong>{$nbActionsReturning} </strong> actions by the returning visits</span></p>
-	<p><img class="sparkline" src="{$urlSparklineMaxActionsReturning}" /> <span><strong>{$maxActionsReturning} </strong> maximum actions by a returning visit</span></p>
-	<p><img class="sparkline" src="{$urlSparklineSumVisitLengthReturning}" /> <span><strong>{$sumVisitLengthReturning|sumtime} </strong> total time spent by returning visits</span></p>
-	<p><img class="sparkline" src="{$urlSparklineBounceCountReturning}" /> <span><strong>{$bounceCountReturning} </strong> times that a returning visit has bounced (left the site after one page) </span></p>
+	<p><img class="sparkline" src="{$urlSparklineNbVisitsReturning}" /> <span>
+	{'VisitFrequency_ReturnVisits'|translate:"<strong>$nbVisitsReturning</strong>"}</span></p>
+	<p><img class="sparkline" src="{$urlSparklineNbActionsReturning}" /> <span>
+	{'VisitFrequency_ReturnActions'|translate:"<strong>$nbActionsReturning</strong>"}</span></p>
+	<p><img class="sparkline" src="{$urlSparklineMaxActionsReturning}" /> <span>
+	 {'VisitFrequency_ReturnMaxActions'|translate:"<strong>$maxActionsReturning</strong>"}</span></p>
+	<p><img class="sparkline" src="{$urlSparklineSumVisitLengthReturning}" /> <span>
+	 {assign var=sumtimeVisitLengthReturning value=$sumVisitLengthReturning|sumtime}
+	 {'VisitFrequency_ReturnTotalTime'|translate:"<strong>$sumtimeVisitLengthReturning</strong>"}</span></p>
+	<p><img class="sparkline" src="{$urlSparklineBounceCountReturning}" /> <span>
+	 {'VisitFrequency_ReturnBounces'|translate:"<strong>$bounceCountReturning</strong>"} </span></p>
Index: plugins/SitesManager/API.php
===================================================================
--- plugins/SitesManager/API.php	(wersja 441)
+++ plugins/SitesManager/API.php	(kopia robocza)
@@ -270,8 +270,7 @@
 
 		if($nbSites == 1)
 		{
-			throw new Exception("It is not possible to delete this website as it is the only registered website. 
-			Add a new website first, then delete this one.");
+			throw new Exception(Piwik_TranslateException("SitesManager_ExceptionDeleteSite"));
 		}
 		
 		$db = Zend_Registry::get('db');
@@ -300,7 +299,7 @@
 		if(!is_array($urls)
 			|| count($urls) == 0)
 		{
-			throw new Exception("You must specify at least one URL for the site.");
+			throw new Exception(Piwik_TranslateException("SitesManager_ExceptionNoUrl"));
 		}
 	}
 
@@ -477,7 +476,7 @@
 	{
 		if(empty($siteName))
 		{
-			throw new Exception("The site name can't be empty.");
+			throw new Exception(Piwik_TranslateException("SitesManager_ExceptionEmptyName"));
 		}
 	}
 
@@ -493,7 +492,7 @@
 		{			
 			if(!self::isValidUrl($url))
 			{
-				throw new Exception("The url '$url' is not a valid URL.");
+				throw new Exception(sprintf(Piwik_TranslateException("SitesManager_ExceptionInvalidUrl"),$url));
 			}
 		}
 	}
Index: plugins/SitesManager/lang/en.php
===================================================================
--- plugins/SitesManager/lang/en.php	(wersja 0)
+++ plugins/SitesManager/lang/en.php	(wersja 0)
@@ -0,0 +1,19 @@
+<?php
+$translations = array(
+	'SitesManager_Sites' => 'Sites',
+	'SitesManager_JsCode' => 'Javascript code',
+	'SitesManager_JsCodeHelp' => 'Here is the javascript code to include on all your pages',
+	'SitesManager_ShowJsCode' => 'show code',
+	'SitesManager_NoWebsites' => 'You don\'t have any website to administrate.',
+	'SitesManager_AddSite' => 'Add a new Site',
+	'SitesManager_Id' => 'Id',
+	'SitesManager_Name' => 'Name',
+	'SitesManager_Urls' => 'URLs',
+
+	'SitesManager_DeleteConfirm_js' => 'Are you sure you want to delete the website %s?',
+	
+	'SitesManager_ExceptionDeleteSite' => 'It is not possible to delete this website as it is the only registered website. Add a new website first, then delete this one.',
+	'SitesManager_ExceptionNoUrl' => 'You must specify at least one URL for the site.',
+	'SitesManager_ExceptionEmptyName' => 'The site name can\'t be empty.',
+	'SitesManager_ExceptionInvalidUrl' => 'The url \'%s\' is not a valid URL.',
+);
Index: plugins/SitesManager/SitesManager.php
===================================================================
--- plugins/SitesManager/SitesManager.php	(wersja 441)
+++ plugins/SitesManager/SitesManager.php	(kopia robocza)
@@ -24,7 +24,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
-			'translationAvailable' => false,
+			'translationAvailable' => true,
 		);
 		
 		return $info;
Index: plugins/SitesManager/Controller.php
===================================================================
--- plugins/SitesManager/Controller.php	(wersja 441)
+++ plugins/SitesManager/Controller.php	(kopia robocza)
@@ -39,4 +39,4 @@
 		
 		echo $view->render();
 	}
-}
\ brakuje znaku końca linii na końcu pliku 
+}
Index: plugins/SitesManager/templates/SitesManager.tpl
===================================================================
--- plugins/SitesManager/templates/SitesManager.tpl	(wersja 441)
+++ plugins/SitesManager/templates/SitesManager.tpl	(kopia robocza)
@@ -1,21 +1,23 @@
+{loadJavascriptTranslations modules='SitesManager'}
+
 <script type="text/javascript" src="plugins/SitesManager/templates/SitesManager.js"></script>
 
-<h2>Sites</h2>
+<h2>{'SitesManager_Sites'|translate}</h2>
 <div id="ajaxError" style="display:none"></div>
-<div id="ajaxLoading" style="display:none">Loading... <img src="themes/default/loading.gif"></div>
+<div id="ajaxLoading" style="display:none">{'General_LoadingData'|translate} <img src="themes/default/loading.gif"></div>
 
 {if $sites|@count == 0}
-	You don't have any website to administrate.
+	{'SitesManager_NoWebsites'|translate}
 {else}
 	<table id="editSites" border=1 cellpadding="10">
 		<thead>
 			<tr>
-			<th>Id</th>
-			<th>Name</th>
-			<th>URLs</th>
+			<th>{'SitesManager_Id'|translate}</th>
+			<th>{'SitesManager_Name'|translate}</th>
+			<th>{'SitesManager_Urls'|translate}</th>
 			<th> </th>
 			<th> </th>
-			<th> Javascript code </th>
+			<th> {'SitesManager_JsCode'|translate} </th>
 			</tr>
 		</thead>
 		<tbody>
@@ -25,13 +27,13 @@
 				<td id="siteName" class="editableSite">{$site.name}</td>
 				<td id="urls" class="editableSite">{foreach from=$site.alias_urls item=url}{$url}<br>{/foreach}</td>       
 				<td><img src='plugins/UsersManager/images/edit.png' class="editSite" id="row{$i}" href='#'></td>
-				<td><img src='plugins/UsersManager/images/remove.png' class="deleteSite" id="row{$i}" value="Delete"></td>
-				<td><a href='{url actionToLoad=displayJavascriptCode idsite=$site.idsite}'>Show Code</a></td>
+				<td><img src='plugins/UsersManager/images/remove.png' class="deleteSite" id="row{$i}" value="{'General_Delete'|translate}"></td>
+				<td><a href='{url actionToLoad=displayJavascriptCode idsite=$site.idsite}'>{'SitesManager_ShowJsCode'|translate}</a></td>
 			</tr>
 			{/foreach}
 			
 		</tbody>
 	</table>
-	<div id="addRowSite"><img src='plugins/UsersManager/images/add.png'> <a href="#">Add a new Site</a></div>
+	<div id="addRowSite"><img src='plugins/UsersManager/images/add.png'> <a href="#">{'SitesManager_AddSite'|translate}</a></div>
 {/if}
 
Index: plugins/SitesManager/templates/DisplayJavascriptCode.tpl
===================================================================
--- plugins/SitesManager/templates/DisplayJavascriptCode.tpl	(wersja 441)
+++ plugins/SitesManager/templates/DisplayJavascriptCode.tpl	(kopia robocza)
@@ -1,4 +1,4 @@
-<p>Here is the javascript code to include on all your pages:</p>
+<p>{'SitesManager_JsCodeHelp'|translate}:</p>
 
 <code>
 {$jsTag}
Index: plugins/SitesManager/templates/SitesManager.js
===================================================================
--- plugins/SitesManager/templates/SitesManager.js	(wersja 441)
+++ plugins/SitesManager/templates/SitesManager.js	(kopia robocza)
@@ -108,7 +108,7 @@
 			var idRow = $(this).attr('id');
 			var nameToDelete = $(this).parent().parent().find('#siteName').html();
 			var idsiteToDelete = $(this).parent().parent().find('#idSite').html();
-			if(confirm('Are you sure you want to delete the website "'+nameToDelete+'" (idSite = '+idsiteToDelete+')?'))
+			if(confirm(_pk_translate('SitesManager_DeleteConfirm','Are you sure you want to delete the website %s','"'+nameToDelete+'" (idSite = '+idsiteToDelete+')')) )
 			{
 				$.ajax( getDeleteSiteAJAX( idsiteToDelete ) );
 			}
Index: plugins/Feedback/lang/en.php
===================================================================
--- plugins/Feedback/lang/en.php	(wersja 0)
+++ plugins/Feedback/lang/en.php	(wersja 0)
@@ -0,0 +1,7 @@
+<?php
+
+// not translated - feedback should be sent in English!!!
+
+$translations = array(
+);
+
Index: plugins/Feedback/index.tpl
===================================================================
--- plugins/Feedback/index.tpl	(wersja 0)
+++ plugins/Feedback/index.tpl	(wersja 0)
@@ -0,0 +1,24 @@
+<form method="post" action="?module=Feedback&action=sendFeedback">
+
+<p><strong>Your name:</strong>
+<br /><input type="text" name="name" size="50" /></p>
+
+<p><strong>Your e-mail:</strong>
+<br /><input type="text" name="email" size="50" /></p>
+
+<p><strong>Choose category:</strong>
+<br /><select name="category">
+	<option value="bug">Bug report</option>
+	<option value="feature">Feature missing</option>
+</select>
+</p>
+
+<p><strong>Topic:</strong>
+<br /><input type="text" name="topic" size="50" /></p>
+
+<p><strong>Body:</strong>
+<br /><textarea name="body" cols="50" rows="15"></textarea></p>
+
+<p><input type="submit" value="Send feedback" />
+
+</form>
Index: plugins/Feedback/sent.tpl
===================================================================
--- plugins/Feedback/sent.tpl	(wersja 0)
+++ plugins/Feedback/sent.tpl	(wersja 0)
@@ -0,0 +1,3 @@
+<p>A mail was sent to Piwik developers</p>
+
+<p><strong>Thank you for your feedback.</strong><br /> - Piwik Team</p>
Index: plugins/Feedback/Controller.php
===================================================================
--- plugins/Feedback/Controller.php	(wersja 0)
+++ plugins/Feedback/Controller.php	(wersja 0)
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: Controller.php 169 2008-01-14 05:41:15Z matt $
+ * 
+ * @package Piwik_Feedback
+ */
+
+
+
+/**
+ *
+ * @package Piwik_Feedback 
+ */
+class Piwik_Feedback_Controller extends Piwik_Controller
+{	
+	function index()
+	{		
+		$view = new Piwik_View('Feedback/index.tpl');
+				
+		echo $view->render();
+	}
+
+	/**
+	 * send email to Piwik team and display nice thanks
+	 */
+	function sendFeedback()
+	{
+		// TODO: require user login or captcha if anonymous		
+		
+		$name = Piwik_Common::getRequestVar('name', '', 'string');
+		$topic = Piwik_Common::getRequestVar('topic', '', 'string');
+		$body = Piwik_Common::getRequestVar('body', '', 'string');
+		$email = Piwik_Common::getRequestVar('email', '', 'string');
+		$category = Piwik_Common::getRequestVar('category', '', 'string');
+		
+		$mail = new Piwik_Mail();
+		$mail->setFrom($email, $name);
+		$mail->addTo('hello@piwik.org','Piwik Team');
+		$mail->setSubject('[feedback:'.$category.'] '.$topic);
+		$mail->setBodyText($body);
+		$mail->send();
+		
+		$view = new Piwik_View('Feedback/sent.tpl');			
+		echo $view->render();
+	}
+}
Index: plugins/Feedback/Feedback.php
===================================================================
--- plugins/Feedback/Feedback.php	(wersja 0)
+++ plugins/Feedback/Feedback.php	(wersja 0)
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: ExamplePlugin.php 169 2008-01-14 05:41:15Z matt $
+ * 
+ * @package Piwik_Feedback
+ */
+
+class Piwik_Feedback extends Piwik_Plugin
+{
+	public function getInformation()
+	{
+		return array(
+			'name' => 'Feedback',
+			'description' => '',
+			'author' => 'Piwik',
+			'homepage' => 'http://piwik.org/',
+			'version' => '0.1',
+			'translationAvailable' => true,
+		);
+	}
+}
Index: plugins/Dashboard/lang/en.php
===================================================================
--- plugins/Dashboard/lang/en.php	(wersja 0)
+++ plugins/Dashboard/lang/en.php	(wersja 0)
@@ -0,0 +1,14 @@
+<?php
+$translations = array(
+	'Dashboard_AddWidget' => 'Add a widget...',
+	'Dashboard_DeleteWidgetConfirm' => 'Are you sure you want to delete this widget from the dashboard?',
+	'Dashboard_SelectWidget' => 'Select the widget to add in the dashboard',
+	'Dashboard_AddPreviewedWidget' => 'Add previewed widget to the dashboard',
+	'Dashboard_WidgetPreview' => 'Widget preview',	
+
+	'Dashboard_TitleWidgetInDashboard_js' => 'Widget already in dashboard',
+	'Dashboard_TitleClickToAdd_js' => 'Click to add to dashboard',
+	'Dashboard_LoadingPreview_js' => 'Loading preview, please wait...',
+	'Dashboard_LoadingWidget_js' => 'Loading widget, please wait...',
+	'Dashboard_WidgetNotFound_js' => 'Widget not found',
+);
Index: plugins/Dashboard/Dashboard.php
===================================================================
--- plugins/Dashboard/Dashboard.php	(wersja 441)
+++ plugins/Dashboard/Dashboard.php	(kopia robocza)
@@ -20,6 +20,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
+			'translationAvailable' => true,
 		);
 	}
 
Index: plugins/Dashboard/templates/Dashboard.js
===================================================================
--- plugins/Dashboard/templates/Dashboard.js	(wersja 441)
+++ plugins/Dashboard/templates/Dashboard.js	(kopia robocza)
@@ -1,18 +1,3 @@
-
-
-//label and string used in the javascript
-//overide this object for dataTable_translation
-if(typeof dashboard_translation == "undefined")
-{
-	var dashboard_translation = {
-		titleWidgetInDashboard: 	'Widget already in dashboard',
-		titleClickToAdd: 			'Click to add to dashboard',
-		loadingPreview: 			'Loading preview, please wait...',
-		loadingWidget: 				'Loading widget, please wait...',
-		widgetNotFound: 			'Widget not found'
-	};
-}
-
 //there is a problem with loop for-in when we extends javascript Array
 //so I prefer using a separate function to do this
 function contains(array, searchElem) {
@@ -158,7 +143,7 @@
 						//format the div for upcomming ajax loading and set a temporary content
 						$(this)	.attr('plugin', plugin)
 								.attr('id', action)
-								.html('<div id="previewLoading"><img src="themes/default/loading.gif" />'+ dashboard_translation.loadingPreview +'</div>').show();
+								.html('<div id="previewLoading"><img src="themes/default/loading.gif" />'+ _pk_translate('Dashboard_LoadingPreview','Loading preview, please wait...') +'</div>').show();
 						self.dashboard.ajaxLoading(plugin, action);
 					}
 				});
@@ -208,12 +193,12 @@
 			if(contains(widgets, plugin+'.'+action))
 			{
 				$(this).addClass('menuDisabled');
-				$(this).attr('title', dashboard_translation.titleWidgetInDashboard);
+				$(this).attr('title', _pk_translate('Dashboard_TitleWidgetInDashboard','Widget already in dashboard'));
 			}
 			else
 			{
 				$(this).removeClass('menuDisabled');
-				$(this).attr('title', dashboard_translation.titleClickToAdd);
+				$(this).attr('title', _pk_translate('Dashboard_TitleClickToAdd','Click to add to dashboard'));
 			}
 		});
 	},
@@ -343,7 +328,7 @@
 		if(typeof onTop == "undefined")
 			onTop = false;
 		
-		var item = '<div class="items"><div class="widget"><div class="widgetLoading">'+dashboard_translation.loadingWidget+'</div><div plugin="'+plugin+'"'+' id="'+action+'" class="widgetDiv"></div></div></div>';
+		var item = '<div class="items"><div class="widget"><div class="widgetLoading">'+ _pk_translate('Dashboard_LoadingWidget','Loading widget, please wait...') +'</div><div plugin="'+plugin+'"'+' id="'+action+'" class="widgetDiv"></div></div></div>';
 	
 		if(onTop)
 		{
@@ -390,7 +375,7 @@
 	{
 		var self = this;
 		
-		var title = dashboard_translation.widgetNotFound;
+		var title = _pk_translate('Dashboard_WidgetNotFound','Widget not found');
 		var widgets = piwik.availableWidgets[plugin];
 		for(var i in widgets)
 		{
Index: plugins/Dashboard/templates/index.tpl
===================================================================
--- plugins/Dashboard/templates/index.tpl	(wersja 441)
+++ plugins/Dashboard/templates/index.tpl	(kopia robocza)
@@ -1,3 +1,5 @@
+{loadJavascriptTranslations modules='Dashboard'}
+
 <script type="text/javascript">
 	{* define some global constants for the following javascript includes *}
 	var piwik = new Object;
@@ -22,18 +24,18 @@
  
 	<div class="dialog" id="confirm"> 
 	        <img src="themes/default/images/delete.png" style="padding: 10px; position: relative; margin-top: 10%; float: left;"/>
-	        <p>Are you sure you want to delete this widget from the dashboard ?</p>
-			<input id="yes" type="button" value="Yes"/>
-			<input id="no" type="button" value="No"/>
+	        <p>{'Dashboard_DeleteWidgetConfirm'|translate}</p>
+			<input id="yes" type="button" value="{'General_Yes'|translate}"/>
+			<input id="no" type="button" value="{'General_No'|translate}"/>
 	</div> 
 
 	<div class="button" id="addWidget">
-		Add a widget...
+		{'Dashboard_AddWidget'|translate}
 	</div>
 	
 	<div class="menu" id="widgetChooser">
-		<div id="closeMenuIcon"><img src="themes/default/images/close_medium.png" title="Close this menu"/></div>
-		<div id="menuTitleBar">Select the widget to add in the dashboard</div>
+		<div id="closeMenuIcon"><img src="themes/default/images/close_medium.png" title="{'General_Close'|translate}"/></div>
+		<div id="menuTitleBar">{'Dashboard_SelectWidget'|translate}</div>
 		<div class="subMenu" id="sub1">
 		</div>
 		
@@ -42,11 +44,11 @@
 		
 		<div class="subMenu" id="sub3">
 			<div class="widget">
-				<div class="handle" title="Add previewed widget to the dashboard">
+				<div class="handle" title="{'Dashboard_AddPreviewedWidget'|translate}">
 					<div class="button" id="close">
-						<img src="themes/default/images/close.png" />
+						<img src="themes/default/images/close.png" title="{'General_Close'|translate}"/>
 					</div>
-					<div class="widgetTitle">Widget preview</div>
+					<div class="widgetTitle">{'Dashboard_WidgetPreview'|translate}</div>
 				</div>
 				<div class="widgetDiv previewDiv"></div>
 			</div>
Index: plugins/Dashboard/templates/header.tpl
===================================================================
--- plugins/Dashboard/templates/header.tpl	(wersja 441)
+++ plugins/Dashboard/templates/header.tpl	(kopia robocza)
@@ -1,6 +1,8 @@
 {* This header is for loading the dashboard in stand alone mode*}
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
 
+{loadJavascriptTranslations modules='Home Dashboard'}
+
 <script type="text/javascript" src="libs/jquery/jquery.js"></script>
 
 <script type="text/javascript" src="themes/default/common.js"></script>
@@ -20,4 +22,4 @@
 <script type="text/javascript" src="libs/jquery/ui.sortable_modif.js"></script>
 
 <link rel="stylesheet" href="plugins/Home/templates/datatable.css">
-<link rel="stylesheet" href="plugins/Dashboard/templates/dashboard.css">
\ brakuje znaku końca linii na końcu pliku 
+<link rel="stylesheet" href="plugins/Dashboard/templates/dashboard.css">
Index: plugins/Home/lang/en.php
===================================================================
--- plugins/Home/lang/en.php	(wersja 0)
+++ plugins/Home/lang/en.php	(wersja 0)
@@ -0,0 +1,17 @@
+<?php
+$translations = array(
+	'Home_NoPrivileges' => "You are logged in as '%s' but it seems you don't have any permission set in Piwik.".
+		"<br />Ask your Piwik administrator to give you 'view' access to a website.",
+	'Home_JavascriptDisabled' => "JavaScript must be enabled in order for you to use Piwik in standard view.<br>".
+		"However, it seems JavaScript is either disabled or not supported by your browser.<br>".
+		"To use standard view, enable JavaScript by changing your browser options, then %1stry again%2s.<br>",
+	'Home_TableNoData' => 'No data for this table.',
+	'Home_CategoryNoData' => 'No data in this category. Try to "Include all population".',
+	'Home_ShowJSCode' => 'Show the javascript code to insert',
+	
+	'Home_IncludeAllPopulation_js' => 'Include all population',
+	'Home_ExcludeLowPopulation_js' => 'Exclude low population',
+	'Home_PageOf_js' => '%s of %s',
+	'Home_Loading_js' => 'Loading...',
+	
+);
Index: plugins/Home/Controller.php
===================================================================
--- plugins/Home/Controller.php	(wersja 441)
+++ plugins/Home/Controller.php	(kopia robocza)
@@ -37,9 +37,8 @@
 		{
 			if(($currentLogin = Piwik::getCurrentUserLogin()) != 'anonymous')
 			{
-				Piwik_ExitWithMessage( "You are logged in as '$currentLogin' but it seems you don't have any permission set in Piwik.
-				<br />Ask your Piwik administrator to give you 'view' access to a website.
-				<br /><br />&nbsp;&nbsp;&nbsp;<b><a href='?module=Login&action=logout'>&rsaquo; Logout from Piwik</a></b><br />");
+				Piwik_ExitWithMessage( sprintf(Piwik_Translate('Home_NoPrivileges'),$currentLogin).
+				"<br /><br />&nbsp;&nbsp;&nbsp;<b><a href='?module=Login&action=logout'>&rsaquo; ".Piwik_Translate('General_Logout')."</a></b><br />");
 			}
 			else
 			{
@@ -117,4 +116,4 @@
 
 	
 
-}
\ brakuje znaku końca linii na końcu pliku 
+}
Index: plugins/Home/templates/datatable.tpl
===================================================================
--- plugins/Home/templates/datatable.tpl	(wersja 441)
+++ plugins/Home/templates/datatable.tpl	(kopia robocza)
@@ -3,7 +3,7 @@
 		{$arrayDataTable.message} 
 	{else}
 		{if count($arrayDataTable) == 0}
-		<div id="emptyDatatable">No data for this table.</div>
+		<div id="emptyDatatable">{'Home_TableNoData'|translate}</div>
 		{else}
 			<a name="{$id}"></a>
 			<table cellspacing="0" class="dataTable"> 
Index: plugins/Home/templates/links_misc_modules.tpl
===================================================================
--- plugins/Home/templates/links_misc_modules.tpl	(wersja 441)
+++ plugins/Home/templates/links_misc_modules.tpl	(kopia robocza)
@@ -1,3 +1,5 @@
+<script type="text/javascript" src="libs/jquery/thickbox.js"></script>
+<link rel="stylesheet" href="libs/jquery/thickbox.css">
 <span id="miscLinks">
 	<ul>
 		<li><a href='?module=API&action=listAllAPI'><b>API</b> examples</a></li>
@@ -2,4 +4,5 @@
 		<li><a href='?module=AdminHome'>Administration</a></li>
-		<li><a href='?module=Widgetize'>Embed</a> Piwik widgets everywhere</li>
+		<li><a href='?module=Widgetize'>Embed</a> Piwik widgets everywhere</li>
+		<li><a href="?module=Feedback&action=index&keepThis=true&TB_iframe=true&height=550&width=400" title="Send us feedback" class="thickbox">Send us feedback</a></li>
 	</ul>
-</span>
\ brakuje znaku końca linii na końcu pliku 
+</span>
Index: plugins/Home/templates/datatable_actions_subdatable.tpl
===================================================================
--- plugins/Home/templates/datatable_actions_subdatable.tpl	(wersja 441)
+++ plugins/Home/templates/datatable_actions_subdatable.tpl	(kopia robocza)
@@ -3,7 +3,7 @@
 	{$arrayDataTable.message} 
 {else}
 	{if count($arrayDataTable) == 0}
-	<tr><td colspan="{$nbColumns}">No data in this category. Try to "Include all population".</td></tr>
+	<tr><td colspan="{$nbColumns}">{'Home_CategoryNoData'|translate}</td></tr>
 	{else}
 		{foreach from=$arrayDataTable item=row}
 		<tr {if $row.idsubdatatable}class="subActionsDataTable" id="{$row.idsubdatatable}"{else}class="actionsDataTable"{/if}>
@@ -16,4 +16,4 @@
 		</tr>
 		{/foreach}
 	{/if}		
-{/if}
\ brakuje znaku końca linii na końcu pliku 
+{/if}
Index: plugins/Home/templates/datatable_actions_recursive.tpl
===================================================================
--- plugins/Home/templates/datatable_actions_recursive.tpl	(wersja 441)
+++ plugins/Home/templates/datatable_actions_recursive.tpl	(kopia robocza)
@@ -3,7 +3,7 @@
 	{$arrayDataTable.message} 
 {else}
 	{if count($arrayDataTable) == 0}
-		<div id="emptyDatatable">No data for this table.</div>
+		<div id="emptyDatatable">{'Home_TableNoData'|translate}</div>
 	{else}
 		<table cellspacing="0" class="dataTable dataTableActions"> 
 		<thead>
@@ -41,4 +41,4 @@
 	{include file="Home/templates/datatable_actions_js.tpl"}
 	
 	{/if}
-</div>
\ brakuje znaku końca linii na końcu pliku 
+</div>
Index: plugins/Home/templates/menu.css
===================================================================
--- plugins/Home/templates/menu.css	(wersja 441)
+++ plugins/Home/templates/menu.css	(kopia robocza)
@@ -24,15 +24,15 @@
 	border-left: 1px solid #fff;
 	float: left;
 	list-style: none;
-	z-index: 999;
+	z-index: 49;
 }
 
 .nav li.current ul {
-	z-index: 999;
+	z-index: 49;
 }
 
 .nav li.sfHover ul,ul.nav li:hover ul {
-	z-index: 1000;
+	z-index: 50;
 }
 
 /* LEVEL2 NORMAL */
@@ -108,4 +108,4 @@
 when and how it appears*/
 .superfish li:hover ul,.superfish li li:hover ul {
 	top: -999em;
-}
\ brakuje znaku końca linii na końcu pliku 
+}
Index: plugins/Home/templates/datatable.js
===================================================================
--- plugins/Home/templates/datatable.js	(wersja 441)
+++ plugins/Home/templates/datatable.js	(kopia robocza)
@@ -1,16 +1,3 @@
-
-//label and string used in the javascript
-//overide this object for dataTable_translation
-if(typeof dataTable_translation == "undefined")
-{
-	var dataTable_translation = {
-		includeLowPop: 		'Include all population',
-		excludeLowPop: 		'Exclude low population',
-		pageOf: 			' of ',						//like in 1-10 _of_ 42
-		loading: 			'Loading...'
-	};
-}
-
 //-----------------------------------------------------------------------------
 //								Data Table
 //-----------------------------------------------------------------------------
@@ -281,11 +268,11 @@
 					{
 						if(Number(self.param.filter_excludelowpop) != 0)
 						{
-							string = dataTable_translation.includeLowPop;
+							string = _pk_translate('Home_IncludeAllPopulation','Include all population');
 						}
 						else
 						{
-							string = dataTable_translation.excludeLowPop;
+							string = _pk_translate('Home_ExcludeLowPopulation','Exclude low population');
 						}
 						$(this).html(string);
 					} 
@@ -423,7 +410,7 @@
 					// only show this string if there is some rows in the datatable
 					if(totalRows != 0)
 					{
-						var str = offset + '-' + offsetEndDisp + dataTable_translation.pageOf + totalRows;
+						var str = _pk_translate('Home_PageOf','%s of %s',offset + '-' + offsetEndDisp,totalRows);
 						$(this).text(str);
 					}
 				}
@@ -631,7 +618,7 @@
 					<tr>\
 						<td colspan="'+numberOfColumns+'" class="cellSubDataTable">\
 							<div id="'+divIdToReplaceWithSubTable+'">\
-								<span id="loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" />'+ dataTable_translation.loading +'</span>\
+								<span id="loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" />'+ _pk_translate('Home_Loading','Loading...') +'</span>\
 							</div>\
 						</td>\
 					</tr>\
@@ -999,4 +986,4 @@
 	$('img',domElem).attr('src', 'themes/default/images/plus.png');
 }
 
-	
\ brakuje znaku końca linii na końcu pliku 
+	
Index: plugins/Home/templates/datatable_footer.tpl
===================================================================
--- plugins/Home/templates/datatable_footer.tpl	(wersja 441)
+++ plugins/Home/templates/datatable_footer.tpl	(kopia robocza)
@@ -7,8 +7,8 @@
 	</span>
 	
 	<span id="dataTablePages"></span>
-	<span id="dataTablePrevious">&lt; Previous</span>
-	<span id="dataTableNext">Next &gt;</span>
+	<span id="dataTablePrevious">&lt; {'General_Previous'|translate}</span>
+	<span id="dataTableNext">{'General_Next'|translate} &gt;</span>
 	<div>
 		<span id="exportDataTable">
 			<span id="exportToFormat" style="display:none">
@@ -19,17 +19,17 @@
 					<a target="_blank" class="exportToFormat" methodToCall="{$method}" format="JSON" filter_limit="100">Json</a> |
 					<a target="_blank" class="exportToFormat" methodToCall="{$method}" format="PHP" filter_limit="100">Php</a>
 				</span>
-				<a class="viewDataTable" format="table"><img width="16" height="16" src="themes/default/images/table.png" title="Table" /></a>
-				<a class="viewDataTable" format="cloud"><img width="16" height="16" src="themes/default/images/tagcloud.png" title="Tag Cloud" /></a>
-				<a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="themes/default/images/chart_bar.png" title="Vertical bar graph" /></a>
-				<a class="viewDataTable" format="graphPie"><img width="16" height="16" src="themes/default/images/chart_pie.png" title="Pie chart" /></a>
+				<a class="viewDataTable" format="table"><img width="16" height="16" src="themes/default/images/table.png" title="{'General_Table'|translate}" /></a>
+				<a class="viewDataTable" format="cloud"><img width="16" height="16" src="themes/default/images/tagcloud.png" title="{'General_TagCloud'|translate}" /></a>
+				<a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="themes/default/images/chart_bar.png" title="{'General_VBarGraph'|translate}" /></a>
+				<a class="viewDataTable" format="graphPie"><img width="16" height="16" src="themes/default/images/chart_pie.png" title="{'General_Piechart'|translate}" /></a>
 			</span>
 			<span id="exportDataTableShow" style="display:none">
 				<img src="plugins/Home/templates/images/more.png" />
 			</span>
 		</span>
 
-		<span id="loadingDataTable"><img src="themes/default/images/loading-blue.gif" /> Loading...</span>
+		<span id="loadingDataTable"><img src="themes/default/images/loading-blue.gif" /> {'General_LoadingData'|translate}</span>
 	</div>
 </div>
 
Index: plugins/Home/templates/datatable_actions.tpl
===================================================================
--- plugins/Home/templates/datatable_actions.tpl	(wersja 441)
+++ plugins/Home/templates/datatable_actions.tpl	(kopia robocza)
@@ -3,7 +3,7 @@
 	{$arrayDataTable.message} 
 {else}
 	{if count($arrayDataTable) == 0}
-		<div id="emptyDatatable">No data for this table.</div>
+		<div id="emptyDatatable">{'Home_TableNoData'|translate}</div>
 	{else}
 		<table cellspacing="0" class="dataTable dataTableActions"> 
 		<thead>
Index: plugins/Home/templates/graph.tpl
===================================================================
--- plugins/Home/templates/graph.tpl	(wersja 441)
+++ plugins/Home/templates/graph.tpl	(kopia robocza)
@@ -6,7 +6,7 @@
 	<form class="formEmbedCode" id="{$formId}">
 	Embed <input name="embed_code" value="{$codeEmbed}" onclick="javascript:document.getElementById('{$formId}').embed_code.focus();document.getElementById('{$formId}').embed_code.select();" readonly="true" type="text">
 	
-	| <a target="_blank" href="{$urlData}">Graph data</a>
+	| <a target="_blank" href="{$urlData}">{'General_GraphData'|translate}</a>
 	</form>
 	
 	{include file="Home/templates/datatable_footer.tpl"}
Index: plugins/Home/templates/index.tpl
===================================================================
--- plugins/Home/templates/index.tpl	(wersja 441)
+++ plugins/Home/templates/index.tpl	(kopia robocza)
@@ -4,6 +4,7 @@
 </head>
 <body>
 
+{loadJavascriptTranslations modules='Home'}
 
 <script type="text/javascript">
 var period = "{$period}";
@@ -282,7 +283,7 @@
 	   {/foreach}
 	</optgroup>
 </select>
-</span> | {if $userLogin=='anonymous'}<a href='?module=Login'>Login</a>{else}<a href='?module=Login&action=logout'>Logout</a>{/if}</a>
+</span> | {if $userLogin=='anonymous'}<a href='?module=Login'>{'Login_LogIn'|translate}</a>{else}<a href='?module=Login&action=logout'>{'Login_Logout'|translate}</a>{/if}</a>
 </small>
 </form>
 </span>
@@ -299,9 +300,7 @@
 
 <noscript>
 <span id="javascriptDisable">
-JavaScript must be enabled in order for you to use Piwik in standard view.<br> 
-However, it seems JavaScript is either disabled or not supported by your browser.<br> 
-To use standard view, enable JavaScript by changing your browser options, then <a href=''>try again</a>.<br>
+{'Home_JavascriptDisabled'|translate:'<a href="">':'</a>'}
 </span>
 </noscript>
 {include file="Home/templates/period_select.tpl"}
@@ -311,8 +310,8 @@
 
 <div style='clear:both'></div>
 
-<div id="loadingPiwik" {if $basicHtmlView}style="display:none"{/if}><img src="themes/default/images/loading-blue.gif"> Loading data...</div>
-<div id="loadingError">Oops&hellip; problem during the request, please try again.</div>
+<div id="loadingPiwik" {if $basicHtmlView}style="display:none"{/if}><img src="themes/default/images/loading-blue.gif"> {'General_LoadingData'|translate}</div>
+<div id="loadingError">{'General_ErrorRequest'|translate}</div>
 <div id='content'>
 {if $content}{$content}{/if}
 </div>
Index: plugins/Home/templates/datatable_js.tpl
===================================================================
--- plugins/Home/templates/datatable_js.tpl	(wersja 441)
+++ plugins/Home/templates/datatable_js.tpl	(kopia robocza)
@@ -1,4 +1,3 @@
-
 <script type="text/javascript" defer="defer">
 $(document).ready(function(){literal}{{/literal} 
 	dataTables['{$id}'] = new dataTable();
Index: plugins/Home/Home.php
===================================================================
--- plugins/Home/Home.php	(wersja 441)
+++ plugins/Home/Home.php	(kopia robocza)
@@ -20,7 +20,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
-			'translationAvailable' => false,
+			'translationAvailable' => true,
 		);
 	}
 }
Index: plugins/PluginsAdmin/PluginsAdmin.php
===================================================================
--- plugins/PluginsAdmin/PluginsAdmin.php	(wersja 441)
+++ plugins/PluginsAdmin/PluginsAdmin.php	(kopia robocza)
@@ -15,12 +15,12 @@
 	{
 		return array(
 			// name must be the className prefix!
-			'name' => 'Plugins administration',
+			'name' => 'PluginsAdmin',
 			'description' => '',
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
-			'translationAvailable' => false,
+			'translationAvailable' => true,
 		);
 	}
 }
Index: plugins/PluginsAdmin/lang/en.php
===================================================================
--- plugins/PluginsAdmin/lang/en.php	(wersja 0)
+++ plugins/PluginsAdmin/lang/en.php	(wersja 0)
@@ -0,0 +1,8 @@
+<?php
+$translations = array(
+	'PluginsAdmin_Plugins' => 'Plugins',
+	'PluginsAdmin_Activated' => 'Activated',
+	'PluginsAdmin_ActivatedHelp' => 'This plugin cannot be deactivated',
+	'PluginsAdmin_Deactivate' => 'Deactivate',
+	'PluginsAdmin_Activate' => 'Activate',	
+);
Index: plugins/PluginsAdmin/templates/manage.tpl
===================================================================
--- plugins/PluginsAdmin/templates/manage.tpl	(wersja 441)
+++ plugins/PluginsAdmin/templates/manage.tpl	(kopia robocza)
@@ -20,8 +20,8 @@
 	<td>{$plugin.info.description}&nbsp;</td>
 	<td class="center"><a href="{$plugin.info.homepage}">{$plugin.info.author}</a></td>
 	<td>{$plugin.info.version}</td>
-	<td class="switch">{if $plugin.alwaysActivated}<span title="This plugin cannot be deactivated">Activated</span>{elseif $plugin.activated}<a href=?module=PluginsAdmin&action=deactivate&pluginName={$name}>Deactivate</a>
-{else}<a href=?module=PluginsAdmin&action=activate&pluginName={$name}>Activate</a>{/if}</td>
+	<td class="switch">{if $plugin.alwaysActivated}<span title="{'PluginsAdmin_ActivatedHelp'|translate}">{'PluginsAdmin_Activated'|translate}</span>{elseif $plugin.activated}<a href=?module=PluginsAdmin&action=deactivate&pluginName={$name}>{'PluginsAdmin_Deactivate'|translate}</a>
+{else}<a href=?module=PluginsAdmin&action=activate&pluginName={$name}>{'PluginsAdmin_Activate'|translate}</a>{/if}</td>
 	</tr>
 {/foreach}
 
Index: plugins/Widgetize/templates/iframe.tpl
===================================================================
--- plugins/Widgetize/templates/iframe.tpl	(wersja 441)
+++ plugins/Widgetize/templates/iframe.tpl	(kopia robocza)
@@ -1,6 +1,8 @@
 <html>
 <body>
 
+{loadJavascriptTranslations modules='Home'}
+
 <script type="text/javascript" src="libs/jquery/jquery.js"></script>
 <script type="text/javascript" src="themes/default/common.js"></script>
 <script type="text/javascript" src="libs/jquery/jquery.dimensions.js"></script>
@@ -16,4 +18,4 @@
 {$content}
 
 </body>
-</html>
\ brakuje znaku końca linii na końcu pliku 
+</html>
Index: plugins/Widgetize/templates/js.tpl
===================================================================
--- plugins/Widgetize/templates/js.tpl	(wersja 441)
+++ plugins/Widgetize/templates/js.tpl	(kopia robocza)
@@ -1,3 +1,5 @@
+{loadJavascriptTranslations modules='Home'}
+
 document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/jquery.js"><\/scr'+'ipt>');
 document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}themes/default/common.js"><\/scr'+'ipt>');
 document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/jquery.dimensions.js"><\/scr'+'ipt>');
@@ -11,4 +13,4 @@
 document.write('<link rel="stylesheet" href="{$piwikUrl}plugins/Home/templates/datatable.css">');
 
 var content = '{$content|escape:'javascript'}';
-document.write(content);
\ brakuje znaku końca linii na końcu pliku 
+document.write(content);
Index: plugins/UsersManager/API.php
===================================================================
--- plugins/UsersManager/API.php	(wersja 441)
+++ plugins/UsersManager/API.php	(kopia robocza)
@@ -185,16 +185,35 @@
 		return $user;
 	}
 	
+	/**
+	 * Returns the user information (login, password md5, alias, email, date_registered, etc.)
+	 * 
+	 * @param string the user email
+	 * 
+	 * @return array the user information
+	 */
+	static public function getUserByEmail( $userEmail )
+	{
+		Piwik::checkUserIsSuperUser();
+		self::checkUserExists($userLogin);
+		
+		$db = Zend_Registry::get('db');
+		$user = $db->fetchRow("SELECT * 
+								FROM ".Piwik::prefixTable("user")
+								." WHERE email = ?", $userEmail);
+		return $user;
+	}
+	
 	static private function checkLogin($userLogin)
 	{
 		if(self::userExists($userLogin))
 		{
-			throw new Exception("Login $userLogin already exists.");
+			throw new Exception(sprintf(Piwik_TranslateException('UsersManager_ExceptionLoginExists'),$userLogin));
 		}
 		
 		if(!self::isValidLoginString($userLogin))
 		{
-			throw new Exception("The login must contain only letters, numbers, or the characters '_' or '-' or '.'");
+			throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidLogin'));
 		}
 	}
 		
@@ -202,7 +221,7 @@
 	{
 		if(!self::isValidPasswordString($password))
 		{
-			throw new Exception("The password length must be between 6 and 26 characters.");
+			throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidPassword'));
 		}
 	}
 	
@@ -210,7 +229,7 @@
 	{
 		if(!Piwik::isValidEmailString($email))
 		{
-			throw new Exception("The email doesn't have a valid format.");
+			throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidEmail'));
 		}
 	}
 		
@@ -343,7 +362,7 @@
 		
 		if(!self::userExists($userLogin))
 		{
-			throw new Exception("User '$userLogin' doesn't exist therefore it can't be deleted.");
+			throw new Exception(sprintf(Piwik_TranslateException("UsersManager_ExceptionDeleteDoesNotExist"),$userLogin));
 		}
 		
 		
@@ -364,6 +383,21 @@
 													WHERE login = ?", $userLogin);
 		return $count != 0;
 	}
+	
+	/**
+	 * Returns true if user with given email (userEmail) is known in the database
+	 *
+	 * @return bool true if the user is known
+	 */
+	 
+	static public function userEmailExists( $userEmail )
+	{
+		Piwik::checkUserHasSomeAdminAccess();	
+		$count = Zend_Registry::get('db')->fetchOne("SELECT count(*) 
+													FROM ".Piwik::prefixTable("user"). " 
+													WHERE email = ?", $userEmail);
+		return $count != 0;	
+	}
 
 	/**
 	 * Set an access level to a given user for a list of websites ID.
@@ -389,7 +423,7 @@
 		if($userLogin == 'anonymous'
 			&& $access == 'admin')
 		{
-			throw new Exception("You cannot grant 'admin' access to the 'anonymous' user.");
+			throw new Exception(Piwik_TranslateException("UsersManager_ExceptionAdminAnonymous"));
 		}
 		
 		// in case idSites is null we grant access to all the websites on which the current connected user
@@ -441,7 +475,7 @@
 	{
 		if(!self::userExists($userLogin))
 		{
-			throw new Exception("User '$userLogin' doesn't exist.");
+			throw new Exception(sprintf(Piwik_TranslateException("UsersManager_ExceptionUserDoesNotExist"),$userLogin));
 		}
 	}
 	
@@ -449,7 +483,7 @@
 	{
 		if($userLogin == 'anonymous')
 		{
-			throw new Exception("The anonymous user cannot be edited or deleted. It is used by Piwik to define a user that has not loggued in yet. For example, you can make your statistics public by granting the 'view' access to the 'anonymous' user.");
+			throw new Exception(Piwik_TranslateException("UsersManager_ExceptionEditAnonymous"));
 		}
 	}
 	
@@ -462,7 +496,7 @@
 		
 		if(!in_array($access,$accessList))
 		{
-			throw new Exception("The parameter access must have one of the following values : [ ". implode(", ", $accessList)." ]");
+			throw new Exception(sprintf(Piwik_TranslateException("UsersManager_ExceptionAccessValues"),implode(", ", $accessList)));
 		}
 	}
 	
@@ -550,4 +584,4 @@
 		return $l >= 6 && $l <= 26;
 	}
 
-}
\ brakuje znaku końca linii na końcu pliku 
+}
Index: plugins/UsersManager/lang/en.php
===================================================================
--- plugins/UsersManager/lang/en.php	(wersja 0)
+++ plugins/UsersManager/lang/en.php	(wersja 0)
@@ -0,0 +1,32 @@
+<?php
+$translations = array(
+	'UsersManager_ManageAccess' => 'Manage access',
+	'UsersManager_Sites' => 'Sites',
+	'UsersManager_AllWebsites' => 'All websites',
+	'UsersManager_ApplyToAllWebsites' => 'Apply to all websites',
+	'UsersManager_User' => 'User',
+	'UsersManager_PrivNone' => 'No access',
+	'UsersManager_PrivView' => 'View',
+	'UsersManager_PrivAdmin' => 'Admin',
+	'UsersManager_ChangeAllConfirm' => 'Are you sure you want to change \'%s\' permissions on all the websites?',
+	'UsersManager_Login' => 'Login',
+	'UsersManager_Password' => 'Password',
+	'UsersManager_Email' => 'Email',
+	'UsersManager_Alias' => 'Alias',
+	'UsersManager_Token' => 'token_auth',
+	'UsersManager_Edit' => 'Edit',
+	'UsersManager_AddUser' => 'Add a new user',
+
+	'UsersManager_DeleteConfirm_js' => 'Are you sure you want to delete the user %s?',
+	
+	'UsersManager_ExceptionLoginExists' => "Login '%s' already exists.",
+	'UsersManager_ExceptionInvalidLogin' => "The login must contain only letters, numbers, or the characters '_' or '-' or '.'",
+	'UsersManager_ExceptionInvalidPassword' => "The password length must be between 6 and 26 characters.",
+	'UsersManager_ExceptionInvalidEmail' => "The email doesn't have a valid format.",
+	'UsersManager_ExceptionDeleteDoesNotExist' => "User '%s' doesn't exist therefore it can't be deleted.",
+	'UsersManager_ExceptionAdminAnonymous' => "You cannot grant 'admin' access to the 'anonymous' user.",
+	'UsersManager_ExceptionEditAnonymous' => "The anonymous user cannot be edited or deleted. It is used by Piwik to define a user that has not logged in yet. For example, you can make your statistics public by granting the 'view' access to the 'anonymous' user.",
+	'UsersManager_ExceptionUserDoesNotExist' => "User '%s' doesn't exist.",
+	'UsersManager_ExceptionAccessValues' => "The parameter access must have one of the following values : [ %s ]",
+
+);
Index: plugins/UsersManager/UsersManager.php
===================================================================
--- plugins/UsersManager/UsersManager.php	(wersja 441)
+++ plugins/UsersManager/UsersManager.php	(kopia robocza)
@@ -19,12 +19,12 @@
 	{
 		$info = array(
 			// name must be the className prefix!
-			'name' => 'UserManager',
+			'name' => 'UsersManager',
 			'description' => 'Description',
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
-			'translationAvailable' => false,
+			'translationAvailable' => true,
 		);
 		
 		return $info;
Index: plugins/UsersManager/templates/UsersManager.js
===================================================================
--- plugins/UsersManager/templates/UsersManager.js	(wersja 441)
+++ plugins/UsersManager/templates/UsersManager.js	(kopia robocza)
@@ -222,7 +222,7 @@
 			ajaxHideError();
 			var idRow = $(this).attr('id');
 			var loginToDelete = $(this).parent().parent().find('#userLogin').html();
-			if(confirm('Are you sure you want to delete the user "'+loginToDelete+'"?'))
+			if(confirm(_pk_translate('UsersManager_DeleteConfirm','Are you sure you want to delete the user %s','"'+loginToDelete+'"')))
 			{
 				$.ajax( getDeleteUserAJAX( loginToDelete ) );
 			}
Index: plugins/UsersManager/templates/UsersManager.tpl
===================================================================
--- plugins/UsersManager/templates/UsersManager.tpl	(wersja 441)
+++ plugins/UsersManager/templates/UsersManager.tpl	(kopia robocza)
@@ -1,3 +1,4 @@
+{loadJavascriptTranslations modules='UsersManager'}
 <script type="text/javascript" src="libs/jquery/jquery.js"></script>
 <script type="text/javascript" src="themes/default/common.js"></script>
 <link rel="stylesheet" href="themes/default/common-admin.css">
@@ -18,16 +19,16 @@
 </style>
 {/literal}
 
-<h2>Manage access</h2>
+<h2>{'UsersManager_ManageAccess'|translate}</h2>
 
 <div id="sites">
 <form method="post" action="{url actionToLoad=index}" id="accessSites">
-	<p>Sites: <select id="selectIdsite" name="idsite" onchange="this.form.submit()">
+	<p>{'UsersManager_Sites'|translate}: <select id="selectIdsite" name="idsite" onchange="this.form.submit()">
 	
-	<optgroup label="All websites">
-		<option label="All websites" value="-1" {if $idSiteSelected==-1} selected="selected"{/if}>Apply to all websites</option>
+	<optgroup label="{'UsersManager_AllWebsites'|translate}">
+		<option label="{'UsersManager_AllWebsites'|translate}" value="-1" {if $idSiteSelected==-1} selected="selected"{/if}>{'UsersManager_ApplyToAllWebsites'|translate}</option>
 	</optgroup>
-	<optgroup label="Sites">
+	<optgroup label="{'UsersManager_Sites'|translate}">
 		{foreach from=$websites item=info}
 			<option value="{$info.idsite}" {if $idSiteSelected==$info.idsite} selected="selected"{/if}>{$info.name}</option>
 		{/foreach}
@@ -40,10 +41,10 @@
 <table id="access">
 <thead>
 <tr>
-	<th>User</th>
-	<th>No access</th>
-	<th>View</th>
-	<th>Admin</th>
+	<th>{'UsersManager_User'|translate}</th>
+	<th>{'UsersManager_PrivNone'|translate}</th>
+	<th>{'UsersManager_PrivView'|translate}</th>
+	<th>{'UsersManager_PrivAdmin'|translate}</th>
 </tr>
 </thead>
 
@@ -61,28 +62,28 @@
 </tbody>
 </table>
 
-<div id="accessUpdated">Done!</div>
+<div id="accessUpdated">{'General_Done'|translate}!</div>
 
 <div class="dialog" id="confirm"> 
-	<p>Are you sure you want to change '<span id='login'></span>' permissions on all the websites?</p>
-	<input id="yes" type="button" value="Yes"/>
-	<input id="no" type="button" value="No"/>
+	<p>{'UsersManager_ChangeAllConfirm'|translate:"<span id='login'></span>"}</p>
+	<input id="yes" type="button" value="{'General_Yes'|translate}"/>
+	<input id="no" type="button" value="{'General_No'|translate}"/>
 </div> 
 
 <h2>Manage users</h2>
 
 <div id="ajaxError" style="display:none"></div>
-<div id="ajaxLoading" style="display:none">Loading... <img src="themes/default/loading.gif"></div>
+<div id="ajaxLoading" style="display:none">{'General_LoadingData'|translate} <img src="themes/default/loading.gif"></div>
 <table id="users">
 	<thead>
 		<tr>
-			<th>Login</th>
-			<th>Password</th>
-			<th>Email</th>
-			<th>Alias</th>
-			<th>token_auth</th>
-			<th>Edit</th>
-			<th>Delete</th>
+			<th>{'UsersManager_Login'|translate}</th>
+			<th>{'UsersManager_Password'|translate}</th>
+			<th>{'UsersManager_Email'|translate}</th>
+			<th>{'UsersManager_Alias'|translate}</th>
+			<th>{'UsersManager_Token'|translate}</th>
+			<th>{'General_Edit'|translate}</th>
+			<th>{'General_Delete'|translate}</th>
 		</tr>
 	</thead>
 	
@@ -103,5 +104,5 @@
 	</tbody>
 </table>
 
-<div id="addrow"><img src='plugins/UsersManager/images/add.png'> Add a new user</div>
+<div id="addrow"><img src='plugins/UsersManager/images/add.png'> {'UsersManager_AddUser'|translate}</div>
 <script type="text/javascript" src="plugins/UsersManager/templates/UsersManager.js"></script>
Index: plugins/UserSettings/lang/en.php
===================================================================
--- plugins/UserSettings/lang/en.php	(wersja 0)
+++ plugins/UserSettings/lang/en.php	(wersja 0)
@@ -0,0 +1,10 @@
+<?php
+$translations = array(
+	'UserSettings_BrowserFamilies' => 'Browser families',
+	'UserSettings_Browsers' => 'Browsers',
+	'UserSettings_Plugins' => 'Plugins',
+	'UserSettings_Configurations' => 'Configurations',
+	'UserSettings_OperatinsSystems' => 'Operating systems',
+	'UserSettings_Resolutions' => 'Resolutions',
+	'UserSettings_WideScreen' => 'Wide Screen',
+);
Index: plugins/UserSettings/UserSettings.php
===================================================================
--- plugins/UserSettings/UserSettings.php	(wersja 441)
+++ plugins/UserSettings/UserSettings.php	(kopia robocza)
@@ -38,6 +38,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
+			'translationAvailable' => true,
 		);
 		
 		return $info;
Index: plugins/UserSettings/index.tpl
===================================================================
--- plugins/UserSettings/index.tpl	(wersja 441)
+++ plugins/UserSettings/index.tpl	(kopia robocza)
@@ -1,25 +1,25 @@
 <div id='leftcolumn'>
-	<h2>Browser families</h2>
+	<h2>{'UserSettings_BrowserFamilies'|translate}</h2>
 	{$dataTableBrowserType}
 	
-	<h2>Browsers</h2>
+	<h2>{'UserSettings_Browsers'|translate}</h2>
 	{$dataTableBrowser}
 	
-	<h2>Plugins</h2>
+	<h2>{'UserSettings_Plugins'|translate}</h2>
 	{$dataTablePlugin}
 </div>
 
 <div id='rightcolumn'>
-	<h2>Configurations</h2>
+	<h2>{'UserSettings_Configurations'|translate}</h2>
 	{$dataTableConfiguration}
 	
-	<h2>Operating systems</h2>
+	<h2>{'UserSettings_OperatinsSystems'|translate}</h2>
 	{$dataTableOS}
 	
-	<h2>Resolutions</h2>
+	<h2>{'UserSettings_Resolutions'|translate}</h2>
 	{$dataTableResolution}
 	
-	<h2>Wide Screen</h2>
+	<h2>{'UserSettings_WideScreen'|translate}</h2>
 	{$dataTableWideScreen}
 </div>	
 
Index: plugins/VisitsSummary/lang/en.php
===================================================================
--- plugins/VisitsSummary/lang/en.php	(wersja 0)
+++ plugins/VisitsSummary/lang/en.php	(wersja 0)
@@ -0,0 +1,14 @@
+<?php
+$translations = array(
+	'VisitsSummary_NbVisits' => '%s visits',
+	'VisitsSummary_NbUniqueVisitors' => '%s unique visitors',
+	'VisitsSummary_NbActions' => '%s actions (page views)',
+	'VisitsSummary_TotalTime' => '%s total time spent by the visitors',
+	'VisitsSummary_MaxNbActions' => '%s max actions in one visit',
+	'VisitsSummary_NbBounced' => '%s visitors have bounced (left the site after one page)',
+	'VisitsSummary_Evolution' => 'Evolution on the last 30 %ss',
+	'VisitsSummary_Report' => 'Report',
+	'VisitsSummary_GenerateTime' => '%s seconds to generate the page',
+	'VisitsSummary_GenerateQueries' => '%s queries executed',
+
+);
Index: plugins/VisitsSummary/VisitsSummary.php
===================================================================
--- plugins/VisitsSummary/VisitsSummary.php	(wersja 441)
+++ plugins/VisitsSummary/VisitsSummary.php	(kopia robocza)
@@ -19,12 +19,12 @@
 	{
 		$info = array(
 			// name must be the className prefix!
-			'name' => 'Piwik_VisitsSummary',
+			'name' => 'VisitsSummary',
 			'description' => 'Description',
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
-			'translationAvailable' => false,
+			'translationAvailable' => true,
 		);
 		
 		return $info;
@@ -129,4 +129,4 @@
 Piwik_AddWidget( 'VisitsSummary', 'getLastUniqueVisitorsGraph', 'Last unique visitors graph');
 Piwik_AddWidget( 'VisitsSummary', 'index', 'Overview with graph');
 
-Piwik_AddMenu('Visitors', 'Overview', array('module' => 'VisitsSummary'), true);
\ brakuje znaku końca linii na końcu pliku 
+Piwik_AddMenu('Visitors', 'Overview', array('module' => 'VisitsSummary'), true);
Index: plugins/VisitsSummary/index.tpl
===================================================================
--- plugins/VisitsSummary/index.tpl	(wersja 441)
+++ plugins/VisitsSummary/index.tpl	(kopia robocza)
@@ -1,12 +1,15 @@
 <script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script>
 
 <a name="evolutionGraph" graphId="VisitsSummarygetLastVisitsGraph"></a>
-<h2>Evolution on the last 30 {$period}s</h2>
+<h2>{'VisitsSummary_Evolution'|translate:$period}</h2>
 {$graphEvolutionVisitsSummary}
 
-<h2>Report</h2>
+<h2>{'VisitsSummary_Report'|translate}</h2>
 {include file=VisitsSummary/sparklines.tpl}
 
 
 <br><br><br>
-<p style='color:lightgrey; size:0.8em;'>{$totalTimeGeneration} seconds {if $totalNumberOfQueries != 0}/ {$totalNumberOfQueries}  queries{/if} to generate the page</p>
+<p style='color:lightgrey; size:0.8em;'>
+{'VisitsSummary_GenerateTime'|translate:$totalTimeGeneration:$totalNumberOfQueries}
+{if $totalNumberOfQueries != 0}, {'VisitsSummary_GenerateQueries'|translate:$totalNumberOfQueries}{/if}
+</p>
Index: plugins/VisitsSummary/sparklines.tpl
===================================================================
--- plugins/VisitsSummary/sparklines.tpl	(wersja 441)
+++ plugins/VisitsSummary/sparklines.tpl	(kopia robocza)
@@ -1,9 +1,15 @@
 <div id="to remove this div" class="parentDiv">
-<p><img class="sparkline" src="{$urlSparklineNbVisits}" /> <span><strong>{$nbVisits} </strong>visits</span></p>
-<p><img class="sparkline" src="{$urlSparklineNbUniqVisitors}" /> <span><strong>{$nbUniqVisitors}</strong> unique visitors</span></p>
-<p><img class="sparkline" src="{$urlSparklineNbActions}" /> <span><strong>{$nbActions}</strong> actions (page views)</span></p>
-<p><img class="sparkline" src="{$urlSparklineSumVisitLength}" /> <span><strong>{$sumVisitLength|sumtime}</strong> total time spent by the visitors</span></p>
-<p><img class="sparkline" src="{$urlSparklineMaxActions}" /> <span><strong>{$maxActions}</strong> max actions in one visit</span></p>
-<p><img class="sparkline" src="{$urlSparklineBounceCount}" /> <span><strong>{$bounceCount} </strong>visitors have bounced (left the site after one page)</span></p>
-
-</div>
\ brakuje znaku końca linii na końcu pliku 
+<p><img class="sparkline" src="{$urlSparklineNbVisits}" /> <span>
+	{'VisitsSummary_NbVisits'|translate:"<strong>$nbVisits</strong>"}</span></p>
+<p><img class="sparkline" src="{$urlSparklineNbUniqVisitors}" /> <span>
+	{'VisitsSummary_NbUniqueVisitors'|translate:"<strong>$nbUniqVisitors</strong>"}</span></p>
+<p><img class="sparkline" src="{$urlSparklineNbActions}" /> <span>
+	{'VisitsSummary_NbActions'|translate:"<strong>$nbActions</strong>"}</span></p>
+<p><img class="sparkline" src="{$urlSparklineSumVisitLength}" /> <span>
+	{assign var=sumtimeVisitLength value=$sumVisitLength|sumtime}
+	{'VisitsSummary_TotalTime'|translate:"<strong>$sumtimeVisitLength</strong>"}</span></p>
+<p><img class="sparkline" src="{$urlSparklineMaxActions}" /> <span>
+	{'VisitsSummary_MaxNbActions'|translate:"<strong>$maxActions</strong>"}</span></p>
+<p><img class="sparkline" src="{$urlSparklineBounceCount}" /> <span>
+	{'VisitsSummary_NbBounced'|translate:"<strong>$bounceCount</strong>"}</span></p>
+</div>
Index: plugins/Actions/API.php
===================================================================
--- plugins/Actions/API.php	(wersja 441)
+++ plugins/Actions/API.php	(kopia robocza)
@@ -66,7 +66,7 @@
 	public function getDownloads( $idSite, $period, $date, $expanded = false, $idSubtable = false )
 	{
 		$dataTable = $this->getDataTable('Actions_downloads', $idSite, $period, $date, $expanded, $idSubtable );
-		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'url', create_function('$url', 'return $url;')));
+		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('full_url', 'url', create_function('$url', 'return $url;')));
 		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getPathFromActionsUrl'));
 		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_truncateActionsPath'));
 		
@@ -76,7 +76,7 @@
 	public function getOutlinks( $idSite, $period, $date, $expanded = false, $idSubtable = false )
 	{
 		$dataTable = $this->getDataTable('Actions_outlink', $idSite, $period, $date, $expanded, $idSubtable );
-		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'url', create_function('$url', 'return $url;')));
+		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('full_url', 'url', create_function('$url', 'return $url;')));
 		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getPathFromActionsUrl'));
 		$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_truncateActionsPath'));
 		return $dataTable;
Index: plugins/Actions/Actions.php
===================================================================
--- plugins/Actions/Actions.php	(wersja 441)
+++ plugins/Actions/Actions.php	(kopia robocza)
@@ -37,6 +37,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
+			'translationAvailable' => false
 		);
 		
 		return $info;
@@ -282,6 +283,7 @@
 				$currentTable = new Piwik_DataTable_Row(
 					array(	Piwik_DataTable_Row::COLUMNS => 
 							array(	'label' => (string)$actionName,
+									'full_url' => (string)$row['name'],
 								)
 						)
 					);
Index: plugins/Installation/lang/en.php
===================================================================
--- plugins/Installation/lang/en.php	(wersja 0)
+++ plugins/Installation/lang/en.php	(wersja 0)
@@ -0,0 +1,74 @@
+<?php
+$translations = array(
+	'Installation_Installation' => 'Installation',
+	'Installation_InstallationStatus' => 'Installation status',
+	'Installation_PercentDone' => '%s %% Done',
+		
+	'Installation_NoConfigFound' => 
+		"The Piwik configuration file couldn't be found and you are trying to access a Piwik page.<br>".
+		"<b>&nbsp;&nbsp;&raquo; You can <a href='index.php'>install Piwik now</a></b>".
+		"<br><small>If you installed Piwik before and have some tables in your DB, don't worry,".
+		"you can reuse the same tables and keep your existing data!</small>",
+
+	'Installation_MysqlSetup' => 'Mysql database setup',
+	'Installation_MysqlErrorConnect' => 'Error while trying to connect to the Mysql database',
+
+	'Installation_JsTag' => 'Javascript tag',	
+	'Installation_JsTagHelp' => 
+		'<p>To count all visitors, you must insert the javascript code on all of your pages.</p>'.
+		'<p>Your pages do not have to be made with PHP, Piwik will work on all kinds of pages (whether it is HTML, ASP, Perl or any other languages).</p>'.
+		'<p>Here is the code you have to insert: (copy and paste on all your pages) </p>',
+
+	'Installation_Congratulations' => 'Congratulations',
+	'Installation_ContratulationsHelp' => 
+		'<p>Congratulations! Your Piwik installation is complete.</p>'.
+		'<p>Make sure your javascript code is entered on your pages, and wait for your first visitors!</p>',
+	'Installation_GoToPiwik' => 'Go to Piwik',
+
+	'Installation_SetupWebsite' => 'Setup a website',
+	'Installation_SetupWebsiteError' => 'There was an error when adding the website',
+
+	'Installation_GeneralSetup' => 'General Setup',
+	'Installation_GeneralSetupSuccess' => 'General Setup configured with success',
+
+	'Installation_SystemCheck' => 'System check',
+	'Installation_SystemCheckPhp' => 'PHP version',
+	'Installation_SystemCheckPdo' => 'Pdo extension',				
+	'Installation_SystemCheckPdoMysql' => 'Pdo_Mysql extension',
+	'Installation_SystemCheckPdoError' => 'You need to enable the <code>php_pdo</code> and <code>php_pdo_mysql</code> extensions in your php.ini file.',			
+	'Installation_SystemCheckPdoErrorHelp' => 
+		"On a windows server you can add the lines 	<code>extension=php_pdo.dll\nextension=php_pdo_mysql.dll</code> in your php.ini".
+		'<br><br>On a Linux server you can compile php with the following option <code>--with-pdo-mysql </code>'.
+		'<br><br>More information on the <a style="color:red" href="http://php.net/pdo">PHP website</a>.',
+	'Installation_SystemCheckPhpXml' => 'PHP-XML extension',
+	'Installation_SystemCheckWriteDirs' => 'Directories with write access',
+	'Installation_SystemCheckWriteDirsHelp' => 'To fix this error on your Linux system, try typing in the following command(s)',
+	'Installation_SystemCheckMemoryLimit' => 'Memory limit',	
+	'Installation_SystemCheckMemoryLimitHelp' => 
+		'On a high traffic website, the archiving process may require more memory than currently allowed.'.
+		'<br>See the directive memory_limit in your php.ini file if necessary.',
+	'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphics)',
+	'Installation_SystemCheckGDHelp' => 'The sparklines (small graphs) will not work.',
+	'Installation_SystemCheckTimeLimit' => 'set_time_limit() allowed',
+	'Installation_SystemCheckTimeLimitHelp' => 
+		'On a high traffic website, executing the archiving process may require more time than currently allowed.'.
+		'<br>See the directive max_execution_time  in your php.ini file if necessary',
+	'Installation_SystemCheckMail' => 'mail() allowed',
+	'Installation_SystemCheckError' => 'An error occured - must be fixed before you proceed',
+	'Installation_SystemCheckWarning' => 'Piwik will work normally but some features may be missing',
+	
+	'Installation_Tables' => 'Creating the tables',
+	'Installation_TablesWarning' => 'Some <span id="linkToggle">Piwik tables</span> are already installed in the DB',
+	'Installation_TablesFound' => 'The following tables have been found in the database',
+	'Installation_TablesWarningHelp' => 'Either choose to reuse the existing database tables or select a clean install to erase all existing data in the database.',
+	'Installation_TablesReuse' => 'Reuse the existing tables',
+	'Installation_TablesDelete' => 'Delete the detected tables',
+	'Installation_TablesDeletedSuccess' => 'Existing Piwik tables deleted with success',
+	'Installation_TablesCreatedSuccess' => 'Tables created with success!',
+	'Installation_TablesDeleteConfirm' => 'Are you sure you want to delete all the Piwik tables from this database?',
+
+	'Installation_Welcome' => 'Welcome!',
+	'Installation_WelcomeHelp' => 
+		'<p>Piwik is an open source web analytics software that makes it easy to get the information you want from your visitors.</p>'.
+		'<p>This process is split up into %s easy steps and will take around 5 minutes.</p>',	
+);
Index: plugins/Installation/Installation.php
===================================================================
--- plugins/Installation/Installation.php	(wersja 441)
+++ plugins/Installation/Installation.php	(kopia robocza)
@@ -29,7 +29,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
-			'translationAvailable' => false,
+			'translationAvailable' => true,
 		);
 		
 		return $info;
@@ -67,12 +67,8 @@
 		}
 		else
 		{
-			Piwik::exitWithErrorMessage("
-				The Piwik configuration file couldn't be found and you are trying to access a Piwik page.<br>
-				<b>&nbsp;&nbsp;&raquo; You can <a href='index.php'>install Piwik now</a></b>
-				<br><small>If you installed Piwik before and have some tables in your DB, don't worry, 
-				you can reuse the same tables and keep your existing data!</small>");
+			Piwik::exitWithErrorMessage(Piwik_Translate('Installation_NoConfigFound'));
 		}
 		exit;
 	}	
-}
\ brakuje znaku końca linii na końcu pliku 
+}
Index: plugins/Installation/templates/systemCheck.tpl
===================================================================
--- plugins/Installation/templates/systemCheck.tpl	(wersja 441)
+++ plugins/Installation/templates/systemCheck.tpl	(kopia robocza)
@@ -2,37 +2,30 @@
 {assign var=error value="<img src='themes/default/images/error.png' />"}
 {assign var=warning value="<img src='themes/default/images/warning.png' />"}
 
-<h1>System check</h1>
+<h1>{'Installation_SystemCheck'|translate}</h1>
 
 
 <table class="infosServer">
 	<tr>
-		<td class="label">PHP version &gt; {$infos.phpVersion_minimum}</td>
+		<td class="label">{'Installation_SystemCheckPhp'|translate} &gt; {$infos.phpVersion_minimum}</td>
 		<td>{if $infos.phpVersion_ok}{$ok}{else}{$error}{/if}</td>
 	</tr><tr>
-		<td class="label">Pdo extension</td>
+		<td class="label">{'Installation_SystemCheckPdo'|translate}</td>
 		<td>{if $infos.pdo_ok}{$ok}
 		{else}{$error}{/if}	
 		</td>
 	</tr>  
 	<tr>
-		<td class="label">Pdo_Mysql extension</td>
+		<td class="label">{'Installation_SystemCheckPdoMysql'|translate}</td>
 		<td>{if $infos.pdo_mysql_ok}{$ok}
 		{else}{$error}
 		{/if}
 		
 		{if !$infos.pdo_mysql_ok || !$infos.pdo_ok}
-			<p class="error" style="width:80%">You need to enable the <code>php_pdo</code> and <code>php_pdo_mysql</code> extensions in your 
-			php.ini file.
+			<p class="error" style="width:80%">{'Installation_SystemCheckPdoError'|translate}
 			<small>
-			<br><br>On a windows server you can add the lines 
-			<code>extension=php_pdo.dll
-				extension=php_pdo_mysql.dll</code> in your php.ini 
-			
-			<br><br>On a Linux server you can compile php with the following option
-			<code>--with-pdo-mysql </code> 
-			
-			<br><br>More information on the <a style="color:red" href='http://php.net/pdo'>PHP website</a>.
+			<br><br>
+			{'Installation_SystemCheckPdoErrorHelp'|translate}
 			</small>
 			</p>
 		{/if}
@@ -42,13 +35,13 @@
 	
 	{* We don't use utf8_encode currently but I think we will soon so I leave the code here
 	<tr>
-		<td class="label">PHP-XML extension <br> (utf8_decode function)</td>
+		<td class="label">{'Installation_SystemCheckPhpXml'|translate} <br> (utf8_decode function)</td>
 	    <td>{if $infos.phpXml_ok}{$ok}{else}{$error}{/if}</td>
 	</tr>
 	*}
 	<tr>
 		<td valign="top">
-			Directories with write access
+			{'Installation_SystemCheckWriteDirs'|translate}
 		</td>
 		<td>
 			{foreach from=$infos.directories key=dir item=bool}
@@ -64,7 +57,7 @@
 {if $problemWithSomeDirectories}
 	<br>
 	<div class="error">
-		To fix this error on your Linux system, try typing in the following command(s):
+			{'Installation_SystemCheckWriteDirsHelp'|translate}:
 	{foreach from=$infos.directories key=dir item=bool}
 		<ul>{if !$bool}
 			<li>chmod a+w {$basePath}{$dir}</li>
@@ -77,42 +70,40 @@
 <h1>Optional</h1>
 <table class="infos">
 	<tr>
-		<td class="label">Memory limit</td>
+		<td class="label">{'Installation_SystemCheckMemoryLimit'|translate}</td>
 		<td>
 			{$infos.memoryCurrent}
 			{if $infos.memory_ok}{$ok}{else}{$warning} 
-				<br><i>On a high traffic website, the archiving process may require more memory than currently allowed.
-				<br>See the directive memory_limit in your php.ini file if necessary.</i>{/if}	
+				<br><i>{'Installation_SystemCheckMemoryLimitHelp'|translate}</i>{/if}	
 		</td>
 	</tr>
 	<tr>
-		<td class="label">GD &gt; 2.x (graphics)</td>
+		<td class="label">{'Installation_SystemCheckGD'|translate}</td>
 		<td>
-			{if $infos.gd_ok}{$ok}{else}{$warning} <br><i>The sparklines (small graphs) will not work.</i>{/if}
+			{if $infos.gd_ok}{$ok}{else}{$warning} <br><i>{'Installation_SystemCheckGDHelp'|translate}</i>{/if}
 		</td>
 	</tr>
 	<tr>
-		<td class="label">set_time_limit() allowed</td>
+		<td class="label">{'Installation_SystemCheckTimeLimit'|translate}</td>
 		<td>{if $infos.setTimeLimit_ok}{$ok}{else}{$warning}
-			<br><i>On a high traffic website, executing the archiving process may require more time than currently allowed.
-				<br>See the directive max_execution_time  in your php.ini file if necessary.</i>{/if}</td>
+			<br><i>{'Installation_SystemCheckTimeLimitHelp'|translate}</i>{/if}</td>
 	</tr>
 	<tr>
-		<td class="label">mail() allowed</td>
+		<td class="label">{'Installation_SystemCheckMail'|translate}</td>
 		<td>{if $infos.mail_ok}{$ok}{else}{$warning}{/if}</td>
 	</tr>
 </table>
 <p><small>
 Legend:
 <br>
-{$ok} Ok<br>
-{$error} Error to be fixed<br>
-{$warning} Warning: Piwik will work normally but some features may be missing<br>
+{$ok} {'General_Ok'|translate}<br>
+{$error} {'General_Error'|translate}: {'Installation_SystemCheckError'|translate} <br>
+{$warning} {'General_Warning'|translate}: {'Installation_SystemCheckWarning'|translate} <br>
 </small></p>
 
 {if !$showNextStep}
 <p class="nextStep">
-	<a href="{url}">Refresh the page &raquo;</a>
+	<a href="{url}">{'General_Refresh'|translate} &raquo;</a>
 </p>
 
 {/if}
Index: plugins/Installation/templates/databaseSetup.tpl
===================================================================
--- plugins/Installation/templates/databaseSetup.tpl	(wersja 441)
+++ plugins/Installation/templates/databaseSetup.tpl	(kopia robocza)
@@ -1,9 +1,9 @@
-<h1>Mysql database setup</h1>
+<h1>{'Installation_MysqlSetup'|translate}</h1>
 
 {if isset($errorMessage)}
 	<div class="error">
 		<img src="themes/default/images/error_medium.png">
-		Error while trying to connect to the Mysql database:
+		{'Installation_MysqlErrorConnect'|translate}:
 		<br>{$errorMessage}
 		
 	</div>
@@ -11,4 +11,4 @@
 
 {if isset($form_data)}
 	{include file=default/genericForm.tpl}
-{/if}
\ brakuje znaku końca linii na końcu pliku 
+{/if}
Index: plugins/Installation/templates/displayJavascriptCode.tpl
===================================================================
--- plugins/Installation/templates/displayJavascriptCode.tpl	(wersja 441)
+++ plugins/Installation/templates/displayJavascriptCode.tpl	(kopia robocza)
@@ -31,10 +31,8 @@
 	<img src="themes/default/images/success_medium.png">
 </span>
 {/if}
-<h1>Javascript tag</h1>
-<p>To count all visitors, you must insert the javascript code on all of your pages.</p>
-<p>Your pages do not have to be made with PHP, Piwik will work on all kinds of pages (whether it is HTML, ASP, Perl or any other languages).</p>
-<p>Here is the code you have to insert: (copy and paste on all your pages) </P>
+<h1>{'Installation_JsTag'|translate}</h1>
+{'Installation_JsTagHelp'|translate}
 <code>
 {$javascriptTag}
 </code>
Index: plugins/Installation/templates/finished.tpl
===================================================================
--- plugins/Installation/templates/finished.tpl	(wersja 441)
+++ plugins/Installation/templates/finished.tpl	(kopia robocza)
@@ -1,11 +1,8 @@
-<h1>Congratulations</h1>
+<h1>{'Installation_Congratulations'|translate}</h1>
 
-<p>Congratulations! Your Piwik installation is complete.</p>
+{'Installation_ContratulationsHelp'|translate}
 
-<p>Make sure your javascript code is entered on your pages, 
-and wait for your first visitors!</p>
 
-
 <p class="nextStep">
-	<a href="{url module='' action=''}">Go to Piwik &raquo;</a>
+	<a href="{url module='' action=''}">{'Installation_GoToPiwik'|translate} &raquo;</a>
 </p>
Index: plugins/Installation/templates/firstWebsiteSetup.tpl
===================================================================
--- plugins/Installation/templates/firstWebsiteSetup.tpl	(wersja 441)
+++ plugins/Installation/templates/firstWebsiteSetup.tpl	(kopia robocza)
@@ -2,19 +2,19 @@
 
 {if isset($displayGeneralSetupSuccess)}
 <span id="toFade" class="success">
-	General Setup configured with success
+	{'Installation_GeneralSetupSuccess'|translate}
 	<img src="themes/default/images/success_medium.png">
 </span>
 {/if}
 
-<h1>Setup a website</h1>
+<h1>{'Installation_SetupWebsite'|translate}</h1>
 
 
 
 {if isset($errorMessage)}
 	<div class="error">
 		<img src="themes/default/images/error_medium.png">
-		There was an error when adding the website:
+		{'Installation_SetupWebsiteError'|translate}:
 		<br>- {$errorMessage}
 		
 	</div>
@@ -23,4 +23,4 @@
 
 {if isset($form_data)}
 	{include file=default/genericForm.tpl}
-{/if}
\ brakuje znaku końca linii na końcu pliku 
+{/if}
Index: plugins/Installation/templates/welcome.tpl
===================================================================
--- plugins/Installation/templates/welcome.tpl	(wersja 441)
+++ plugins/Installation/templates/welcome.tpl	(kopia robocza)
@@ -1,4 +1,3 @@
-<h1>Welcome!</h1>
-<p>Piwik is an open source web analytics software that makes it easy to get the information you want from your visitors.</p>
+<h1>{'Installation_Welcome'|translate}</h1>
 
-<p>This process is split up into {$totalNumberOfSteps} easy steps and will take around 5 minutes.</p>
\ brakuje znaku końca linii na końcu pliku 
+{'Installation_WelcomeHelp'|translate:$totalNumberOfSteps}
Index: plugins/Installation/templates/generalSetup.tpl
===================================================================
--- plugins/Installation/templates/generalSetup.tpl	(wersja 441)
+++ plugins/Installation/templates/generalSetup.tpl	(kopia robocza)
@@ -1,5 +1,5 @@
-<h1>General Setup</h1>
+<h1>{'Installation_GeneralSetup'|translate}</h1>
 
 {if isset($form_data)}
 	{include file=default/genericForm.tpl}
-{/if}
\ brakuje znaku końca linii na końcu pliku 
+{/if}
Index: plugins/Installation/templates/tablesCreation.tpl
===================================================================
--- plugins/Installation/templates/tablesCreation.tpl	(wersja 441)
+++ plugins/Installation/templates/tablesCreation.tpl	(kopia robocza)
@@ -1,27 +1,26 @@
-<h1>Creating the tables</h1>
+<h1>{'Installation_Tables'|translate}</h1>
 {if isset($someTablesInstalled)}
-	<div class="warning">Some <span id="linkToggle">Piwik tables</span> are already installed in the DB
+	<div class="warning">{'Installation_TablesWarning'|translate}
 	<img src="themes/default/images/warning_medium.png">
 	</div>
-	<div id="toggle" style="display:none;color:#4F2410"><small><i>The following tables have been found in the database: 
+	<div id="toggle" style="display:none;color:#4F2410"><small><i>{'Installation_TablesFound'|translate}:
 		<br>{$tablesInstalled} </i></small></div>
 
-	<p>Either choose to reuse the existing database tables or select a clean install 
-	to erase all existing data in the database.</p>
+	<p>{'Installation_TablesWarningHelp'|translate}</p>
 	
-	<p class="nextStep"><a href="{url action=$nextModuleName}">Reuse the existing tables &raquo;</a></p>
-	<p class="nextStep" id="eraseAllTables"><a href="{url deleteTables=1}">Delete the detected tables &raquo;</a></p>
+	<p class="nextStep"><a href="{url action=$nextModuleName}">{'Installation_TablesReuse'|translate} &raquo;</a></p>
+	<p class="nextStep" id="eraseAllTables"><a href="{url deleteTables=1}">{'Installation_TablesDelete'|translate} &raquo;</a></p>
 				
 {/if}
 
 {if isset($existingTablesDeleted)}
-	<div class="success"> Existing Piwik tables deleted with success
+	<div class="success"> {'Installation_TablesDeletedSuccess'|translate} 
 	<img src="themes/default/images/success_medium.png"></div>
 {/if}
 
 
 {if isset($tablesCreated)}
-	<div class="success"> Tables created with success! 
+	<div class="success"> {'Installation_TablesCreatedSuccess'|translate} 
 	<img src="themes/default/images/success_medium.png"></div>
 {/if}
 
@@ -32,7 +31,9 @@
 {literal}
 <script>
 $(document).ready( function(){
-	var strConfirmEraseTables = "Are you sure you want to delete all the Piwik tables from this database?";
+	{/literal}
+	var strConfirmEraseTables = "{'Installation_TablesDeleteConfirm'|translate} ";
+	{literal}	
 	
 	// toggle the display of the tables detected during the installation when clicking
 	// on the span "linkToggle"
@@ -64,4 +65,4 @@
 	;
 });
 </script>
-{/literal}
\ brakuje znaku końca linii na końcu pliku 
+{/literal}
Index: plugins/Installation/templates/structure.tpl
===================================================================
--- plugins/Installation/templates/structure.tpl	(wersja 441)
+++ plugins/Installation/templates/structure.tpl	(kopia robocza)
@@ -1,7 +1,7 @@
 
 <html>
 <head>
-<title>Piwik &raquo; Installation</title>
+<title>Piwik &raquo; {'Installation_Installation'|translate}</title>
 </head>
 <body>
 
@@ -194,18 +194,18 @@
 			{include file="$subTemplateToLoad"}
 			{if $showNextStep}
 				<p class="nextStep">
-					<a href="{url action=$nextModuleName}">Next &raquo;</a>
+					<a href="{url action=$nextModuleName}">{'General_Next'|translate} &raquo;</a>
 				</p>
 			{/if}
 		</div>
 		
 		<div class="both"></div>
 		
-		<h3>Installation status</h3>
+		<h3>{'Installation_InstallationStatus'|translate}</h3>
 		
 		<div id="installPercent">
 		<p style="width: {$percentDone}%;"></p>
 	</div>
 	
-	{$percentDone}% Done
+	{'Installation_PercentDone'|translate:$percentDone} 
 </div>
Index: plugins/AdminHome/templates/index.tpl
===================================================================
--- plugins/AdminHome/templates/index.tpl	(wersja 441)
+++ plugins/AdminHome/templates/index.tpl	(kopia robocza)
@@ -42,6 +42,6 @@
 </div>
 
 <div id="footer" style="border-top:1px solid gray; margin-top:20px;padding-top:10px;">
-<a href='?module=Home'>Back to Piwik homepage</a>
+<a href='?module=Home'>{'General_BackToHomepage'|translate}</a>
 
 </div>
Index: plugins/UserCountry/lang/en.php
===================================================================
--- plugins/UserCountry/lang/en.php	(wersja 441)
+++ plugins/UserCountry/lang/en.php	(kopia robocza)
@@ -1,6 +1,10 @@
 <?php
 $translations = array (
 
+	'UserCountry_Country' => 'Country',
+	'UserCountry_Continent' => 'Continent',
+	'UserCountry_DistinctCountries' => '%s distinct countries',
+	
 	// Countries
 	'country_ac' => 'Ascension Islands',
 	'country_ad' => 'Andorra',
Index: plugins/UserCountry/index.tpl
===================================================================
--- plugins/UserCountry/index.tpl	(wersja 441)
+++ plugins/UserCountry/index.tpl	(kopia robocza)
@@ -2,12 +2,13 @@
 
 <script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script>
 
-<h2>Country</h2>
+<h2>{'UserCountry_Country'|translate}</h2>
 {$dataTableCountry}
 
-<h2>Continent</h2>
+<h2>{'UserCountry_Continent'|translate}</h2>
 {$dataTableContinent}
 
-<p><img class="sparkline" src="{$urlSparklineCountries}" /> <span><strong>{$numberDistinctCountries} </strong> distinct countries</span></p>	
+<p><img class="sparkline" src="{$urlSparklineCountries}" /> <span>
+{'UserCountry_DistinctCountries'|translate:"<strong>$numberDistinctCountries</strong>"} </span></p>	
 
-{postEvent name="template_footerUserCountry"}
\ brakuje znaku końca linii na końcu pliku 
+{postEvent name="template_footerUserCountry"}
Index: plugins/Login/lang/en.php
===================================================================
--- plugins/Login/lang/en.php	(wersja 0)
+++ plugins/Login/lang/en.php	(wersja 0)
@@ -0,0 +1,18 @@
+<?php
+$translations = array(
+	'Login_PluginDescription' => 'Login screen, gives credentials to users',
+	'Login_LoginPasswordNotCorrect' => 'Username & Password not correct',
+	'Login_Login' => 'Username',
+	'Login_Password' => 'Password',
+	'Login_LoginOrEmail' => 'Login or E-mail',
+	'Login_LogIn' => 'Log in',
+	'Login_Logout' => 'Logout',
+	'Login_LostYourPassword' => 'Lost your password?',	
+	'Login_RemindPassword' => 'Remind password',
+	'Login_PasswordReminder' => 'Please enter your username and e-mail address. We will send you a new password to your mailbox.',
+	'Login_InvalidUsernameEmail' => 'Invalid username and/or e-mail address',
+	
+	'Login_MailTopicPasswordRecovery' => 'Password recovery',
+	'Login_MailBodyPasswordRecovery' => "Hi %1s,\n\nYour new password is: %2s\n\nYou can login now at: %3s",
+	'Login_PasswordSent' => 'Password has been just sent. Check your e-mail.'
+);
Index: plugins/Login/lang/fr.php
===================================================================
--- plugins/Login/lang/fr.php	(wersja 0)
+++ plugins/Login/lang/fr.php	(wersja 0)
@@ -0,0 +1,7 @@
+<?php
+$translations = array(
+	'Login_LoginPasswordNotCorrect' => 'Utilisateur & Mot de passe not correct',
+	'Login_Login' => 'Utilisateur',
+	'Login_Password' => 'Mot de passe',
+	'Login_LogIn' => 'Log in',	
+);
Index: plugins/Login/Controller.php
===================================================================
--- plugins/Login/Controller.php	(wersja 441)
+++ plugins/Login/Controller.php	(kopia robocza)
@@ -11,6 +11,7 @@
 
 require_once "UsersManager/API.php";
 require_once "Login/Form.php";
+require_once "Login/PasswordForm.php";
 require_once "View.php";
 
 
@@ -29,20 +30,18 @@
 	{
 		$form = new Piwik_Login_Form;
 		$AccessErrorString = false;
-		
+
+		$currentUrl = Piwik_Url::getCurrentUrl();
+		// get url from POSTed form or GET parameter (getting back from password remind form)
+		$urlToRedirect = Piwik_Common::getRequestVar('form_url', htmlspecialchars($currentUrl), 'string');
+					
 		if($form->validate())
 		{
 			// value submitted in form
 			$login = $form->getSubmitValue('form_login');
 			$password = $form->getSubmitValue('form_password');
-			$password = md5($password);
+			$password = md5($password);
 			
-			$baseUrl = Piwik_Url::getCurrentUrlWithoutQueryString(); 
-			$currentUrl = Piwik_Url::getCurrentUrl();		
-			$urlToRedirect = Piwik_Common::getRequestVar('form_url', $currentUrl, 'string', $_POST);
-			
-			$urlToRedirect = htmlspecialchars_decode($urlToRedirect);
-			
 			$tokenAuth = Piwik_UsersManager_API::getTokenAuth($login, $password);
 	
 			Piwik_Login::prepareAuthObject($login, $tokenAuth);
@@ -59,6 +58,7 @@
 				$cookie->set('token_auth', $tokenAuth);
 				$cookie->save();
 				
+				$urlToRedirect = htmlspecialchars_decode($urlToRedirect);				
 				Piwik_Url::redirectToUrl($urlToRedirect);
 			}
 			else
@@ -66,7 +66,9 @@
 				$messageNoAccess = Piwik_Translate('Login_LoginPasswordNotCorrect');
 			}
 		}
-		$view = new Piwik_View('Login/templates/login.tpl');	
+		$view = new Piwik_View('Login/templates/login.tpl');
+		// make navigation login form -> reset password -> login form remember your first url
+		$view->urlToRedirect = $urlToRedirect;
 		$view->AccessErrorString = $messageNoAccess;
 		$view->linkTitle = Piwik::getRandomTitle();
 		$view->addForm( $form );
@@ -74,6 +76,75 @@
 		echo $view->render();
 	}
 	
+	function lostpassword($messageNoAccess = null)
+	{
+		$form = new Piwik_Login_PasswordForm;
+		$AccessErrorString = false;
+		
+		$currentUrl = Piwik_Url::getCurrentUrlWithoutQueryString();	
+		$urlToRedirect = Piwik_Common::getRequestVar('form_url', htmlspecialchars($currentUrl), 'string');
+		
+		if($form->validate())
+		{
+			// value submitted in form (login or email)
+			$loginMail = $form->getSubmitValue('form_login');
+
+			// get admin privileges before calling API
+			Piwik::setUserIsSuperUser();
+			
+			$user = null;
+			
+			// determine if given value is login or email
+			if( Piwik_UsersManager_API::userExists($loginMail) )
+			{
+				$user = Piwik_UsersManager_API::getUser($loginMail);
+			}
+			else if( Piwik_UsersManager_API::userEmailExists($loginMail) )
+			{
+				$user = Piwik_UsersManager_API::getUserByEmail($loginMail);
+
+			}
+			
+			// if user exists
+			if( $user != null )
+			{
+				$login = $user['login'];
+				$email = $user['email'];
+							
+				$randomPassword = Piwik_Common::getRandomString(8);
+				
+				Piwik_UsersManager_API::updateUser($login, $randomPassword);
+
+				// send email with new password
+				$mail = new Piwik_Mail();				
+				$mail->addTo($email, $login);
+				$mail->setSubject(Piwik_Translate('Login_MailTopicPasswordRecovery'));				
+				$mail->setBodyText(sprintf(Piwik_Translate('Login_MailBodyPasswordRecovery'),
+					$login, $randomPassword, Piwik_Url::getCurrentUrlWithoutQueryString()));				
+				$mail->send();
+						
+				$view = new Piwik_View('Login/templates/passwordsent.tpl');
+				$view->linkTitle = Piwik::getRandomTitle();
+				$view->urlToRedirect = $urlToRedirect;
+				echo $view->render();
+
+				return;
+			}
+			else
+			{
+				$messageNoAccess = Piwik_Translate('Login_InvalidUsernameEmail');
+			}
+		}	
+		$view = new Piwik_View('Login/templates/lostpassword.tpl');	
+		$view->AccessErrorString = $messageNoAccess;
+		// make navigation login form -> reset password -> login form remember your first url		
+		$view->urlToRedirect = $urlToRedirect;
+		$view->linkTitle = Piwik::getRandomTitle();
+		$view->addForm( $form );
+		$view->subTemplate = 'genericForm.tpl';
+		echo $view->render();		
+	}
+	
 	function logout()
 	{		
 		$authCookieName = 'piwik-auth';
Index: plugins/Login/Form.php
===================================================================
--- plugins/Login/Form.php	(wersja 441)
+++ plugins/Login/Form.php	(kopia robocza)
@@ -26,7 +26,8 @@
 	
 	function init()
 	{
-		$urlToGoAfter = Piwik_Url::getCurrentUrl();			
+		// if form_url is not defined go to current url
+		$urlToGoAfter = Piwik_Common::getRequestVar('form_url', Piwik_Url::getCurrentUrl(), 'string');
 		
 		// if the current url to redirect contains module=login we insteaed redirect to the referer url
 		if(stripos($urlToGoAfter,'module=login') !== false)
Index: plugins/Login/PasswordForm.php
===================================================================
--- plugins/Login/PasswordForm.php	(wersja 0)
+++ plugins/Login/PasswordForm.php	(wersja 0)
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: Form.php 390 2008-03-19 01:31:11Z matt $
+ * 
+ * @package Piwik_Login
+ */
+
+require_once "modules/Form.php";
+
+/**
+ * 
+ * @package Piwik_Login
+ */
+class Piwik_Login_PasswordForm extends Piwik_Form
+{
+	function __construct()
+	{
+		parent::__construct();
+		// reset 
+		$this->updateAttributes('id="loginform" name="loginform"');
+	}
+	
+	function init()
+	{
+		$urlToGoAfter = Piwik_Common::getRequestVar('form_url', Piwik_Url::getCurrentUrlWithoutQueryString(), 'string');
+			
+		$formElements = array(
+			array('text', 'form_login'),
+			array('hidden', 'form_url', $urlToGoAfter),
+		);
+		$this->addElements( $formElements );
+		
+		$formRules = array(
+			array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_LoginOrEmail')), 'required'),		
+			array('hidden', 'form_url', $urlToGoAfter),			
+		);
+		$this->addRules( $formRules );	
+		
+		$this->addElement('submit', 'submit');	
+	}
+	
+	
+}
+
Index: plugins/Login/templates/login.css
===================================================================
--- plugins/Login/templates/login.css	(wersja 441)
+++ plugins/Login/templates/login.css	(kopia robocza)
@@ -37,9 +37,14 @@
 
 form p { margin-bottom: 24px; }
 
+.updated, .login #login_error, .login .message {
+	background-color: #ffffe0;
+	border-color: #e6db55;
+}
+
 #login { width: 292px; margin: 7em auto; margin-top: 20px; }
 
-#login_error {
+#login_error, .message {
 	margin: 0 0 16px 8px;
 	border-width: 1px;
 	border-style: solid;
Index: plugins/Login/templates/lostpassword.tpl
===================================================================
--- plugins/Login/templates/lostpassword.tpl	(wersja 0)
+++ plugins/Login/templates/lostpassword.tpl	(wersja 0)
@@ -0,0 +1,66 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
+<head>
+	<title>Piwik &rsaquo; Lost password</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	
+	{literal}
+	<script type="text/javascript">
+		function focusit() {
+			document.getElementById('form_login').focus();
+		}
+		window.onload = focusit;
+	</script>
+	{/literal}
+<link rel="stylesheet" href="plugins/Login/templates/login.css">
+</head>
+
+<body class="login">
+<!-- shamelessly taken from wordpress 2.5 - thank you guys!!! -->
+
+<div id="logo">
+	<a href="http://piwik.org" title="{$linkTitle}"><span class="h1">Piwik <span class="description"># open source web analytics</span></span></a>
+</div>
+
+<div id="login">
+
+{if $form_data.errors}
+<div id="login_error">	
+	{foreach from=$form_data.errors item=data}
+		<strong>{'General_Error'|translate}</strong>: {$data}<br />
+	{/foreach}
+</div>
+{/if}
+
+{if $AccessErrorString}
+<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div>
+{/if}
+
+<p class="message">
+{'Login_PasswordReminder'|translate}
+</p>
+
+<form {$form_data.attributes}>
+
+	<p>
+		<label>{'Login_LoginOrEmail'|translate}:<br />
+		<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label>
+	</p>
+	{$form_data.form_url.html}
+	<p class="submit">
+		<input type="submit" value="{'Login_RemindPassword'|translate}" tabindex="100" />
+	</p>
+</form>
+
+
+<p id="nav">
+<a href="?module=Login&form_url={$urlToRedirect}" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
+</p>
+
+</div>
+
+</body>
+</html>
+
+
+
Index: plugins/Login/templates/login.tpl
===================================================================
--- plugins/Login/templates/login.tpl	(wersja 441)
+++ plugins/Login/templates/login.tpl	(kopia robocza)
@@ -27,23 +27,23 @@
 {if $form_data.errors}
 <div id="login_error">	
 	{foreach from=$form_data.errors item=data}
-		<strong>ERROR</strong>: {$data}<br />
+		<strong>{'General_Error'|translate}</strong>: {$data}<br />
 	{/foreach}
 </div>
 {/if}
 
 {if $AccessErrorString}
-<div id="login_error"><strong>ERROR</strong>: {$AccessErrorString}<br /></div>
+<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div>
 {/if}
 
 <form {$form_data.attributes}>
 	<p>
-		<label>{'Login_Login'|translate}<br />
+		<label>{'Login_Login'|translate}:<br />
 		<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label>
 	</p>
 
 	<p>
-		<label>{'Login_Password'|translate}<br />
+		<label>{'Login_Password'|translate}:<br />
 		<input type="password" name="form_password" id="form_password" class="input" value="" size="20" tabindex="20" /></label>
 	</p>
 	{*
@@ -55,11 +55,11 @@
 	</p>
 </form>
 
-{*
+
 <p id="nav">
-<a href="" title="Password Lost and Found">Lost your password?</a>
+<a href="?module=Login&action=lostpassword&form_url={$urlToRedirect}" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
 </p>
-*}
+
 </div>
 
 </body>
Index: plugins/Login/templates/passwordsent.tpl
===================================================================
--- plugins/Login/templates/passwordsent.tpl	(wersja 0)
+++ plugins/Login/templates/passwordsent.tpl	(wersja 0)
@@ -0,0 +1,32 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
+<head>
+	<title>Piwik &rsaquo; Lost password</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<link rel="stylesheet" href="plugins/Login/templates/login.css">
+</head>
+
+<body class="login">
+<!-- shamelessly taken from wordpress 2.5 - thank you guys!!! -->
+
+<div id="logo">
+	<a href="http://piwik.org" title="{$linkTitle}"><span class="h1">Piwik <span class="description"># open source web analytics</span></span></a>
+</div>
+
+<div id="login">
+
+<p class="message">
+{'Login_PasswordSent'|translate}
+</p>
+
+<p id="nav">
+<a href="?module=Login&form_url={$urlToRedirect}" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
+</p>
+
+</div>
+
+</body>
+</html>
+
+
+
Index: plugins/Login/Login.php
===================================================================
--- plugins/Login/Login.php	(wersja 441)
+++ plugins/Login/Login.php	(kopia robocza)
@@ -27,7 +27,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
-			'translationAvailable' => false,
+			'translationAvailable' => true,
 		);
 		
 		return $info;
Index: plugins/API/API.php
===================================================================
--- plugins/API/API.php	(wersja 441)
+++ plugins/API/API.php	(kopia robocza)
@@ -20,7 +20,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
-			'translationAvailable' => false,
+			'translationAvailable' => true,
 		);
 	}
 }
Index: plugins/API/lang/en.php
===================================================================
--- plugins/API/lang/en.php	(wersja 0)
+++ plugins/API/lang/en.php	(wersja 0)
@@ -0,0 +1,12 @@
+<?php
+$translations = array(
+	'API_QuickDocumentation' => 
+		"<h1>API quick documentation</h1>".
+		"<p>If you don't have data for today you can first <a href='misc/generateVisits.php' target=_blank>generate some data</a> using the Visits Generator script.</p>".
+		"<p>You can try the different formats available for every method. It is very easy to extract any data you want from piwik!</p>".
+		"<p>If you want to <b>request the data without being logged in to Piwik</b> you need to add the parameter <code><u>&token_auth=%s</u></code> to the API calls URLs that require authentication.</p>".
+		"<p><b>For more information have a look at the <a href='http://dev.piwik.org/trac/wiki/API'>official API Documentation</a> or the <a href='http://dev.piwik.org/trac/wiki/API/Reference'>API Reference</a>.</b></P>",
+	'API_LoadedAPIs' => 'Loaded successfully %s APIs',
+	
+
+);
Index: plugins/API/Controller.php
===================================================================
--- plugins/API/Controller.php	(wersja 441)
+++ plugins/API/Controller.php	(kopia robocza)
@@ -55,18 +55,15 @@
 	function listAllAPI()
 	{
 		$token_auth = Zend_Registry::get('auth')->getTokenAuth();
-		echo "<style>body{ font-family:georgia,arial; font-size:0.95em;} </style>";
-		echo "<h1>API quick documentation</h1>";
-		echo "<p>If you don't have data for today you can first <a href='misc/generateVisits.php' target=_blank>generate some data</a> using the Visits Generator script.</p>";
-		echo "<p>You can try the different formats available for every method. It is very easy to extract any data you want from piwik!</p>";
-		echo "<p>If you want to <b>request the data without being logged in to Piwik</b> you need to add the parameter <code><u>&token_auth=$token_auth</u></code> to the API calls URLs that require authentication.</p>";
-		echo "<p><b>For more information have a look at the <a href='http://dev.piwik.org/trac/wiki/API'>official API Documentation</a> or the <a href='http://dev.piwik.org/trac/wiki/API/Reference'>API Reference</a>.</b></P>";
+		echo "<style>body{ font-family:georgia,arial; font-size:0.95em;} </style>";
+		echo sprintf(Piwik_Translate('API_QuickDocumentation'),$token_auth);
+
 
 		$loaded = $this->init();
-		echo "<p><i> Loaded successfully $loaded APIs</i></p>\n";
+		echo "<p><i> ".sprintf(Piwik_Translate('API_LoadedAPIs'),$loaded)."</i></p>\n";
 		
 		echo Piwik_API_Proxy::getInstance()->getAllInterfaceString();
-		echo "<p><a href='?module=Home'>Back to Piwik homepage</a></p>";
+		echo "<p><a href='?module=Home'>".Piwik_Translate('General_BackToHomepage')."</a></p>";
 	}
 	
 }
Index: plugins/Referers/lang/en.php
===================================================================
--- plugins/Referers/lang/en.php	(wersja 441)
+++ plugins/Referers/lang/en.php	(kopia robocza)
@@ -1,10 +1,27 @@
 <?php
 $translations = array(
-	'Referers_DirectEntry' => 'Direct Entry',
 	'Referers_SearchEngines' => 'Search Engines',
-	'Referers_Websites' => 'Websites',
-	'Referers_Partners' => 'Partners',
-	'Referers_Newsletters' => 'Newsletters',
-	'Referers_Campaigns' => 'Campaigns',
+	
+	'Referers_Keywords' => 'Keywords',
+	
+	'Referers_Evolution' => 'Evolution over the period',
+	
+	'Referers_Type' => 'Referer Type',	
+	'Referers_TypeDirectEntries' => '%s direct entries',
+	'Referers_TypeSearchEngines' => '%s from search engines',
+	'Referers_TypePartners' => '%s from partners',
+	'Referers_TypeWebsites' => '%s from websites',
+	'Referers_TypeNewsletters' => '%s from newsletters',
+	'Referers_TypeCampaigns' => '%s from campaigns',
+	
+	'Referers_Other' => 'Other',
+	'Referers_OtherDistinctSearchEngines' => '%s distinct search engines',
+	'Referers_OtherDistinctKeywords' => '%s distinct keywords',
+	'Referers_OtherDistinctWebsites' => '%1s distinct websites (using %2s distinct urls)',
+	'Referers_OtherDistinctPartners' => '%1s distinct partners (using %2s distinct urls)',
+	'Referers_OtherDistinctCampaigns' => '%s distinct campaigns',
+	
+	'Referers_TagCloud' => 'Tag cloud output',
+
 );
  
Index: plugins/Referers/searchEngines_Keywords.tpl
===================================================================
--- plugins/Referers/searchEngines_Keywords.tpl	(wersja 441)
+++ plugins/Referers/searchEngines_Keywords.tpl	(kopia robocza)
@@ -1,9 +1,9 @@
 <div id='leftcolumn'>
-	<h2>Search engines</h2>
+	<h2>{'Referers_SearchEngines'|translate}</h2>
 	{$searchEngines}
 </div>
 
 <div id='rightcolumn'>
-	<h2>Keywords</h2>
+	<h2>{'Referers_Keywords'|translate}</h2>
 	{$keywords}
 </div>
Index: plugins/Referers/index.tpl
===================================================================
--- plugins/Referers/index.tpl	(wersja 441)
+++ plugins/Referers/index.tpl	(kopia robocza)
@@ -1,33 +1,44 @@
 <script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script>
 
 	<a name="evolutionGraph" graphId="{$nameGraphEvolutionReferers}"></a>
-	<h2>Evolution over the period</h2>
+	<h2>{'Referers_Evolution'|translate}</h2>
 	{$graphEvolutionReferers}
 	
-	<h2>Referer Type</h2>
+	<h2>{'Referers_Type'|translate}</h2>
 	<table>
 		<tr><td>
-			<p><img class="sparkline" src="{$urlSparklineDirectEntry}" /> <span><strong>{$visitorsFromDirectEntry} </strong> direct entries</span></p>
-			<p><img class="sparkline" src="{$urlSparklineSearchEngines}" /> <span><strong>{$visitorsFromSearchEngines} </strong>  from search engines</span></p>
-			<p><img class="sparkline" src="{$urlSparklinePartners}" /> <span><strong>{$visitorsFromPartners} </strong> from partners</span></p>
+			<p><img class="sparkline" src="{$urlSparklineDirectEntry}" /> <span>
+			{'Referers_TypeDirectEntries'|translate:"<strong>$visitorsFromDirectEntry</strong>"}</span></p>
+			<p><img class="sparkline" src="{$urlSparklineSearchEngines}" /> <span>
+			{'Referers_TypeSearchEngines'|translate:"<strong>$visitorsFromSearchEngines</strong>"}</span></p>
+			<p><img class="sparkline" src="{$urlSparklinePartners}" /> <span>
+			{'Referers_TypePartners'|translate:"<strong>$visitorsFromPartners</strong>"}</span></p>
 		</td><td>
-			<p><img class="sparkline" src="{$urlSparklineWebsites}" /> <span><strong>{$visitorsFromWebsites} </strong> from websites</span></p>
-			<p><img class="sparkline" src="{$urlSparklineNewsletters}" /> <span><strong>{$visitorsFromNewsletters} </strong>  from newsletters</span></p>
-			<p><img class="sparkline" src="{$urlSparklineCampaigns}" /> <span><strong>{$visitorsFromCampaigns} </strong>  from campaigns</span></p>
+			<p><img class="sparkline" src="{$urlSparklineWebsites}" /> <span>
+			{'Referers_TypeWebsites'|translate:"<strong>$visitorsFromWebsites</strong>"}</span></p>
+			<p><img class="sparkline" src="{$urlSparklineNewsletters}" /> <span>
+			{'Referers_TypeNewsletters'|translate:"<strong>$visitorsFromNewsletters</strong>"}</span></p>
+			<p><img class="sparkline" src="{$urlSparklineCampaigns}" /> <span>
+			{'Referers_TypeCampaigns'|translate:"<strong>$visitorsFromCampaigns</strong>"}</span></p>
 		</td></tr>
 	</table>
 	
-	<h2>Other</h2>
+	<h2>{'Referers_Other'|translate}</h2>
 	<table>
 		<tr><td>
-			<p><img class="sparkline" src="{$urlSparklineDistinctSearchEngines}" /> <span><strong>{$numberDistinctSearchEngines} </strong>  distinct search engines</span></p>
-			<p><img class="sparkline" src="{$urlSparklineDistinctKeywords}" /> <span><strong>{$numberDistinctKeywords} </strong> distinct keywords</span></p>
+			<p><img class="sparkline" src="{$urlSparklineDistinctSearchEngines}" /> <span>
+			{'Referers_OtherDistinctSearchEngines'|translate:"<strong>$numberDistinctSearchEngines</strong>"}</span></p>
+			<p><img class="sparkline" src="{$urlSparklineDistinctKeywords}" /> <span>
+			{'Referers_OtherDistinctKeywords'|translate:"<strong>$numberDistinctKeywords</strong>"}</span></p>
 		</td><td>
-			<p><img class="sparkline" src="{$urlSparklineDistinctWebsites}" /> <span><strong>{$numberDistinctWebsites} </strong>  distinct websites (using <strong>{$numberDistinctWebsitesUrls}</strong> distinct urls)</span></p>
-			<p><img class="sparkline" src="{$urlSparklineDistinctPartners}" /> <span><strong>{$numberDistinctPartners} </strong>   distinct partners (using <strong>{$numberDistinctPartnersUrls}</strong> distinct urls)</span></p>
-			<p><img class="sparkline" src="{$urlSparklineDistinctCampaigns}" /> <span><strong>{$numberDistinctCampaigns} </strong>  distinct campaigns</span></p>
+			<p><img class="sparkline" src="{$urlSparklineDistinctWebsites}" /> <span>
+			{'Referers_OtherDistinctWebsites'|translate:"<strong>$numberDistinctWebsites</strong>":"<strong>$numberDistinctWebsitesUrls</strong>"}</span></p>
+			<p><img class="sparkline" src="{$urlSparklineDistinctPartners}" /> <span>
+			{'Referers_OtherDistinctPartners'|translate:"<strong>$numberDistinctPartners</strong>":"<strong>$numberDistinctPartnersUrls</strong>"}</span></p>
+			<p><img class="sparkline" src="{$urlSparklineDistinctCampaigns}" /> <span> 
+			{'Referers_OtherDistinctCampaigns'|translate:"<strong>$numberDistinctCampaigns</strong>"}</span></p>
 			</td></tr>
 	</table>
 	
-	<p>Tag cloud output</p>
-	{$dataTableRefererType}
\ brakuje znaku końca linii na końcu pliku 
+	<p>{'Referers_TagCloud'|translate}</p>
+	{$dataTableRefererType}
Index: plugins/VisitTime/lang/en.php
===================================================================
--- plugins/VisitTime/lang/en.php	(wersja 0)
+++ plugins/VisitTime/lang/en.php	(wersja 0)
@@ -0,0 +1,5 @@
+<?php
+$translations = array(
+	'VisitTime_LocalTime' => 'Visit per local time',
+	'VisitTime_ServerTime' => 'Visit per server time',
+);
Index: plugins/VisitTime/VisitTime.php
===================================================================
--- plugins/VisitTime/VisitTime.php	(wersja 441)
+++ plugins/VisitTime/VisitTime.php	(kopia robocza)
@@ -29,6 +29,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
+			'translationAvailable' => true
 		);
 		
 		return $info;
Index: plugins/VisitTime/index.tpl
===================================================================
--- plugins/VisitTime/index.tpl	(wersja 441)
+++ plugins/VisitTime/index.tpl	(kopia robocza)
@@ -1,9 +1,9 @@
 <div id='leftcolumn'>
-<h2>Visit per local time</h2>
+<h2>{'VisitTime_LocalTime'|translate}</h2>
 {$dataTableVisitInformationPerLocalTime}
 </div>
 
 <div id='rightcolumn'>
-<h2>Visit per server time</h2>
+<h2>{'VisitTime_ServerTime'|translate}</h2>
 {$dataTableVisitInformationPerServerTime}
-</div>
\ brakuje znaku końca linii na końcu pliku 
+</div>
Index: plugins/VisitorInterest/lang/en.php
===================================================================
--- plugins/VisitorInterest/lang/en.php	(wersja 0)
+++ plugins/VisitorInterest/lang/en.php	(wersja 0)
@@ -0,0 +1,5 @@
+<?php
+$translations = array(
+	'VisitorInterest_VisitsPerDuration' => 'Visits per visit duration',
+	'VisitorInterest_VisitsPerNbOfPages' => 'Visits per number of pages',
+);
Index: plugins/VisitorInterest/VisitorInterest.php
===================================================================
--- plugins/VisitorInterest/VisitorInterest.php	(wersja 441)
+++ plugins/VisitorInterest/VisitorInterest.php	(kopia robocza)
@@ -49,6 +49,7 @@
 			'author' => 'Piwik',
 			'homepage' => 'http://piwik.org/',
 			'version' => '0.1',
+			'translationAvailable' => true
 		);
 		
 		return $info;
Index: plugins/VisitorInterest/index.tpl
===================================================================
--- plugins/VisitorInterest/index.tpl	(wersja 441)
+++ plugins/VisitorInterest/index.tpl	(kopia robocza)
@@ -1,5 +1,5 @@
 
-	<h2>Visits per visit duration</h2>
+	<h2>{'VisitorInterest_VisitsPerDuration'|translate}</h2>
 	{$dataTableNumberOfVisitsPerVisitDuration}
-	<h2>Visits per number of pages</h2>
-	{$dataTableNumberOfVisitsPerPage}
\ brakuje znaku końca linii na końcu pliku 
+	<h2>{'VisitorInterest_VisitsPerNbOfPages'|translate}</h2>
+	{$dataTableNumberOfVisitsPerPage}
Index: lang/en.php
===================================================================
--- lang/en.php	(wersja 441)
+++ lang/en.php	(kopia robocza)
@@ -2,10 +2,25 @@
 $translations = array(
 	'General_Unknown' => 'Unknown',
 	'General_Required' => '%s required',
-
-	'Login_LoginPasswordNotCorrect' => 'Username & Password not correct',
-	'Login_Login' => 'Username',
-	'Login_Password' => 'Password',
-	'Login_LogIn' => 'Log in',
-	
-);
\ brakuje znaku końca linii na końcu pliku 
+	'General_Error' => 'Error',
+	'General_Warning' => 'Warning',
+	'General_BackToHomepage' => 'Back to Piwik homepage',
+	'General_Yes' => 'Yes',
+	'General_No' => 'No',
+	'General_Delete' => 'Delete',
+	'General_Edit' => 'Edit',
+	'General_Ok' => 'Ok',
+	'General_Close' => 'Close',
+	'General_Logout' => 'Logout',
+	'General_Done' => 'Done',
+	'General_LoadingData' => 'Loading data...',
+	'General_ErrorRequest' => 'Oops&hellip; problem during the request, please try again.',
+	'General_Next' => 'Next',
+	'General_Previous' => 'Previous',
+	'General_Table' => 'Table',
+	'General_Piechart' => 'Piechart',
+	'General_TagCloud' => 'Tag Cloud',
+	'General_VBarGraph' => 'Vertial bar graph',
+	'General_GraphData' => 'Graph data',
+	'General_Refresh' => 'Refresh the page',
+);
Index: lang/fr.php
===================================================================
--- lang/fr.php	(wersja 441)
+++ lang/fr.php	(kopia robocza)
@@ -2,10 +2,4 @@
 $translations = array(
 	'General_Unknown' => 'Inconnu',
 	'General_Required' => '%s requis',
-
-	'Login_LoginPasswordNotCorrect' => 'Utilisateur & Mot de passe not correct',
-	'Login_Login' => 'Utilisateur',
-	'Login_Password' => 'Mot de passe',
-	'Login_LogIn' => 'Log in',
-	
 );
Index: libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php
===================================================================
--- libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php	(wersja 0)
+++ libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php	(wersja 0)
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Plain.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Protocol_Smtp
+ */
+require_once 'Zend/Mail/Protocol/Smtp.php';
+
+
+/**
+ * Performs PLAIN authentication
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Protocol_Smtp_Auth_Plain extends Zend_Mail_Protocol_Smtp
+{
+    /**
+     * PLAIN username
+     *
+     * @var string
+     */
+    protected $_username;
+
+
+    /**
+     * PLAIN password
+     *
+     * @var string
+     */
+    protected $_password;
+
+
+    /**
+     * Constructor.
+     *
+     * @param  string $host   (Default: 127.0.0.1)
+     * @param  int    $port   (Default: null)
+     * @param  array  $config Auth-specific parameters
+     * @return void
+     */
+    public function __construct($host = '127.0.0.1', $port = null, $config = null)
+    {
+        if (is_array($config)) {
+            if (isset($config['username'])) {
+                $this->_username = $config['username'];
+            }
+            if (isset($config['password'])) {
+                $this->_password = $config['password'];
+            }
+        }
+
+        parent::__construct($host, $port, $config);
+    }
+
+
+    /**
+     * Perform PLAIN authentication with supplied credentials
+     *
+     * @return void
+     */
+    public function auth()
+    {
+        // Ensure AUTH has not already been initiated.
+        parent::auth();
+
+        $this->_send('AUTH PLAIN');
+        $this->_expect(334);
+        $this->_send(base64_encode(chr(0) . $this->_username . chr(0) . $this->_password));
+        $this->_expect(235);
+        $this->_auth = true;
+    }
+}
Index: libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php
===================================================================
--- libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php	(wersja 0)
+++ libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php	(wersja 0)
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Crammd5.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Protocol_Smtp
+ */
+require_once 'Zend/Mail/Protocol/Smtp.php';
+
+
+/**
+ * Performs CRAM-MD5 authentication
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Protocol_Smtp_Auth_Crammd5 extends Zend_Mail_Protocol_Smtp
+{
+    /**
+     * Constructor.
+     *
+     * @param  string $host   (Default: 127.0.0.1)
+     * @param  int    $port   (Default: null)
+     * @param  array  $config Auth-specific parameters
+     * @return void
+     */
+    public function __construct($host = '127.0.0.1', $port = null, $config = null)
+    {
+        if (is_array($config)) {
+            if (isset($config['username'])) {
+                $this->_username = $config['username'];
+            }
+            if (isset($config['password'])) {
+                $this->_password = $config['password'];
+            }
+        }
+
+        parent::__construct($host, $port, $config);
+    }
+
+
+    /**
+     * @todo Perform CRAM-MD5 authentication with supplied credentials
+     *
+     * @return void
+     */
+    public function auth()
+    {
+        // Ensure AUTH has not already been initiated.
+        parent::auth();
+
+        $this->_send('AUTH CRAM-MD5');
+        $challenge = $this->_expect(334);
+        $challenge = base64_decode($challenge);
+        $digest = $this->_hmacMd5($this->_password, $challenge);
+        $this->_send(base64_encode($this->_username . ' ' . $digest));
+        $this->_expect(235);
+        $this->_auth = true;
+    }
+
+
+    /**
+     * Prepare CRAM-MD5 response to server's ticket
+     *
+     * @param  string $key   Challenge key (usually password)
+     * @param  string $data  Challenge data
+     * @param  string $block Length of blocks
+     * @return string
+     */
+    protected function _hmacMd5($key, $data, $block = 64)
+    {
+        if (strlen($key) > 64) {
+            $key = pack('H32', md5($key));
+        } elseif (strlen($key) < 64) {
+            $key = str_pad($key, $block, chr(0));
+        }
+
+        $k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64);
+        $k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64);
+
+        $inner = pack('H32', md5($k_ipad . $data));
+        $digest = md5($k_opad . $inner);
+
+        return $digest;
+    }
+}
Index: libs/Zend/Mail/Protocol/Smtp/Auth/Login.php
===================================================================
--- libs/Zend/Mail/Protocol/Smtp/Auth/Login.php	(wersja 0)
+++ libs/Zend/Mail/Protocol/Smtp/Auth/Login.php	(wersja 0)
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Login.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Protocol_Smtp
+ */
+require_once 'Zend/Mail/Protocol/Smtp.php';
+
+
+/**
+ * Performs LOGIN authentication
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Protocol_Smtp_Auth_Login extends Zend_Mail_Protocol_Smtp
+{
+    /**
+     * LOGIN username
+     *
+     * @var string
+     */
+    protected $_username;
+
+
+    /**
+     * LOGIN password
+     *
+     * @var string
+     */
+    protected $_password;
+
+
+    /**
+     * Constructor.
+     *
+     * @param  string $host   (Default: 127.0.0.1)
+     * @param  int    $port   (Default: null)
+     * @param  array  $config Auth-specific parameters
+     * @return void
+     */
+    public function __construct($host = '127.0.0.1', $port = null, $config = null)
+    {
+        if (is_array($config)) {
+            if (isset($config['username'])) {
+                $this->_username = $config['username'];
+            }
+            if (isset($config['password'])) {
+                $this->_password = $config['password'];
+            }
+        }
+
+        parent::__construct($host, $port, $config);
+    }
+
+
+    /**
+     * Perform LOGIN authentication with supplied credentials
+     *
+     * @return void
+     */
+    public function auth()
+    {
+        // Ensure AUTH has not already been initiated.
+        parent::auth();
+
+        $this->_send('AUTH LOGIN');
+        $this->_expect(334);
+        $this->_send(base64_encode($this->_username));
+        $this->_expect(334);
+        $this->_send(base64_encode($this->_password));
+        $this->_expect(235);
+        $this->_auth = true;
+    }
+}
Index: libs/Zend/Mail/Protocol/Exception.php
===================================================================
--- libs/Zend/Mail/Protocol/Exception.php	(wersja 0)
+++ libs/Zend/Mail/Protocol/Exception.php	(wersja 0)
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Exception
+ */
+require_once 'Zend/Mail/Exception.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Protocol_Exception extends Zend_Mail_Exception
+{}
+
Index: libs/Zend/Mail/Protocol/Pop3.php
===================================================================
--- libs/Zend/Mail/Protocol/Pop3.php	(wersja 0)
+++ libs/Zend/Mail/Protocol/Pop3.php	(wersja 0)
@@ -0,0 +1,461 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Pop3.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Protocol_Pop3
+{
+    /**
+     * saves if server supports top
+     * @var null|bool
+     */
+    public $hasTop = null;
+
+    /**
+     * socket to pop3
+     * @var null|resource
+     */
+    protected $_socket;
+
+    /**
+     * greeting timestamp for apop
+     * @var null|string
+     */
+    protected $_timestamp;
+
+
+    /**
+     * Public constructor
+     *
+     * @param  string      $host  hostname of IP address of POP3 server, if given connect() is called
+     * @param  int|null    $port  port of POP3 server, null for default (110 or 995 for ssl)
+     * @param  bool|string $ssl   use ssl? 'SSL', 'TLS' or false
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function __construct($host = '', $port = null, $ssl = false)
+    {
+        if ($host) {
+            $this->connect($host, $port, $ssl);
+        }
+    }
+
+
+    /**
+     * Public destructor
+     */
+    public function __destruct()
+    {
+        $this->logout();
+    }
+
+
+    /**
+     * Open connection to POP3 server
+     *
+     * @param  string      $host  hostname of IP address of POP3 server
+     * @param  int|null    $port  of POP3 server, default is 110 (995 for ssl)
+     * @param  string|bool $ssl   use 'SSL', 'TLS' or false
+     * @return string welcome message
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function connect($host, $port = null, $ssl = false)
+    {
+        if ($ssl == 'SSL') {
+            $host = 'ssl://' . $host;
+        }
+
+        if ($port === null) {
+            $port = $ssl == 'SSL' ? 995 : 110;
+        }
+
+        $this->_socket = @fsockopen($host, $port);
+        if (!$this->_socket) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('cannot connect to host');
+        }
+
+        $welcome = $this->readResponse();
+
+        strtok($welcome, '<');
+        $this->_timestamp = strtok('>');
+        if (!strpos($this->_timestamp, '@')) {
+            $this->_timestamp = null;
+        } else {
+            $this->_timestamp = '<' . $this->_timestamp . '>';
+        }
+
+        if ($ssl === 'TLS') {
+            $this->request('STLS');
+            $result = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
+            if (!$result) {
+                /**
+                 * @see Zend_Mail_Protocol_Exception
+                 */
+                require_once 'Zend/Mail/Protocol/Exception.php';
+                throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
+            }
+        }
+
+        return $welcome;
+    }
+
+
+    /**
+     * Send a request
+     *
+     * @param string $request your request without newline
+     * @return null
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function sendRequest($request)
+    {
+        $result = @fputs($this->_socket, $request . "\r\n");
+        if (!$result) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('send failed - connection closed?');
+        }
+    }
+
+
+    /**
+     * read a response
+     *
+     * @param  boolean $multiline response has multiple lines and should be read until "<nl>.<nl>"
+     * @return string response
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function readResponse($multiline = false)
+    {
+        $result = @fgets($this->_socket);
+        if (!is_string($result)) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('read failed - connection closed?');
+        }
+
+        $result = trim($result);
+        if (strpos($result, ' ')) {
+            list($status, $message) = explode(' ', $result, 2);
+        } else {
+            $status = $result;
+            $message = '';
+        }
+
+        if ($status != '+OK') {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('last request failed');
+        }
+
+        if ($multiline) {
+            $message = '';
+            $line = fgets($this->_socket);
+            while ($line && trim($line) != '.') {
+                $message .= $line;
+                $line = fgets($this->_socket);
+            };
+        }
+
+        return $message;
+    }
+
+
+    /**
+     * Send request and get resposne
+     *
+     * @see sendRequest(), readResponse()
+     *
+     * @param  string $request    request
+     * @param  bool   $multiline  multiline response?
+     * @return string             result from readResponse()
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function request($request, $multiline = false)
+    {
+        $this->sendRequest($request);
+        return $this->readResponse($multiline);
+    }
+
+
+    /**
+     * End communication with POP3 server (also closes socket)
+     *
+     * @return null
+     */
+    public function logout()
+    {
+        if (!$this->_socket) {
+            return;
+        }
+
+        try {
+            $this->request('QUIT');
+        } catch (Zend_Mail_Protocol_Exception $e) {
+            // ignore error - we're closing the socket anyway
+        }
+
+        fclose($this->_socket);
+        $this->_socket = null;
+    }
+
+
+    /**
+     * Get capabilities from POP3 server
+     *
+     * @return array list of capabilities
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function capa()
+    {
+        $result = $this->request('CAPA', true);
+        return explode("\n", $result);
+    }
+
+
+    /**
+     * Login to POP3 server. Can use APOP
+     *
+     * @param  string $user      username
+     * @param  string $password  password
+     * @param  bool   $try_apop  should APOP be tried?
+     * @return void
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function login($user, $password, $tryApop = true)
+    {
+        if ($tryApop && $this->_timestamp) {
+            try {
+                $this->request("APOP $user " . md5($this->_timestamp . $password));
+                return;
+            } catch (Zend_Mail_Protocol_Exception $e) {
+                // ignore
+            }
+        }
+
+        $result = $this->request("USER $user");
+        $result = $this->request("PASS $password");
+    }
+
+
+    /**
+     * Make STAT call for message count and size sum
+     *
+     * @param  int $messages  out parameter with count of messages
+     * @param  int $octets    out parameter with size in octects of messages
+     * @return void
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function status(&$messages, &$octets)
+    {
+        $messages = 0;
+        $octets = 0;
+        $result = $this->request('STAT');
+
+        list($messages, $octets) = explode(' ', $result);
+    }
+
+
+    /**
+     * Make LIST call for size of message(s)
+     *
+     * @param  int|null $msgno number of message, null for all
+     * @return int|array size of given message or list with array(num => size)
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function getList($msgno = null)
+    {
+        if ($msgno !== null) {
+            $result = $this->request("LIST $msgno");
+
+            list(, $result) = explode(' ', $result);
+            return (int)$result;
+        }
+
+        $result = $this->request('LIST', true);
+        $messages = array();
+        $line = strtok($result, "\n");
+        while ($line) {
+            list($no, $size) = explode(' ', trim($line));
+            $messages[(int)$no] = (int)$size;
+            $line = strtok("\n");
+        }
+
+        return $messages;
+    }
+
+
+    /**
+     * Make UIDL call for getting a uniqueid
+     *
+     * @param  int|null $msgno number of message, null for all
+     * @return string|array uniqueid of message or list with array(num => uniqueid)
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function uniqueid($msgno = null)
+    {
+        if ($msgno !== null) {
+            $result = $this->request("UIDL $msgno");
+
+            list(, $result) = explode(' ', $result);
+            return $result;
+        }
+
+        $result = $this->request('UIDL', true);
+
+        $result = explode("\n", $result);
+        $messages = array();
+        foreach ($result as $line) {
+            if (!$line) {
+                continue;
+            }
+            list($no, $id) = explode(' ', trim($line), 2);
+            $messages[(int)$no] = $id;
+        }
+
+        return $messages;
+
+    }
+
+
+    /**
+     * Make TOP call for getting headers and maybe some body lines
+     * This method also sets hasTop - before it it's not known if top is supported
+     *
+     * The fallback makes normale RETR call, which retrieves the whole message. Additional
+     * lines are not removed.
+     *
+     * @param  int  $msgno    number of message
+     * @param  int  $lines    number of wanted body lines (empty line is inserted after header lines)
+     * @param  bool $fallback fallback with full retrieve if top is not supported
+     * @return string message headers with wanted body lines
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function top($msgno, $lines = 0, $fallback = false)
+    {
+        if ($this->hasTop === false) {
+            if ($fallback) {
+                return $this->retrieve($msgno);
+            } else {
+                /**
+                 * @see Zend_Mail_Protocol_Exception
+                 */
+                require_once 'Zend/Mail/Protocol/Exception.php';
+                throw new Zend_Mail_Protocol_Exception('top not supported and no fallback wanted');
+            }
+        }
+        $this->hasTop = true;
+
+        $lines = (!$lines || $lines < 1) ? 0 : (int)$lines;
+
+        try {
+            $result = $this->request("TOP $msgno $lines", true);
+        } catch (Zend_Mail_Protocol_Exception $e) {
+            $this->hasTop = false;
+            if ($fallback) {
+                $result = $this->retrieve($msgno);
+            } else {
+                throw $e;
+            }
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * Make a RETR call for retrieving a full message with headers and body
+     *
+     * @deprecated since 1.1.0; this method has a typo - please use retrieve()
+     * @param  int $msgno  message number
+     * @return string message
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function retrive($msgno)
+    {
+        return $this->retrieve($msgno);
+    }
+
+
+    /**
+     * Make a RETR call for retrieving a full message with headers and body
+     *
+     * @param  int $msgno  message number
+     * @return string message
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function retrieve($msgno)
+    {
+        $result = $this->request("RETR $msgno", true);
+        return $result;
+    }
+
+    /**
+     * Make a NOOP call, maybe needed for keeping the server happy
+     *
+     * @return null
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function noop()
+    {
+        $this->request('NOOP');
+    }
+
+
+    /**
+     * Make a DELE count to remove a message
+     *
+     * @return null
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function delete($msgno)
+    {
+        $this->request("DELE $msgno");
+    }
+
+
+    /**
+     * Make RSET call, which rollbacks delete requests
+     *
+     * @return null
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function undelete()
+    {
+        $this->request('RSET');
+    }
+}
Index: libs/Zend/Mail/Protocol/Abstract.php
===================================================================
--- libs/Zend/Mail/Protocol/Abstract.php	(wersja 0)
+++ libs/Zend/Mail/Protocol/Abstract.php	(wersja 0)
@@ -0,0 +1,385 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Abstract.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Validate
+ */
+require_once 'Zend/Validate.php';
+
+
+/**
+ * @see Zend_Validate_Hostname
+ */
+require_once 'Zend/Validate/Hostname.php';
+
+
+/**
+ * Zend_Mail_Protocol_Abstract
+ *
+ * Provides low-level methods for concrete adapters to communicate with a remote mail server and track requests and responses.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Abstract.php 8064 2008-02-16 10:58:39Z thomas $
+ * @todo Implement proxy settings
+ */
+abstract class Zend_Mail_Protocol_Abstract
+{
+    /**
+     * Mail default EOL string
+     */
+    const EOL = "\r\n";
+
+
+    /**
+     * Default timeout in seconds for initiating session
+     */
+    const TIMEOUT_CONNECTION = 30;
+
+
+    /**
+     * Hostname or IP address of remote server
+     * @var string
+     */
+    protected $_host;
+
+
+    /**
+     * Port number of connection
+     * @var integer
+     */
+    protected $_port;
+
+
+    /**
+     * Instance of Zend_Validate to check hostnames
+     * @var Zend_Validate
+     */
+    protected $_validHost;
+
+
+    /**
+     * Socket connection resource
+     * @var resource
+     */
+    protected $_socket;
+
+
+    /**
+     * Last request sent to server
+     * @var string
+     */
+    protected $_request;
+
+
+    /**
+     * Array of server responses to last request
+     * @var array
+     */
+    protected $_response;
+
+
+    /**
+     * String template for parsing server responses using sscanf (default: 3 digit code and response string)
+     * @var resource
+     */
+    protected $_template = '%d%s';
+
+
+    /**
+     * Log of mail requests and server responses for a session
+     * @var string
+     */
+    private $_log;
+
+
+    /**
+     * Constructor.
+     *
+     * @param  string  $host OPTIONAL Hostname of remote connection (default: 127.0.0.1)
+     * @param  integer $port OPTIONAL Port number (default: null)
+     * @throws Zend_Mail_Protocol_Exception
+     * @return void
+     */
+    public function __construct($host = '127.0.0.1', $port = null)
+    {
+        $this->_validHost = new Zend_Validate();
+        $this->_validHost->addValidator(new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL));
+
+        if (!$this->_validHost->isValid($host)) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
+        }
+
+        $this->_host = $host;
+        $this->_port = $port;
+    }
+
+
+    /**
+     * Class destructor to cleanup open resources
+     *
+     * @return void
+     */
+    public function __destruct()
+    {
+        $this->_disconnect();
+    }
+
+
+    /**
+     * Create a connection to the remote host
+     *
+     * Concrete adapters for this class will implement their own unique connect scripts, using the _connect() method to create the socket resource.
+     */
+    abstract public function connect();
+
+
+    /**
+     * Retrieve the last client request
+     *
+     * @return string
+     */
+    public function getRequest()
+    {
+        return $this->_request;
+    }
+
+
+    /**
+     * Retrieve the last server response
+     *
+     * @return array
+     */
+    public function getResponse()
+    {
+        return $this->_response;
+    }
+
+
+    /**
+     * Retrieve the transaction log
+     *
+     * @return string
+     */
+    public function getLog()
+    {
+        return $this->_log;
+    }
+
+
+    /**
+     * Reset the transaction log
+     *
+     * @return void
+     */
+    public function resetLog()
+    {
+        $this->_log = '';
+    }
+
+
+    /**
+     * Connect to the server using the supplied transport and target
+     *
+     * An example $remote string may be 'tcp://mail.example.com:25' or 'ssh://hostname.com:2222'
+     *
+     * @param  string $remote Remote
+     * @throws Zend_Mail_Protocol_Exception
+     * @return boolean
+     */
+    protected function _connect($remote)
+    {
+        $errorNum = 0;
+        $errorStr = '';
+
+        // open connection
+        $this->_socket = stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION);
+
+        if ($this->_socket === false) {
+            if ($errorNum == 0) {
+                $errorStr = 'Could not open socket';
+            }
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception($errorStr);
+        }
+
+        if (($result = stream_set_timeout($this->_socket, self::TIMEOUT_CONNECTION)) === false) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('Could not set stream timeout');
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * Disconnect from remote host and free resource
+     *
+     * @return void
+     */
+    protected function _disconnect()
+    {
+        if (is_resource($this->_socket)) {
+            fclose($this->_socket);
+        }
+    }
+
+
+    /**
+     * Send the given request followed by a LINEEND to the server.
+     *
+     * @param  string $request
+     * @throws Zend_Mail_Protocol_Exception
+     * @return integer|boolean Number of bytes written to remote host
+     */
+    protected function _send($request)
+    {
+        if (!is_resource($this->_socket)) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
+        }
+
+        $this->_request = $request;
+
+        $result = fwrite($this->_socket, $request . self::EOL);
+
+        // Save request to internal log
+        $this->_log .= $request . self::EOL;
+
+        if ($result === false) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('Could not send request to ' . $this->_host);
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * Get a line from the stream.
+     *
+     * @var    integer $timeout Per-request timeout value if applicable
+     * @throws Zend_Mail_Protocol_Exception
+     * @return string
+     */
+    protected function _receive($timeout = null)
+    {
+        if (!is_resource($this->_socket)) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
+        }
+
+        // Adapters may wish to supply per-commend timeouts according to appropriate RFC
+        if ($timeout !== null) {
+           stream_set_timeout($this->_socket, $timeout);
+        }
+
+        // Retrieve response
+        $reponse = fgets($this->_socket, 1024);
+
+        // Save request to internal log
+        $this->_log .= $reponse;
+
+        // Check meta data to ensure connection is still valid
+        $info = stream_get_meta_data($this->_socket);
+
+        if (!empty($info['timed_out'])) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception($this->_host . ' has timed out');
+        }
+
+        if ($reponse === false) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('Could not read from ' . $this->_host);
+        }
+
+        return $reponse;
+    }
+
+
+    /**
+     * Parse server response for successful codes
+     *
+     * Read the response from the stream and check for expected return code.
+     * Throws a Zend_Mail_Protocol_Exception if an unexpected code is returned.
+     *
+     * @param  string|array $code One or more codes that indicate a successful response
+     * @throws Zend_Mail_Protocol_Exception
+     * @return string Last line of response string
+     */
+    protected function _expect($code, $timeout = null)
+    {
+        $this->_response = array();
+        $cmd = '';
+        $msg = '';
+
+        if (!is_array($code)) {
+            $code = array($code);
+        }
+
+        do {
+            $this->_response[] = $result = $this->_receive($timeout);
+            sscanf($result, $this->_template, $cmd, $msg);
+
+            if ($cmd === null || !in_array($cmd, $code)) {
+                /**
+                 * @see Zend_Mail_Protocol_Exception
+                 */
+                require_once 'Zend/Mail/Protocol/Exception.php';
+                throw new Zend_Mail_Protocol_Exception($result);
+            }
+
+        } while (strpos($msg, '-') === 0); // The '-' message prefix indicates an information string instead of a response string.
+
+        return $msg;
+    }
+}
Index: libs/Zend/Mail/Protocol/Smtp.php
===================================================================
--- libs/Zend/Mail/Protocol/Smtp.php	(wersja 0)
+++ libs/Zend/Mail/Protocol/Smtp.php	(wersja 0)
@@ -0,0 +1,443 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Smtp.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mime
+ */
+require_once 'Zend/Mime.php';
+
+
+/**
+ * @see Zend_Mail_Protocol_Abstract
+ */
+require_once 'Zend/Mail/Protocol/Abstract.php';
+
+
+/**
+ * Smtp implementation of Zend_Mail_Protocol_Abstract
+ *
+ * Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
+{
+    /**
+     * The transport method for the socket
+     *
+     * @var string
+     */
+    protected $_transport = 'tcp';
+
+
+    /**
+     * Indicates that a session is requested to be secure
+     *
+     * @var string
+     */
+    protected $_secure;
+
+
+    /**
+     * Indicates an smtp session has been started by the HELO command
+     *
+     * @var boolean
+     */
+    protected $_sess = false;
+
+
+    /**
+     * Indicates the HELO command has been issues
+     *
+     * @var unknown_type
+     */
+    protected $_helo = false;
+
+
+    /**
+     * Indicates an smtp AUTH has been issued and authenticated
+     *
+     * @var unknown_type
+     */
+    protected $_auth = false;
+
+
+    /**
+     * Indicates a MAIL command has been issued
+     *
+     * @var unknown_type
+     */
+    protected $_mail = false;
+
+
+    /**
+     * Indicates one or more RCTP commands have been issued
+     *
+     * @var unknown_type
+     */
+    protected $_rcpt = false;
+
+
+    /**
+     * Indicates that DATA has been issued and sent
+     *
+     * @var unknown_type
+     */
+    protected $_data = null;
+
+
+    /**
+     * Constructor.
+     *
+     * @param  string  $host
+     * @param  integer $port
+     * @param  array   $config
+     * @return void
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function __construct($host = '127.0.0.1', $port = null, array $config = array())
+    {
+        if (isset($config['ssl'])) {
+            switch (strtolower($config['ssl'])) {
+                case 'tls':
+                    $this->_secure = 'tls';
+                    break;
+
+                case 'ssl':
+                    $this->_transport = 'ssl';
+                    $this->_secure = 'ssl';
+                    if ($port == null) {
+                        $port = 465;
+                    }
+                    break;
+
+                default:
+                    /**
+                     * @see Zend_Mail_Protocol_Exception
+                     */
+                    require_once 'Zend/Mail/Protocol/Exception.php';
+                    throw new Zend_Mail_Protocol_Exception($config['ssl'] . ' is unsupported SSL type');
+                    break;
+            }
+        }
+
+        // If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null.
+        if ($port == null) {
+            if (($port = ini_get('smtp_port')) == '') {
+                $port = 25;
+            }
+        }
+
+        parent::__construct($host, $port);
+    }
+
+
+    /**
+     * Connect to the server with the parameters given in the constructor.
+     *
+     * @return boolean
+     */
+    public function connect()
+    {
+        return $this->_connect($this->_transport . '://' . $this->_host . ':'. $this->_port);
+    }
+
+
+    /**
+     * Initiate HELO/EHLO sequence and set flag to indicate valid smtp session
+     *
+     * @param  string $host The client hostname or IP address (default: 127.0.0.1)
+     * @throws Zend_Mail_Protocol_Exception
+     * @return void
+     */
+    public function helo($host = '127.0.0.1')
+    {
+        // Respect RFC 2821 and disallow HELO attempts if session is already initiated.
+        if ($this->_sess === true) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('Cannot issue HELO to existing session');
+        }
+
+        // Validate client hostname
+        if (!$this->_validHost->isValid($host)) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessage()));
+        }
+
+        // Initiate helo sequence
+        $this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
+        $this->_ehlo($host);
+
+        // If a TLS session is required, commence negotiation
+        if ($this->_secure == 'tls') {
+            $this->_send('STARTTLS');
+            $this->_expect(220, 180);
+            if (!stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
+                /**
+                 * @see Zend_Mail_Protocol_Exception
+                 */
+                require_once 'Zend/Mail/Protocol/Exception.php';
+                throw new Zend_Mail_Protocol_Exception('Unable to connect via TLS');
+            }
+            $this->_ehlo($host);
+        }
+
+        $this->_startSession();
+        $this->auth();
+    }
+
+
+    /**
+     * Send EHLO or HELO depending on capabilities of smtp host
+     *
+     * @param  string $host The client hostname or IP address (default: 127.0.0.1)
+     * @throws Zend_Mail_Protocol_Exception
+     * @return void
+     */
+    protected function _ehlo($host)
+    {
+        // Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO.
+        try {
+            $this->_send('EHLO ' . $host);
+            $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
+        } catch (Zend_Mail_Protocol_Exception $e) {
+            $this->_send('HELO ' . $host);
+            $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
+        } catch (Zend_Mail_Protocol_Exception $e) {
+            throw $e;
+        }
+    }
+
+
+    /**
+     * Issues MAIL command
+     *
+     * @param  string $from Sender mailbox
+     * @throws Zend_Mail_Protocol_Exception
+     * @return void
+     */
+    public function mail($from)
+    {
+        if ($this->_sess !== true) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('A valid session has not been started');
+        }
+
+        $this->_send('MAIL FROM:<' . $from . '>');
+        $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
+
+        // Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821
+        $this->_mail = true;
+        $this->_rcpt = false;
+        $this->_data = false;
+    }
+
+
+    /**
+     * Issues RCPT command
+     *
+     * @param  string $to Receiver(s) mailbox
+     * @throws Zend_Mail_Protocol_Exception
+     * @return void
+     */
+    public function rcpt($to)
+    {
+        if ($this->_mail !== true) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('No sender reverse path has been supplied');
+        }
+
+        // Set rcpt to true, as per 4.1.1.3 of RFC 2821
+        $this->_send('RCPT TO:<' . $to . '>');
+        $this->_expect(array(250, 251), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
+        $this->_rcpt = true;
+    }
+
+
+    /**
+     * Issues DATA command
+     *
+     * @param  string $data
+     * @throws Zend_Mail_Protocol_Exception
+     * @return void
+     */
+    public function data($data)
+    {
+        // Ensure recipients have been set
+        if ($this->_rcpt !== true) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('No recipient forward path has been supplied');
+        }
+
+        $this->_send('DATA');
+        $this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2
+
+        foreach (explode(Zend_Mime::LINEEND, $data) as $line) {
+            if (strpos($line, '.') === 0) {
+                // Escape lines prefixed with a '.'
+                $line = '.' . $line;
+            }
+            $this->_send($line);
+        }
+
+        $this->_send('.');
+        $this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2
+        $this->_data = true;
+    }
+
+
+    /**
+     * Issues the RSET command end validates answer
+     *
+     * Can be used to restore a clean smtp communication state when a transaction has been cancelled or commencing a new transaction.
+     *
+     * @return void
+     */
+    public function rset()
+    {
+        $this->_send('RSET');
+        // MS ESMTP doesn't follow RFC, see [ZF-1377]
+        $this->_expect(array(250, 220));
+
+        $this->_mail = false;
+        $this->_rcpt = false;
+        $this->_data = false;
+    }
+
+
+    /**
+     * Issues the NOOP command end validates answer
+     *
+     * Not used by Zend_Mail, could be used to keep a connection alive or check if it is still open.
+     *
+     * @return void
+     */
+    public function noop()
+    {
+        $this->_send('NOOP');
+        $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
+    }
+
+
+    /**
+     * Issues the VRFY command end validates answer
+     *
+     * Not used by Zend_Mail.
+     *
+     * @param  string $user User Name or eMail to verify
+     * @return void
+     */
+    public function vrfy($user)
+    {
+        $this->_send('VRFY ' . $user);
+        $this->_expect(array(250, 251, 252), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
+    }
+
+
+    /**
+     * Issues the QUIT command and clears the current session
+     *
+     * @return void
+     */
+    public function quit()
+    {
+        if ($this->_sess) {
+            $this->_send('QUIT');
+            $this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
+            $this->_stopSession();
+        }
+    }
+
+
+    /**
+     * Default authentication method
+     *
+     * This default method is implemented by AUTH adapters to properly authenticate to a remote host.
+     *
+     * @throws Zend_Mail_Protocol_Exception
+     * @return void
+     */
+    public function auth()
+    {
+        if ($this->_auth === true) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('Already authenticated for this session');
+        }
+    }
+
+
+    /**
+     * Closes connection
+     *
+     * @return void
+     */
+    public function disconnect()
+    {
+        $this->_disconnect();
+    }
+
+
+    /**
+     * Start mail session
+     *
+     * @return void
+     */
+    protected function _startSession()
+    {
+        $this->_sess = true;
+    }
+
+
+    /**
+     * Stop mail session
+     *
+     * @return void
+     */
+    protected function _stopSession()
+    {
+        $this->_sess = false;
+    }
+}
Index: libs/Zend/Mail/Protocol/Imap.php
===================================================================
--- libs/Zend/Mail/Protocol/Imap.php	(wersja 0)
+++ libs/Zend/Mail/Protocol/Imap.php	(wersja 0)
@@ -0,0 +1,805 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Imap.php 8928 2008-03-20 19:41:41Z thomas $
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Protocol
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Protocol_Imap
+{
+    /**
+     * socket to imap server
+     * @var resource|null
+     */
+    protected $_socket;
+
+    /**
+     * counter for request tag
+     * @var int
+     */
+    protected $_tagCount = 0;
+
+
+    /**
+     * Public constructor
+     *
+     * @param  string   $host  hostname of IP address of IMAP server, if given connect() is called
+     * @param  int|null $port  port of IMAP server, null for default (143 or 993 for ssl)
+     * @param  bool     $ssl   use ssl? 'SSL', 'TLS' or false
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    function __construct($host = '', $port = null, $ssl = false)
+    {
+        if ($host) {
+            $this->connect($host, $port, $ssl);
+        }
+    }
+
+    /**
+     * Public destructor
+     */
+    public function __destruct()
+    {
+        $this->logout();
+    }
+
+    /**
+     * Open connection to POP3 server
+     *
+     * @param  string      $host  hostname of IP address of POP3 server
+     * @param  int|null    $port  of IMAP server, default is 143 (993 for ssl)
+     * @param  string|bool $ssl   use 'SSL', 'TLS' or false
+     * @return string welcome message
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function connect($host, $port = null, $ssl = false)
+    {
+        if ($ssl == 'SSL') {
+            $host = 'ssl://' . $host;
+        }
+
+        if ($port === null) {
+            $port = $ssl === 'SSL' ? 993 : 143;
+        }
+
+        $this->_socket = @fsockopen($host, $port);
+        if (!$this->_socket) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('cannot connect to host');
+        }
+
+        if (!$this->_assumedNextLine('* OK')) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('host doesn\'t allow connection');
+        }
+
+        if ($ssl === 'TLS') {
+            $result = $this->requestAndResponse('STARTTLS');
+            $result = $result && stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
+            if (!$result) {
+                /**
+                 * @see Zend_Mail_Protocol_Exception
+                 */
+                require_once 'Zend/Mail/Protocol/Exception.php';
+                throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
+            }
+        }
+    }
+
+    /**
+     * get the next line from socket with error checking, but nothing else
+     *
+     * @return string next line
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    protected function _nextLine()
+    {
+        $line = @fgets($this->_socket);
+        if ($line === false) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('cannot read - connection closed?');
+        }
+
+        return $line;
+    }
+
+    /**
+     * get next line and assume it starts with $start. some requests give a simple
+     * feedback so we can quickly check if we can go on.
+     *
+     * @param  string $start the first bytes we assume to be in the next line
+     * @return bool line starts with $start
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    protected function _assumedNextLine($start)
+    {
+        $line = $this->_nextLine();
+        return strpos($line, $start) === 0;
+    }
+
+    /**
+     * get next line and split the tag. that's the normal case for a response line
+     *
+     * @param  string $tag tag of line is returned by reference
+     * @return string next line
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    protected function _nextTaggedLine(&$tag)
+    {
+        $line = $this->_nextLine();
+
+        // seperate tag from line
+        list($tag, $line) = explode(' ', $line, 2);
+
+        return $line;
+    }
+
+    /**
+     * split a given line in tokens. a token is literal of any form or a list
+     *
+     * @param  string $line line to decode
+     * @return array tokens, literals are returned as string, lists as array
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    protected function _decodeLine($line)
+    {
+        $tokens = array();
+        $stack = array();
+
+        /*
+            We start to decode the response here. The unterstood tokens are:
+                literal
+                "literal" or also "lit\\er\"al"
+                {bytes}<NL>literal
+                (literals*)
+            All tokens are returned in an array. Literals in braces (the last unterstood
+            token in the list) are returned as an array of tokens. I.e. the following response:
+                "foo" baz {3}<NL>bar ("f\\\"oo" bar)
+            would be returned as:
+                array('foo', 'baz', 'bar', array('f\\\"oo', 'bar'));
+                
+            // TODO: add handling of '[' and ']' to parser for easier handling of response text 
+        */
+        //  replace any trailling <NL> including spaces with a single space
+        $line = rtrim($line) . ' ';
+        while (($pos = strpos($line, ' ')) !== false) {
+            $token = substr($line, 0, $pos);
+            while ($token[0] == '(') {
+                array_push($stack, $tokens);
+                $tokens = array();
+                $token = substr($token, 1);
+            }
+            if ($token[0] == '"') {
+                if (preg_match('%^"((.|\\\\|\\")*?)" *%', $line, $matches)) {
+                    $tokens[] = $matches[1];
+                    $line = substr($line, strlen($matches[0]));
+                    continue;
+                }
+            }
+            if ($token[0] == '{') {
+                $endPos = strpos($token, '}');
+                $chars = substr($token, 1, $endPos - 1);
+                if (is_numeric($chars)) {
+                    $token = '';
+                    while (strlen($token) < $chars) {
+                        $token .= $this->_nextLine();
+                    }
+                    $line = '';
+                    if (strlen($token) > $chars) {
+                        $line = substr($token, $chars);
+                        $token = substr($token, 0, $chars);
+                    } else {
+                        $line .= $this->_nextLine();
+                    }
+                    $tokens[] = $token;
+                    $line = trim($line) . ' ';
+                    continue;
+                }
+            }
+            if ($stack && $token[strlen($token) - 1] == ')') {
+                // closing braces are not seperated by spaces, so we need to count them
+                $braces = strlen($token);
+                $token = rtrim($token, ')');
+                // only count braces if more than one
+                $braces -= strlen($token) + 1;
+                // only add if token had more than just closing braces
+                if ($token) {
+                    $tokens[] = $token;
+                }
+                $token = $tokens;
+                $tokens = array_pop($stack);
+                // special handline if more than one closing brace
+                while ($braces-- > 0) {
+                    $tokens[] = $token;
+                    $token = $tokens;
+                    $tokens = array_pop($stack);
+                }
+            }
+            $tokens[] = $token;
+            $line = substr($line, $pos + 1);
+        }
+
+        // maybe the server forgot to send some closing braces
+        while ($stack) {
+            $child = $tokens;
+            $tokens = array_pop($stack);
+            $tokens[] = $child;
+        }
+
+        return $tokens;
+    }
+
+    /**
+     * read a response "line" (could also be more than one real line if response has {..}<NL>)
+     * and do a simple decode
+     *
+     * @param  array|string  $tokens    decoded tokens are returned by reference, if $dontParse
+     *                                  is true the unparsed line is returned here
+     * @param  string        $wantedTag check for this tag for response code. Default '*' is
+     *                                  continuation tag.
+     * @param  bool          $dontParse if true only the unparsed line is returned $tokens
+     * @return bool if returned tag matches wanted tag
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function readLine(&$tokens = array(), $wantedTag = '*', $dontParse = false)
+    {
+        $line = $this->_nextTaggedLine($tag);
+        if (!$dontParse) {
+            $tokens = $this->_decodeLine($line);
+        } else {
+            $tokens = $line;
+        }
+
+        // if tag is wanted tag we might be at the end of a multiline response
+        return $tag == $wantedTag;
+    }
+
+    /**
+     * read all lines of response until given tag is found (last line of response)
+     *
+     * @param  string       $tag       the tag of your request
+     * @param  string|array $filter    you can filter the response so you get only the
+     *                                 given response lines
+     * @param  bool         $dontParse if true every line is returned unparsed instead of
+     *                                 the decoded tokens
+     * @return null|bool|array tokens if success, false if error, null if bad request
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function readResponse($tag, $dontParse = false)
+    {
+        $lines = array();
+        while (!$this->readLine($tokens, $tag, $dontParse)) {
+            $lines[] = $tokens;
+        }
+
+        if ($dontParse) {
+            // last to chars are still needed for response code
+            $tokens = array(substr($tokens, 0, 2));
+        }
+        // last line has response code
+        if ($tokens[0] == 'OK') {
+            return $lines ? $lines : true;
+        } else if ($tokens[0] == 'NO'){
+            return false;
+        }
+        return null;
+    }
+
+    /**
+     * send a request
+     *
+     * @param  string $command your request command
+     * @param  array  $tokens  additional parameters to command, use escapeString() to prepare
+     * @param  string $tag     provide a tag otherwise an autogenerated is returned
+     * @return null
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function sendRequest($command, $tokens = array(), &$tag = null)
+    {
+        if (!$tag) {
+            ++$this->_tagCount;
+            $tag = 'TAG' . $this->_tagCount;
+        }
+
+        $line = $tag . ' ' . $command;
+
+        foreach ($tokens as $token) {
+            if (is_array($token)) {
+                if (@fputs($this->_socket, $line . ' ' . $token[0] . "\r\n") === false) {
+                    /**
+                     * @see Zend_Mail_Protocol_Exception
+                     */
+                    require_once 'Zend/Mail/Protocol/Exception.php';
+                    throw new Zend_Mail_Protocol_Exception('cannot write - connection closed?');
+                }
+                if (!$this->_assumedNextLine('+ OK')) {
+                    /**
+                     * @see Zend_Mail_Protocol_Exception
+                     */
+                    require_once 'Zend/Mail/Protocol/Exception.php';
+                    throw new Zend_Mail_Protocol_Exception('cannot send literal string');
+                }
+                $line = $token[1];
+            } else {
+                $line .= ' ' . $token;
+            }
+        }
+
+        if (@fputs($this->_socket, $line . "\r\n") === false) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('cannot write - connection closed?');
+        }
+    }
+
+    /**
+     * send a request and get response at once
+     *
+     * @param  string $command   command as in sendRequest()
+     * @param  array  $tokens    parameters as in sendRequest()
+     * @param  bool   $dontParse if true unparsed lines are returned instead of tokens
+     * @return mixed response as in readResponse()
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function requestAndResponse($command, $tokens = array(), $dontParse = false)
+    {
+        $this->sendRequest($command, $tokens, $tag);
+        $response = $this->readResponse($tag, $dontParse);
+
+        return $response;
+    }
+
+    /**
+     * escape one or more literals i.e. for sendRequest
+     *
+     * @param  string|array $string the literal/-s
+     * @return string|array escape literals, literals with newline ar returned
+     *                      as array('{size}', 'string');
+     */
+    public function escapeString($string)
+    {
+        if (func_num_args() < 2) {
+            if (strpos($string, "\n") !== false) {
+                return array('{' . strlen($string) . '}', $string);
+            } else {
+                return '"' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $string) . '"';
+            }
+        }
+        $result = array();
+        foreach (func_get_args() as $string) {
+            $result[] = $this->escapeString($string);
+        }
+        return $result;
+    }
+
+    /**
+     * escape a list with literals or lists
+     *
+     * @param  array $list list with literals or lists as PHP array
+     * @return string escaped list for imap
+     */
+    public function escapeList($list)
+    {
+        $result = array();
+        foreach ($list as $k => $v) {
+            if (!is_array($v)) {
+//              $result[] = $this->escapeString($v);
+                $result[] = $v;
+                continue;
+            }
+            $result[] = $this->escapeList($v);
+        }
+        return '(' . implode(' ', $result) . ')';
+    }
+
+    /**
+     * Login to IMAP server.
+     *
+     * @param  string $user      username
+     * @param  string $password  password
+     * @return bool success
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function login($user, $password)
+    {
+        return $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true);
+    }
+
+    /**
+     * logout of imap server
+     *
+     * @return bool success
+     */
+    public function logout()
+    {
+        $result = false;
+        if ($this->_socket) {
+            try {
+                $result = $this->requestAndResponse('LOGOUT', array(), true);
+            } catch (Zend_Mail_Protocol_Exception $e) {
+                // ignoring exception
+            }
+            fclose($this->_socket);
+            $this->_socket = null;
+        }
+        return $result;
+    }
+
+
+    /**
+     * Get capabilities from IMAP server
+     *
+     * @return array list of capabilities
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function capability()
+    {
+        $response = $this->requestAndResponse('CAPABILITY');
+
+        if (!$response) {
+            return $response;
+        }
+
+        $capabilities = array();
+        foreach ($response as $line) {
+            $capabilities = array_merge($capabilities, $line);
+        }
+        return $capabilities;
+    }
+
+    /**
+     * Examine and select have the same response. The common code for both
+     * is in this method
+     *
+     * @param  string $command can be 'EXAMINE' or 'SELECT' and this is used as command
+     * @param  string $box which folder to change to or examine
+     * @return bool|array false if error, array with returned information
+     *                    otherwise (flags, exists, recent, uidvalidity)
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function examineOrSelect($command = 'EXAMINE', $box = 'INBOX')
+    {
+        $this->sendRequest($command, array($this->escapeString($box)), $tag);
+
+        $result = array();
+        while (!$this->readLine($tokens, $tag)) {
+            if ($tokens[0] == 'FLAGS') {
+                array_shift($tokens);
+                $result['flags'] = $tokens;
+                continue;
+            }
+            switch ($tokens[1]) {
+                case 'EXISTS':
+                case 'RECENT':
+                    $result[strtolower($tokens[1])] = $tokens[0];
+                    break;
+                case '[UIDVALIDITY':
+                    $result['uidvalidity'] = (int)$tokens[2];
+                    break;
+                default:
+                    // ignore
+            }
+        }
+
+        if ($tokens[0] != 'OK') {
+            return false;
+        }
+        return $result;
+    }
+
+    /**
+     * change folder
+     *
+     * @param  string $box change to this folder
+     * @return bool|array see examineOrselect()
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function select($box = 'INBOX')
+    {
+        return $this->examineOrSelect('SELECT', $box);
+    }
+
+    /**
+     * examine folder
+     *
+     * @param  string $box examine this folder
+     * @return bool|array see examineOrselect()
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function examine($box = 'INBOX')
+    {
+        return $this->examineOrSelect('EXAMINE', $box);
+    }
+
+    /**
+     * fetch one or more items of one or more messages
+     *
+     * @param  string|array $items items to fetch from message(s) as string (if only one item)
+     *                             or array of strings
+     * @param  int          $from  message for items or start message if $to !== null
+     * @param  int|null     $to    if null only one message ($from) is fetched, else it's the
+     *                             last message, INF means last message avaible
+     * @return string|array if only one item of one message is fetched it's returned as string
+     *                      if items of one message are fetched it's returned as (name => value)
+     *                      if one items of messages are fetched it's returned as (msgno => value)
+     *                      if items of messages are fetchted it's returned as (msgno => (name => value))
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function fetch($items, $from, $to = null)
+    {
+        if (is_array($from)) {
+            $set = implode(',', $from);
+        } else if ($to === null) {
+            $set = (int)$from;
+        } else if ($to === INF) {
+            $set = (int)$from . ':*';
+        } else {
+            $set = (int)$from . ':' . (int)$to;
+        }
+
+        $items = (array)$items;
+        $itemList = $this->escapeList($items);
+
+        $this->sendRequest('FETCH', array($set, $itemList), $tag);
+
+        $result = array();
+        while (!$this->readLine($tokens, $tag)) {
+            // ignore other responses
+            if ($tokens[1] != 'FETCH') {
+                continue;
+            }
+            // ignore other messages
+            if ($to === null && !is_array($from) && $tokens[0] != $from) {
+                continue;
+            }
+            // if we only want one item we return that one directly
+            if (count($items) == 1) {
+                if ($tokens[2][0] == $items[0]) {
+                    $data = $tokens[2][1];
+                } else {
+                    // maybe the server send an other field we didn't wanted
+                    $count = count($tokens[2]);
+                    // we start with 2, because 0 was already checked
+                    for ($i = 2; $i < $count; $i += 2) {
+                        if ($tokens[2][$i] != $items[0]) {
+                            continue;
+                        }
+                        $data = $tokens[2][$i + 1];
+                        break;
+                    }
+                }
+            } else {
+                $data = array();
+                while (key($tokens[2]) !== null) {
+                    $data[current($tokens[2])] = next($tokens[2]);
+                    next($tokens[2]);
+                }
+            }
+            // if we want only one message we can ignore everything else and just return
+            if ($to === null && !is_array($from) && $tokens[0] == $from) {
+                // we still need to read all lines
+                while (!$this->readLine($tokens, $tag));
+                return $data;
+            }
+            $result[$tokens[0]] = $data;
+        }
+
+        if ($to === null && !is_array($from)) {
+            /**
+             * @see Zend_Mail_Protocol_Exception
+             */
+            require_once 'Zend/Mail/Protocol/Exception.php';
+            throw new Zend_Mail_Protocol_Exception('the single id was not found in response');
+        }
+
+        return $result;
+    }
+
+    /**
+     * get mailbox list
+     *
+     * this method can't be named after the IMAP command 'LIST', as list is a reserved keyword
+     *
+     * @param  string $reference mailbox reference for list
+     * @param  string $mailbox   mailbox name match with wildcards
+     * @return array mailboxes that matched $mailbox as array(globalName => array('delim' => .., 'flags' => ..))
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function listMailbox($reference = '', $mailbox = '*')
+    {
+        $result = array();
+        $list = $this->requestAndResponse('LIST', $this->escapeString($reference, $mailbox));
+        if (!$list) {
+            return $result;
+        }
+
+        foreach ($list as $item) {
+            if (count($item) != 4 || $item[0] != 'LIST') {
+                continue;
+            }
+            $result[$item[3]] = array('delim' => $item[2], 'flags' => $item[1]);
+        }
+
+        return $result;
+    }
+
+    /**
+     * set flags
+     *
+     * @param  array       $flags  flags to set, add or remove - see $mode
+     * @param  int         $from   message for items or start message if $to !== null
+     * @param  int|null    $to     if null only one message ($from) is fetched, else it's the
+     *                             last message, INF means last message avaible
+     * @param  string|null $mode   '+' to add flags, '-' to remove flags, everything else sets the flags as given
+     * @param  bool        $silent if false the return values are the new flags for the wanted messages
+     * @return bool|array new flags if $silent is false, else true or false depending on success
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function store(array $flags, $from, $to = null, $mode = null, $silent = true)
+    {
+        $item = 'FLAGS';
+        if ($mode == '+' || $mode == '-') {
+            $item = $mode . $item;
+        }
+        if ($silent) {
+            $item .= '.SILENT';
+        }
+
+        $flags = $this->escapeList($flags);
+        $set = (int)$from;
+        if ($to != null) {
+            $set .= ':' . ($to == INF ? '*' : (int)$to);
+        }
+
+        $result = $this->requestAndResponse('STORE', array($set, $item, $flags), $silent);
+
+        if ($silent) {
+            return $result ? true : false;
+        }
+
+        $tokens = $result;
+        $result = array();
+        foreach ($tokens as $token) {
+            if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') {
+                continue;
+            }
+            $result[$token[0]] = $token[2][1];
+        }
+
+        return $result;
+    }
+
+    /**
+     * append a new message to given folder
+     *
+     * @param string $folder  name of target folder
+     * @param string $message full message content
+     * @param array  $flags   flags for new message
+     * @param string $date    date for new message
+     * @return bool success
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function append($folder, $message, $flags = null, $date = null)
+    {
+        $tokens = array();
+        $tokens[] = $this->escapeString($folder);
+        if ($flags !== null) {
+            $tokens[] = $this->escapeList($flags);
+        }
+        if ($date !== null) {
+            $tokens[] = $this->escapeString($date);
+        }
+        $tokens[] = $this->escapeString($message);
+
+        return $this->requestAndResponse('APPEND', $tokens, true);
+    }
+
+    /**
+     * copy message set from current folder to other folder
+     *
+     * @param string   $folder destination folder
+     * @param int|null $to     if null only one message ($from) is fetched, else it's the
+     *                         last message, INF means last message avaible
+     * @return bool success
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function copy($folder, $from, $to = null)
+    {
+        $set = (int)$from;
+        if ($to != null) {
+            $set .= ':' . ($to == INF ? '*' : (int)$to);
+        }
+
+        return $this->requestAndResponse('COPY', array($set, $this->escapeString($folder)), true);
+    }
+
+    /**
+     * create a new folder (and parent folders if needed)
+     *
+     * @param string $folder folder name
+     * @return bool success
+     */
+    public function create($folder)
+    {
+        return $this->requestAndResponse('CREATE', array($this->escapeString($folder)), true);
+    }
+
+    /**
+     * rename an existing folder
+     *
+     * @param string $old old name
+     * @param string $new new name
+     * @return bool success
+     */
+    public function rename($old, $new)
+    {
+        return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true);
+    }
+
+    /**
+     * remove a folder
+     *
+     * @param string $folder folder name
+     * @return bool success
+     */
+    public function delete($folder)
+    {
+        return $this->requestAndResponse('DELETE', array($this->escapeString($folder)), true);
+    }
+
+    /**
+     * permanently remove messages
+     *
+     * @return bool success
+     */
+    public function expunge()
+    {
+        // TODO: parse response?
+        return $this->requestAndResponse('EXPUNGE');
+    }
+
+    /**
+     * send noop
+     *
+     * @return bool success
+     */
+    public function noop()
+    {
+        // TODO: parse response
+        return $this->requestAndResponse('NOOP');
+    }
+}
Index: libs/Zend/Mail/Storage/Folder.php
===================================================================
--- libs/Zend/Mail/Storage/Folder.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Folder.php	(wersja 0)
@@ -0,0 +1,236 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Folder.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Folder implements RecursiveIterator
+{
+    /**
+     * subfolders of folder array(localName => Zend_Mail_Storage_Folder folder)
+     * @var array
+     */
+    protected $_folders;
+
+    /**
+     * local name (name of folder in parent folder)
+     * @var string
+     */
+    protected $_localName;
+
+    /**
+     * global name (absolute name of folder)
+     * @var string
+     */
+    protected $_globalName;
+
+    /**
+     * folder is selectable if folder is able to hold messages, else it's just a parent folder
+     * @var bool
+     */
+    protected $_selectable = true;
+
+    /**
+     * create a new mail folder instance
+     *
+     * @param string $localName  name of folder in current subdirectory
+     * @param string $globalName absolute name of folder
+     * @param bool   $selectable if true folder holds messages, if false it's just a parent for subfolders
+     * @param array  $folders    init with given instances of Zend_Mail_Storage_Folder as subfolders
+     */
+    public function __construct($localName, $globalName = '', $selectable = true, array $folders = array())
+    {
+        $this->_localName  = $localName;
+        $this->_globalName = $globalName ? $globalName : $localName;
+        $this->_selectable = $selectable;
+        $this->_folders    = $folders;
+    }
+
+    /**
+     * implements RecursiveIterator::hasChildren()
+     *
+     * @return bool current element has children
+     */
+    public function hasChildren()
+    {
+        $current = $this->current();
+        return $current && $current instanceof Zend_Mail_Storage_Folder && !$current->isLeaf();
+    }
+
+    /**
+     * implements RecursiveIterator::getChildren()
+     *
+     * @return Zend_Mail_Storage_Folder same as self::current()
+     */
+    public function getChildren()
+    {
+        return $this->current();
+    }
+
+    /**
+     * implements Iterator::valid()
+     *
+     * @return bool check if there's a current element
+     */
+    public function valid()
+    {
+        return key($this->_folders) !== null;
+    }
+
+    /**
+     * implements Iterator::next()
+     *
+     * @return null
+     */
+    public function next()
+    {
+        next($this->_folders);
+    }
+
+    /**
+     * implements Iterator::key()
+     *
+     * @return string key/local name of current element
+     */
+    public function key()
+    {
+        return key($this->_folders);
+    }
+
+    /**
+     * implements Iterator::current()
+     *
+     * @return Zend_Mail_Storage_Folder current folder
+     */
+    public function current()
+    {
+        return current($this->_folders);
+    }
+
+    /**
+     * implements Iterator::rewind()
+     *
+     * @return null
+     */
+    public function rewind()
+    {
+        reset($this->_folders);
+    }
+
+    /**
+     * get subfolder named $name
+     *
+     * @param  string $name wanted subfolder
+     * @return Zend_Mail_Storage_Folder folder named $folder
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function __get($name)
+    {
+        if (!isset($this->_folders[$name])) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception("no subfolder named $name");
+        }
+
+        return $this->_folders[$name];
+    }
+
+    /**
+     * add or replace subfolder named $name
+     *
+     * @param string $name local name of subfolder
+     * @param Zend_Mail_Storage_Folder $folder instance for new subfolder
+     * @return null
+     */
+    public function __set($name, Zend_Mail_Storage_Folder $folder)
+    {
+        $this->_folders[$name] = $folder;
+    }
+
+    /**
+     * remove subfolder named $name
+     *
+     * @param string $name local name of subfolder
+     * @return null
+     */
+    public function __unset($name)
+    {
+        unset($this->_folders[$name]);
+    }
+
+    /**
+     * magic method for easy output of global name
+     *
+     * @return string global name of folder
+     */
+    public function __toString()
+    {
+        return (string)$this->getGlobalName();
+    }
+
+    /**
+     * get local name
+     *
+     * @return string local name
+     */
+    public function getLocalName()
+    {
+        return $this->_localName;
+    }
+
+    /**
+     * get global name
+     *
+     * @return string global name
+     */
+    public function getGlobalName()
+    {
+        return $this->_globalName;
+    }
+
+    /**
+     * is this folder selectable?
+     *
+     * @return bool selectable
+     */
+    public function isSelectable()
+    {
+        return $this->_selectable;
+    }
+
+    /**
+     * check if folder has no subfolder
+     *
+     * @return bool true if no subfolders
+     */
+    public function isLeaf()
+    {
+        return empty($this->_folders);
+    }
+}
Index: libs/Zend/Mail/Storage/Exception.php
===================================================================
--- libs/Zend/Mail/Storage/Exception.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Exception.php	(wersja 0)
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Exception
+ */
+require_once 'Zend/Mail/Exception.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Exception extends Zend_Mail_Exception
+{}
+
Index: libs/Zend/Mail/Storage/Maildir.php
===================================================================
--- libs/Zend/Mail/Storage/Maildir.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Maildir.php	(wersja 0)
@@ -0,0 +1,425 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Maildir.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Storage_Abstract
+ */
+require_once 'Zend/Mail/Storage/Abstract.php';
+
+/**
+ * @see Zend_Mail_Message
+ */
+require_once 'Zend/Mail/Message.php';
+
+/**
+ * @see Zend_Mail_Storage
+ */
+require_once 'Zend/Mail/Storage.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
+{
+    /**
+     * data of found message files in maildir dir
+     * @var array
+     */
+    protected $_files = array();
+
+    /**
+     * known flag chars in filenames
+     *
+     * This list has to be in alphabetical order for setFlags()
+     *
+     * @var array
+     */
+    protected static $_knownFlags = array('D' => Zend_Mail_Storage::FLAG_DRAFT,
+                                          'F' => Zend_Mail_Storage::FLAG_FLAGGED,
+                                          'P' => Zend_Mail_Storage::FLAG_PASSED,
+                                          'R' => Zend_Mail_Storage::FLAG_ANSWERED,
+                                          'S' => Zend_Mail_Storage::FLAG_SEEN,
+                                          'T' => Zend_Mail_Storage::FLAG_DELETED);
+
+    /**
+     * Count messages all messages in current box
+     *
+     * @return int number of messages
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function countMessages()
+    {
+        return count($this->_files);
+    }
+
+    /**
+     * Get one or all fields from file structure. Also checks if message is valid
+     *
+     * @param  int         $id    message number
+     * @param  string|null $field wanted field
+     * @return string|array wanted field or all fields as array
+     * @throws Zend_Mail_Storage_Exception
+     */
+    protected function _getFileData($id, $field = null)
+    {
+        if (!isset($this->_files[$id - 1])) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('id does not exist');
+        }
+
+        if (!$field) {
+            return $this->_files[$id - 1];
+        }
+
+        if (!isset($this->_files[$id - 1][$field])) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('field does not exist');
+        }
+
+        return $this->_files[$id - 1][$field];
+    }
+
+    /**
+     * Get a list of messages with number and size
+     *
+     * @param  int|null $id number of message or null for all messages
+     * @return int|array size of given message of list with all messages as array(num => size)
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getSize($id = null)
+    {
+        if ($id !== null) {
+            return filesize($this->_getFileData($id, 'filename'));
+        }
+
+        $result = array();
+        foreach ($this->_files as $num => $pos) {
+            $result[$num + 1] = filesize($this->_files[$num]['filename']);
+        }
+
+        return $result;
+    }
+
+
+
+    /**
+     * Fetch a message
+     *
+     * @param  int $id number of message
+     * @return Zend_Mail_Message
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getMessage($id)
+    {
+        return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $this->getRawHeader($id),
+                                              'flags'   => $this->_getFileData($id, 'flags')));
+    }
+
+    /*
+     * Get raw header of message or part
+     *
+     * @param  int               $id       number of message
+     * @param  null|array|string $part     path to part or null for messsage header
+     * @param  int               $topLines include this many lines with header (after an empty line)
+     * @return string raw header
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getRawHeader($id, $part = null, $topLines = 0)
+    {
+        if ($part !== null) {
+            // TODO: implement
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('not implemented');
+        }
+
+        $fh = fopen($this->_getFileData($id, 'filename'), 'r');
+
+        $content = '';
+        while (!feof($fh)) {
+            $line = fgets($fh);
+            if (!trim($line)) {
+                break;
+            }
+            $content .= $line;
+        }
+
+        fclose($fh);
+        return $content;
+    }
+
+    /*
+     * Get raw content of message or part
+     *
+     * @param  int               $id   number of message
+     * @param  null|array|string $part path to part or null for messsage content
+     * @return string raw content
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getRawContent($id, $part = null)
+    {
+        if ($part !== null) {
+            // TODO: implement
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('not implemented');
+        }
+
+        $fh = fopen($this->_getFileData($id, 'filename'), 'r');
+
+        while (!feof($fh)) {
+            $line = fgets($fh);
+            if (!trim($line)) {
+                break;
+            }
+        }
+
+        $content = stream_get_contents($fh);
+        fclose($fh);
+        return $content;
+    }
+
+    /**
+     * Create instance with parameters
+     * Supported parameters are:
+     *   - dirname dirname of mbox file
+     *
+     * @param  $params array mail reader specific parameters
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function __construct($params)
+    {
+        if (is_array($params)) {
+            $params = (object)$params;
+        }
+
+        if (!isset($params->dirname) || !is_dir($params->dirname)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('no valid dirname given in params');
+        }
+
+        if (!$this->_isMaildir($params->dirname)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('invalid maildir given');
+        }
+
+        $this->_has['top'] = true;
+        $this->_has['flags'] = true;
+        $this->_openMaildir($params->dirname);
+    }
+
+    /**
+     * check if a given dir is a valid maildir
+     *
+     * @param string $dirname name of dir
+     * @return bool dir is valid maildir
+     */
+    protected function _isMaildir($dirname)
+    {
+        if (file_exists($dirname . '/new') && !is_dir($dirname . '/new')) {
+            return false;
+        }
+        if (file_exists($dirname . '/tmp') && !is_dir($dirname . '/tmp')) {
+            return false;
+        }
+        return is_dir($dirname . '/cur');
+    }
+
+    /**
+     * open given dir as current maildir
+     *
+     * @param string $dirname name of maildir
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    protected function _openMaildir($dirname)
+    {
+        if ($this->_files) {
+            $this->close();
+        }
+
+        $dh = @opendir($dirname . '/cur/');
+        if (!$dh) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot open maildir');
+        }
+        $this->_getMaildirFiles($dh, $dirname . '/cur/');
+        closedir($dh);
+
+        $dh = @opendir($dirname . '/new/');
+        if ($dh) {
+            $this->_getMaildirFiles($dh, $dirname . '/new/', array(Zend_Mail_Storage::FLAG_RECENT));
+            closedir($dh);
+        } else if (file_exists($dirname . '/new/')) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot read recent mails in maildir');
+        }
+    }
+
+    /**
+     * find all files in opened dir handle and add to maildir files
+     *
+     * @param resource $dh            dir handle used for search
+     * @param string   $dirname       dirname of dir in $dh
+     * @param array    $default_flags default flags for given dir
+     * @return null
+     */
+    protected function _getMaildirFiles($dh, $dirname, $default_flags = array())
+    {
+        while (($entry = readdir($dh)) !== false) {
+            if ($entry[0] == '.' || !is_file($dirname . $entry)) {
+                continue;
+            }
+
+            @list($uniq, $info) = explode(':', $entry, 2);
+            @list($version, $flags) = explode(',', $info, 2);
+            if ($version != 2) {
+                $flags = '';
+            }
+
+            $named_flags = $default_flags;
+            $length = strlen($flags);
+            for ($i = 0; $i < $length; ++$i) {
+                $flag = $flags[$i];
+                $named_flags[$flag] = isset(self::$_knownFlags[$flag]) ? self::$_knownFlags[$flag] : $flag;
+            }
+
+            $this->_files[] = array('uniq'     => $uniq,
+                                    'flags'    => $named_flags,
+                                    'filename' => $dirname . $entry);
+        }
+    }
+
+
+    /**
+     * Close resource for mail lib. If you need to control, when the resource
+     * is closed. Otherwise the destructor would call this.
+     *
+     * @return void
+     */
+    public function close()
+    {
+        $this->_files = array();
+    }
+
+
+    /**
+     * Waste some CPU cycles doing nothing.
+     *
+     * @return void
+     */
+    public function noop()
+    {
+        return true;
+    }
+
+
+    /**
+     * stub for not supported message deletion
+     *
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function removeMessage($id)
+    {
+        /**
+         * @see Zend_Mail_Storage_Exception
+         */
+        require_once 'Zend/Mail/Storage/Exception.php';
+        throw new Zend_Mail_Storage_Exception('maildir is (currently) read-only');
+    }
+
+    /**
+     * get unique id for one or all messages
+     *
+     * if storage does not support unique ids it's the same as the message number
+     *
+     * @param int|null $id message number
+     * @return array|string message number for given message or all messages as array
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getUniqueId($id = null)
+    {
+        if ($id) {
+            return $this->_getFileData($id, 'uniq');
+        }
+
+        $ids = array();
+        foreach ($this->_files as $num => $file) {
+            $ids[$num + 1] = $file['uniq'];
+        }
+        return $ids;
+    }
+
+    /**
+     * get a message number from a unique id
+     *
+     * I.e. if you have a webmailer that supports deleting messages you should use unique ids
+     * as parameter and use this method to translate it to message number right before calling removeMessage()
+     *
+     * @param string $id unique id
+     * @return int message number
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getNumberByUniqueId($id)
+    {
+        foreach ($this->_files as $num => $file) {
+            if ($file['uniq'] == $id) {
+                return $num + 1;
+            }
+        }
+
+        /**
+         * @see Zend_Mail_Storage_Exception
+         */
+        require_once 'Zend/Mail/Storage/Exception.php';
+        throw new Zend_Mail_Storage_Exception('unique id not found');
+    }
+}
Index: libs/Zend/Mail/Storage/Pop3.php
===================================================================
--- libs/Zend/Mail/Storage/Pop3.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Pop3.php	(wersja 0)
@@ -0,0 +1,328 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Pop3.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Storage_Abstract
+ */
+require_once 'Zend/Mail/Storage/Abstract.php';
+
+/**
+ * @see Zend_Mail_Protocol_Pop3
+ */
+require_once 'Zend/Mail/Protocol/Pop3.php';
+
+/**
+ * @see Zend_Mail_Message
+ */
+require_once 'Zend/Mail/Message.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Pop3 extends Zend_Mail_Storage_Abstract
+{
+    /**
+     * protocol handler
+     * @var null|Zend_Mail_Protocol_Pop3
+     */
+    protected $_protocol;
+
+
+    /**
+     * Count messages all messages in current box
+     *
+     * @return int number of messages
+     * @throws Zend_Mail_Storage_Exception
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function countMessages()
+    {
+        $this->_protocol->status($count, $null);
+        return (int)$count;
+    }
+
+    /**
+     * get a list of messages with number and size
+     *
+     * @param int $id number of message
+     * @return int|array size of given message of list with all messages as array(num => size)
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function getSize($id = 0)
+    {
+        $id = $id ? $id : null;
+        return $this->_protocol->getList($id);
+    }
+
+    /**
+     * Fetch a message
+     *
+     * @param int $id number of message
+     * @return Zend_Mail_Message
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function getMessage($id)
+    {
+        $bodyLines = 0;
+        $message = $this->_protocol->top($id, $bodyLines, true);
+
+        return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $message,
+                                              'noToplines' => $bodyLines < 1));
+    }
+
+    /*
+     * Get raw header of message or part
+     *
+     * @param  int               $id       number of message
+     * @param  null|array|string $part     path to part or null for messsage header
+     * @param  int               $topLines include this many lines with header (after an empty line)
+     * @return string raw header
+     * @throws Zend_Mail_Protocol_Exception
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getRawHeader($id, $part = null, $topLines = 0)
+    {
+        if ($part !== null) {
+            // TODO: implement
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('not implemented');
+        }
+
+        return $this->_protocol->top($id, 0, true);
+    }
+
+    /*
+     * Get raw content of message or part
+     *
+     * @param  int               $id   number of message
+     * @param  null|array|string $part path to part or null for messsage content
+     * @return string raw content
+     * @throws Zend_Mail_Protocol_Exception
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getRawContent($id, $part = null)
+    {
+        if ($part !== null) {
+            // TODO: implement
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('not implemented');
+        }
+
+        $content = $this->_protocol->retrieve($id);
+        // TODO: find a way to avoid decoding the headers
+        Zend_Mime_Decode::splitMessage($content, $null, $body);
+        return $body;
+    }
+
+    /**
+     * create instance with parameters
+     * Supported paramters are
+     *   - host hostname or ip address of POP3 server
+     *   - user username
+     *   - password password for user 'username' [optional, default = '']
+     *   - port port for POP3 server [optional, default = 110]
+     *   - ssl 'SSL' or 'TLS' for secure sockets
+     *
+     * @param  $params array  mail reader specific parameters
+     * @throws Zend_Mail_Storage_Exception
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function __construct($params)
+    {
+        if (is_array($params)) {
+            $params = (object)$params;
+        }
+
+        $this->_has['fetchPart'] = false;
+        $this->_has['top']       = null;
+        $this->_has['uniqueid']  = null;
+
+        if ($params instanceof Zend_Mail_Protocol_Pop3) {
+            $this->_protocol = $params;
+            return;
+        }
+
+        if (!isset($params->user)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('need at least user in params');
+        }
+
+        $host     = isset($params->host)     ? $params->host     : 'localhost';
+        $password = isset($params->password) ? $params->password : '';
+        $port     = isset($params->port)     ? $params->port     : null;
+        $ssl      = isset($params->ssl)      ? $params->ssl      : false;
+
+        $this->_protocol = new Zend_Mail_Protocol_Pop3();
+        $this->_protocol->connect($host, $port, $ssl);
+        $this->_protocol->login($params->user, $password);
+    }
+
+    /**
+     * Close resource for mail lib. If you need to control, when the resource
+     * is closed. Otherwise the destructor would call this.
+     *
+     * @return null
+     */
+    public function close()
+    {
+        $this->_protocol->logout();
+    }
+
+    /**
+     * Keep the server busy.
+     *
+     * @return null
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function noop()
+    {
+        return $this->_protocol->noop();
+    }
+
+    /**
+     * Remove a message from server. If you're doing that from a web enviroment
+     * you should be careful and use a uniqueid as parameter if possible to
+     * identify the message.
+     *
+     * @param  int $id number of message
+     * @return null
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function removeMessage($id)
+    {
+        $this->_protocol->delete($id);
+    }
+
+    /**
+     * get unique id for one or all messages
+     *
+     * if storage does not support unique ids it's the same as the message number
+     *
+     * @param int|null $id message number
+     * @return array|string message number for given message or all messages as array
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getUniqueId($id = null)
+    {
+        if (!$this->hasUniqueid) {
+            if ($id) {
+                return $id;
+            }
+            $count = $this->countMessages();
+            if ($count < 1) {
+                return array(); 
+            }
+            $range = range(1, $count);
+            return array_combine($range, $range);
+        }
+
+        return $this->_protocol->uniqueid($id);
+    }
+
+    /**
+     * get a message number from a unique id
+     *
+     * I.e. if you have a webmailer that supports deleting messages you should use unique ids
+     * as parameter and use this method to translate it to message number right before calling removeMessage()
+     *
+     * @param string $id unique id
+     * @return int message number
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getNumberByUniqueId($id)
+    {
+        if (!$this->hasUniqueid) {
+            return $id;
+        }
+
+        $ids = $this->getUniqueId();
+        foreach ($ids as $k => $v) {
+            if ($v == $id) {
+                return $k;
+            }
+        }
+
+        /**
+         * @see Zend_Mail_Storage_Exception
+         */
+        require_once 'Zend/Mail/Storage/Exception.php';
+        throw new Zend_Mail_Storage_Exception('unique id not found');
+    }
+
+    /**
+     * Special handling for hasTop and hasUniqueid. The headers of the first message is
+     * retrieved if Top wasn't needed/tried yet.
+     *
+     * @see Zend_Mail_Storage_Abstract:__get()
+     * @param  string $var
+     * @return string
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function __get($var)
+    {
+        $result = parent::__get($var);
+        if ($result !== null) {
+            return $result;
+        }
+
+        if (strtolower($var) == 'hastop') {
+            if ($this->_protocol->hasTop === null) {
+                // need to make a real call, because not all server are honest in their capas
+                try {
+                    $this->_protocol->top(1, 0, false);
+                } catch(Zend_Mail_Exception $e) {
+                    // ignoring error
+                }
+            }
+            $this->_has['top'] = $this->_protocol->hasTop;
+            return $this->_protocol->hasTop;
+        }
+
+        if (strtolower($var) == 'hasuniqueid') {
+            $id = null;
+            try {
+                $id = $this->_protocol->uniqueid(1);
+            } catch(Zend_Mail_Exception $e) {
+                // ignoring error
+            }
+            $this->_has['uniqueid'] = $id ? true : false;
+            return $this->_has['uniqueid'];
+        }
+
+        return $result;
+    }
+}
Index: libs/Zend/Mail/Storage/Writable/Interface.php
===================================================================
--- libs/Zend/Mail/Storage/Writable/Interface.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Writable/Interface.php	(wersja 0)
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Interface.php 8928 2008-03-20 19:41:41Z thomas $
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+interface Zend_Mail_Storage_Writable_Interface
+{
+    /**
+     * create a new folder
+     *
+     * This method also creates parent folders if necessary. Some mail storages may restrict, which folder
+     * may be used as parent or which chars may be used in the folder name
+     *
+     * @param string                          $name         global name of folder, local name if $parentFolder is set
+     * @param string|Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function createFolder($name, $parentFolder = null);
+
+    /**
+     * remove a folder
+     *
+     * @param string|Zend_Mail_Storage_Folder $name      name or instance of folder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function removeFolder($name);
+
+    /**
+     * rename and/or move folder
+     *
+     * The new name has the same restrictions as in createFolder()
+     *
+     * @param string|Zend_Mail_Storage_Folder $oldName name or instance of folder
+     * @param string                          $newName new global name of folder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function renameFolder($oldName, $newName);
+
+    /**
+     * append a new message to mail storage
+     *
+     * @param  string|Zend_Mail_Message|Zend_Mime_Message $message message as string or instance of message class
+     * @param  null|string|Zend_Mail_Storage_Folder       $folder  folder for new message, else current folder is taken
+     * @param  null|array                                 $flags   set flags for new message, else a default set is used
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function appendMessage($message, $folder = null, $flags = null);
+
+    /**
+     * copy an existing message
+     *
+     * @param  int                             $id     number of message
+     * @param  string|Zend_Mail_Storage_Folder $folder name or instance of targer folder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function copyMessage($id, $folder);
+
+    /**
+     * set flags for message
+     *
+     * NOTE: this method can't set the recent flag.
+     *
+     * @param  int   $id    number of message
+     * @param  array $flags new flags for message
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function setFlags($id, $flags);
+}
\ brakuje znaku końca linii na końcu pliku 
Index: libs/Zend/Mail/Storage/Writable/Maildir.php
===================================================================
--- libs/Zend/Mail/Storage/Writable/Maildir.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Writable/Maildir.php	(wersja 0)
@@ -0,0 +1,912 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Maildir.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Storage_Folder_Maildir
+ */
+require_once 'Zend/Mail/Storage/Folder/Maildir.php';
+
+/**
+ * @see Zend_Mail_Storage_Writable_Interface
+ */
+require_once 'Zend/Mail/Storage/Writable/Interface.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Writable_Maildir extends    Zend_Mail_Storage_Folder_Maildir
+                                         implements Zend_Mail_Storage_Writable_Interface
+{
+	/**
+	 * use quota and size of quota if given
+	 * @var bool|int
+	 */
+	protected $_quota;
+
+    /**
+     * create a new folder
+     *
+     * This method also creates parent folders if necessary. Some mail storages may restrict, which folder
+     * may be used as parent or which chars may be used in the folder name
+     *
+     * @param   string                          $name         global name of folder, local name if $parentFolder is set
+     * @param   string|Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent
+     * @return  string only used internally (new created maildir)
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    public function createFolder($name, $parentFolder = null)
+    {
+        if ($parentFolder instanceof Zend_Mail_Storage_Folder) {
+            $folder = $parentFolder->getGlobalName() . $this->_delim . $name;
+        } else if ($parentFolder != null) {
+            $folder = rtrim($parentFolder, $this->_delim) . $this->_delim . $name;
+        } else {
+            $folder = $name;
+        }
+
+        $folder = trim($folder, $this->_delim);
+
+        // first we check if we try to create a folder that does exist
+        $exists = null;
+        try {
+            $exists = $this->getFolders($folder);
+        } catch (Zend_Mail_Exception $e) {
+            // ok
+        }
+        if ($exists) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('folder already exists');
+        }
+
+        if (strpos($folder, $this->_delim . $this->_delim) !== false) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('invalid name - folder parts may not be empty');
+        }
+
+        if (strpos($folder, 'INBOX' . $this->_delim) === 0) {
+            $folder = substr($folder, 6);
+        }
+
+        $fulldir = $this->_rootdir . '.' . $folder;
+
+        // check if we got tricked and would create a dir outside of the rootdir or not as direct child
+        if (strpos($folder, DIRECTORY_SEPARATOR) !== false || strpos($folder, '/') !== false
+            || dirname($fulldir) . DIRECTORY_SEPARATOR != $this->_rootdir) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('invalid name - no directory seprator allowed in folder name');
+        }
+
+        // has a parent folder?
+        $parent = null;
+        if (strpos($folder, $this->_delim)) {
+            // let's see if the parent folder exists
+            $parent = substr($folder, 0, strrpos($folder, $this->_delim));
+            try {
+                $this->getFolders($parent);
+            } catch (Zend_Mail_Exception $e) {
+                // does not - create parent folder
+                $this->createFolder($parent);
+            }
+        }
+
+        if (!@mkdir($fulldir) || !@mkdir($fulldir . DIRECTORY_SEPARATOR . 'cur')) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('error while creating new folder, may be created incompletly');
+        }
+
+        mkdir($fulldir . DIRECTORY_SEPARATOR . 'new');
+        mkdir($fulldir . DIRECTORY_SEPARATOR . 'tmp');
+
+        $localName = $parent ? substr($folder, strlen($parent) + 1) : $folder;
+        $this->getFolders($parent)->$localName = new Zend_Mail_Storage_Folder($localName, $folder, true);
+
+        return $fulldir;
+    }
+
+    /**
+     * remove a folder
+     *
+     * @param   string|Zend_Mail_Storage_Folder $name      name or instance of folder
+     * @return  null
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    public function removeFolder($name)
+    {
+        // TODO: This could fail in the middle of the task, which is not optimal.
+        // But there is no defined standard way to mark a folder as removed and there is no atomar fs-op
+        // to remove a directory. Also moving the folder to a/the trash folder is not possible, as
+        // all parent folders must be created. What we could do is add a dash to the front of the
+        // directory name and it should be ignored as long as other processes obey the standard.
+
+        if ($name instanceof Zend_Mail_Storage_Folder) {
+            $name = $name->getGlobalName();
+        }
+
+        $name = trim($name, $this->_delim);
+        if (strpos($name, 'INBOX' . $this->_delim) === 0) {
+            $name = substr($name, 6);
+        }
+
+        // check if folder exists and has no children
+        if (!$this->getFolders($name)->isLeaf()) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('delete children first');
+        }
+
+        if ($name == 'INBOX' || $name == DIRECTORY_SEPARATOR || $name == '/') {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('wont delete INBOX');
+        }
+
+        if ($name == $this->getCurrentFolder()) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('wont delete selected folder');
+        }
+
+        foreach (array('tmp', 'new', 'cur', '.') as $subdir) {
+            $dir = $this->_rootdir . '.' . $name . DIRECTORY_SEPARATOR . $subdir;
+            if (!file_exists($dir)) {
+                continue;
+            }
+            $dh = opendir($dir);
+            if (!$dh) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception("error opening $subdir");
+            }
+            while (($entry = readdir($dh)) !== false) {
+                if ($entry == '.' || $entry == '..') {
+                    continue;
+                }
+                if (!unlink($dir . DIRECTORY_SEPARATOR . $entry)) {
+                    /**
+                     * @see Zend_Mail_Storage_Exception
+                     */
+                    require_once 'Zend/Mail/Storage/Exception.php';
+                    throw new Zend_Mail_Storage_Exception("error cleaning $subdir");
+                }
+            }
+            closedir($dh);
+            if ($subdir !== '.') {
+                if (!rmdir($dir)) {
+                    /**
+                     * @see Zend_Mail_Storage_Exception
+                     */
+                    require_once 'Zend/Mail/Storage/Exception.php';
+                    throw new Zend_Mail_Storage_Exception("error removing $subdir");
+                }
+            }
+        }
+
+        if (!rmdir($this->_rootdir . '.' . $name)) {
+            // at least we should try to make it a valid maildir again
+            mkdir($this->_rootdir . '.' . $name . DIRECTORY_SEPARATOR . 'cur');
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception("error removing maindir");
+        }
+
+        $parent = strpos($name, $this->_delim) ? substr($name, 0, strrpos($name, $this->_delim)) : null;
+        $localName = $parent ? substr($name, strlen($parent) + 1) : $name;
+        unset($this->getFolders($parent)->$localName);
+    }
+
+    /**
+     * rename and/or move folder
+     *
+     * The new name has the same restrictions as in createFolder()
+     *
+     * @param   string|Zend_Mail_Storage_Folder $oldName name or instance of folder
+     * @param   string                          $newName new global name of folder
+     * @return  null
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    public function renameFolder($oldName, $newName)
+    {
+        // TODO: This is also not atomar and has similar problems as removeFolder()
+
+        if ($oldName instanceof Zend_Mail_Storage_Folder) {
+            $oldName = $oldName->getGlobalName();
+        }
+
+        $oldName = trim($oldName, $this->_delim);
+        if (strpos($oldName, 'INBOX' . $this->_delim) === 0) {
+            $oldName = substr($oldName, 6);
+        }
+
+        $newName = trim($newName, $this->_delim);
+        if (strpos($newName, 'INBOX' . $this->_delim) === 0) {
+            $newName = substr($newName, 6);
+        }
+
+        if (strpos($newName, $oldName . $this->_delim) === 0) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('new folder cannot be a child of old folder');
+        }
+
+        // check if folder exists and has no children
+        $folder = $this->getFolders($oldName);
+
+        if ($oldName == 'INBOX' || $oldName == DIRECTORY_SEPARATOR || $oldName == '/') {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('wont rename INBOX');
+        }
+
+        if ($oldName == $this->getCurrentFolder()) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('wont rename selected folder');
+        }
+
+        $newdir = $this->createFolder($newName);
+
+        if (!$folder->isLeaf()) {
+            foreach ($folder as $k => $v) {
+                $this->renameFolder($v->getGlobalName(), $newName . $this->_delim . $k);
+            }
+        }
+
+        $olddir = $this->_rootdir . '.' . $folder;
+        foreach (array('tmp', 'new', 'cur') as $subdir) {
+            $subdir = DIRECTORY_SEPARATOR . $subdir;
+            if (!file_exists($olddir . $subdir)) {
+                continue;
+            }
+            // using copy or moving files would be even better - but also much slower
+            if (!rename($olddir . $subdir, $newdir . $subdir)) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception('error while moving ' . $subdir);
+            }
+        }
+        // create a dummy if removing fails - otherwise we can't read it next time
+        mkdir($olddir . DIRECTORY_SEPARATOR . 'cur');
+        $this->removeFolder($oldName);
+    }
+
+    /**
+     * create a uniqueid for maildir filename
+     *
+     * This is nearly the format defined in the maildir standard. The microtime() call should already
+     * create a uniqueid, the pid is for multicore/-cpu machine that manage to call this function at the
+     * exact same time, and uname() gives us the hostname for multiple machines accessing the same storage.
+     *
+     * If someone disables posix we create a random number of the same size, so this method should also
+     * work on Windows - if you manage to get maildir working on Windows.
+     * Microtime could also be disabled, altough I've never seen it.
+     *
+     * @return string new uniqueid
+     */
+    protected function _createUniqueId()
+    {
+        $id = '';
+        $id .= function_exists('microtime') ? microtime(true) : (time() . ' ' . rand(0, 100000));
+        $id .= '.' . (function_exists('posix_getpid') ? posix_getpid() : rand(50, 65535));
+        $id .= '.' . php_uname('n');
+
+        return $id;
+    }
+
+    /**
+     * open a temporary maildir file
+     *
+     * makes sure tmp/ exists and create a file with a unique name
+     * you should close the returned filehandle!
+     *
+     * @param   string $folder name of current folder without leading .
+     * @return  array array('dirname' => dir of maildir folder, 'uniq' => unique id, 'filename' => name of create file
+     *                     'handle'  => file opened for writing)
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    protected function _createTmpFile($folder = 'INBOX')
+    {
+    	if ($folder == 'INBOX') {
+	        $tmpdir = $this->_rootdir . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
+    	} else {
+	        $tmpdir = $this->_rootdir . '.' . $folder . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
+	    }
+        if (!file_exists($tmpdir)) {
+            if (!mkdir($tmpdir)) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception('problems creating tmp dir');
+            }
+        }
+
+        // we should retry to create a unique id if a file with the same name exists
+        // to avoid a script timeout we only wait 1 second (instead of 2) and stop
+        // after a defined retry count
+        // if you change this variable take into account that it can take up to $max_tries seconds
+        // normally we should have a valid unique name after the first try, we're just following the "standard" here
+        $max_tries = 5;
+        for ($i = 0; $i < $max_tries; ++$i) {
+            $uniq = $this->_createUniqueId();
+            if (!file_exists($tmpdir . $uniq)) {
+                // here is the race condition! - as defined in the standard
+                // to avoid having a long time between stat()ing the file and creating it we're opening it here
+                // to mark the filename as taken
+                $fh = fopen($tmpdir . $uniq, 'w');
+                if (!$fh) {
+                    /**
+                     * @see Zend_Mail_Storage_Exception
+                     */
+                    require_once 'Zend/Mail/Storage/Exception.php';
+                    throw new Zend_Mail_Storage_Exception('could not open temp file');
+                }
+                break;
+            }
+            sleep(1);
+        }
+
+        if (!$fh) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception("tried $max_tries unique ids for a temp file, but all were taken"
+                                                . ' - giving up');
+        }
+
+        return array('dirname' => $this->_rootdir . '.' . $folder, 'uniq' => $uniq, 'filename' => $tmpdir . $uniq,
+                     'handle' => $fh);
+    }
+
+    /**
+     * create an info string for filenames with given flags
+     *
+     * @param   array $flags wanted flags, with the reference you'll get the set flags with correct key (= char for flag)
+     * @return  string info string for version 2 filenames including the leading colon
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    protected function _getInfoString(&$flags)
+    {
+        // accessing keys is easier, faster and it removes duplicated flags
+        $wanted_flags = array_flip($flags);
+        if (isset($wanted_flags[Zend_Mail_Storage::FLAG_RECENT])) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('recent flag may not be set');
+        }
+
+        $info = ':2,';
+        $flags = array();
+        foreach (Zend_Mail_Storage_Maildir::$_knownFlags as $char => $flag) {
+            if (!isset($wanted_flags[$flag])) {
+                continue;
+            }
+            $info .= $char;
+            $flags[$char] = $flag;
+            unset($wanted_flags[$flag]);
+        }
+
+        if (!empty($wanted_flags)) {
+            $wanted_flags = implode(', ', array_keys($wanted_flags));
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('unknown flag(s): ' . $wanted_flags);
+        }
+
+        return $info;
+    }
+
+    /**
+     * append a new message to mail storage
+     *
+     * @param   string|stream                              $message message as string or stream resource
+     * @param   null|string|Zend_Mail_Storage_Folder       $folder  folder for new message, else current folder is taken
+     * @param   null|array                                 $flags   set flags for new message, else a default set is used
+     * @param   bool                                       $recent  handle this mail as if recent flag has been set,
+     *                                                              should only be used in delivery
+     * @throws  Zend_Mail_Storage_Exception
+     */
+     // not yet * @param string|Zend_Mail_Message|Zend_Mime_Message $message message as string or instance of message class
+
+    public function appendMessage($message, $folder = null, $flags = null, $recent = false)
+    {
+    	if ($this->_quota && $this->checkQuota()) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('storage is over quota!');    		
+    	}
+
+        if ($folder === null) {
+            $folder = $this->_currentFolder;
+        }
+
+        if (!($folder instanceof Zend_Mail_Storage_Folder)) {
+            $folder = $this->getFolders($folder);
+        }
+
+        if ($flags === null) {
+            $flags = array(Zend_Mail_Storage::FLAG_SEEN);
+        }
+        $info = $this->_getInfoString($flags);
+        $temp_file = $this->_createTmpFile($folder->getGlobalName());
+
+        // TODO: handle class instances for $message
+        if (is_resource($message) && get_resource_type($message) == 'stream') {
+        	stream_copy_to_stream($message, $temp_file['handle']);
+        } else {
+	        fputs($temp_file['handle'], $message);
+	    }
+        fclose($temp_file['handle']);
+
+        // we're adding the size to the filename for maildir++
+        $size = filesize($temp_file['filename']);
+        if ($size) {
+            $info = ',S=' . $size . $info;
+        }
+        $new_filename = $temp_file['dirname'] . DIRECTORY_SEPARATOR;
+        $new_filename .= $recent ? 'new' : 'cur';
+        $new_filename .= DIRECTORY_SEPARATOR . $temp_file['uniq'] . $info;
+
+        // we're throwing any exception after removing our temp file and saving it to this variable instead
+        $exception = null;
+
+        if (!link($temp_file['filename'], $new_filename)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            $exception = new Zend_Mail_Storage_Exception('cannot link message file to final dir');
+        }
+        @unlink($temp_file['filename']);
+
+        if ($exception) {
+            throw $exception;
+        }
+
+        $this->_files[] = array('uniq'     => $temp_file['uniq'],
+                                'flags'    => $flags,
+                                'filename' => $new_filename);
+        if ($this->_quota) {
+	        $this->_addQuotaEntry((int)$size, 1);
+	    }
+    }
+
+    /**
+     * copy an existing message
+     *
+     * @param   int                             $id     number of message
+     * @param   string|Zend_Mail_Storage_Folder $folder name or instance of targer folder
+     * @return  null
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    public function copyMessage($id, $folder)
+    {
+    	if ($this->_quota && $this->checkQuota()) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('storage is over quota!');    		
+    	}
+    
+        if (!($folder instanceof Zend_Mail_Storage_Folder)) {
+            $folder = $this->getFolders($folder);
+        }
+
+        $filedata = $this->_getFileData($id);
+        $old_file = $filedata['filename'];
+        $flags = $filedata['flags'];
+
+        // copied message can't be recent
+        while (($key = array_search(Zend_Mail_Storage::FLAG_RECENT, $flags)) !== false) {
+            unset($flags[$key]);
+        }
+        $info = $this->_getInfoString($flags);
+
+        // we're creating the copy as temp file before moving to cur/
+        $temp_file = $this->_createTmpFile($folder->getGlobalName());
+        // we don't write directly to the file
+        fclose($temp_file['handle']);
+
+        // we're adding the size to the filename for maildir++
+        // TODO: maybe we should support maildirsize or we just let the MDA do the work
+        $size = filesize($old_file);
+        if ($size) {
+            $info = ',S=' . $size . $info;
+        }
+        $new_file = $temp_file['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $temp_file['uniq'] . $info;
+
+        // we're throwing any exception after removing our temp file and saving it to this variable instead
+        $exception = null;
+
+        if (!copy($old_file, $temp_file['filename'])) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            $exception = new Zend_Mail_Storage_Exception('cannot copy message file');
+        } else if (!link($temp_file['filename'], $new_file)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            $exception = new Zend_Mail_Storage_Exception('cannot link message file to final dir');
+        }
+        @unlink($temp_file['filename']);
+
+        if ($exception) {
+            throw $exception;
+        }
+
+        if ($folder->getGlobalName() == $this->_currentFolder
+            || ($this->_currentFolder == 'INBOX' && $folder->getGlobalName() == '/')) {
+            $this->_files[] = array('uniq'     => $temp_file['uniq'],
+                                    'flags'    => $flags,
+                                    'filename' => $new_file);
+        }
+        
+        if ($this->_quota) {
+	        $this->_addQuotaEntry((int)$size, 1);
+	    }
+    }
+
+    /**
+     * set flags for message
+     *
+     * NOTE: this method can't set the recent flag.
+     *
+     * @param   int   $id    number of message
+     * @param   array $flags new flags for message
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    public function setFlags($id, $flags)
+    {
+        $info = $this->_getInfoString($flags);
+        $filedata = $this->_getFileData($id);
+
+        // TODO: move file from new to cur
+        $new_filename = dirname($filedata['filename']) . DIRECTORY_SEPARATOR . "$filedata[uniq]$info";
+
+        if (!@rename($filedata['filename'], $new_filename)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot rename file');
+        }
+
+        $filedata['flags']    = $flags;
+        $filedata['filename'] = $new_filename;
+
+        $this->_files[$id - 1] = $filedata;
+    }
+
+
+    /**
+     * stub for not supported message deletion
+     *
+     * @return  null
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    public function removeMessage($id)
+    {
+        $filename = $this->_getFileData($id, 'filename');
+        
+        if ($this->_quota) {
+	        $size = filesize($filename);
+	    }
+        
+        if (!@unlink($filename)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot remove message');
+        }
+        unset($this->_files[$id - 1]);
+        // remove the gap
+        $this->_files = array_values($this->_files);
+        if ($this->_quota) {
+	        $this->_addQuotaEntry(0 - (int)$size, -1);
+	    }
+    }
+    
+	/**
+	 * enable/disable quota and set a quota value if wanted or needed
+	 *
+	 * You can enable/disable quota with true/false. If you don't have
+	 * a MDA or want to enforce a quota value you can also set this value
+	 * here. Use array('size' => SIZE_QUOTA, 'count' => MAX_MESSAGE) do
+	 * define your quota. Order of these fields does matter!
+	 *
+	 * @param bool|array $value new quota value
+	 * @return null
+	 */
+    public function setQuota($value) {
+    	$this->_quota = $value;
+    }
+    
+    /**
+     * get currently set quota
+     *
+     * @see Zend_Mail_Storage_Writable_Maildir::setQuota()
+     *
+     * @return bool|array
+     */
+    public function getQuota($fromStorage = false) {
+    	if ($fromStorage) {
+			$fh = @fopen($this->_rootdir . 'maildirsize', 'r');
+			if (!$fh) {
+				/**
+				 * @see Zend_Mail_Storage_Exception
+				 */
+				require_once 'Zend/Mail/Storage/Exception.php';
+				throw new Zend_Mail_Storage_Exception('cannot open maildirsize');
+			}
+			$definition = fgets($fh);
+			fclose($fh);
+			$definition = explode(',', trim($definition));
+			$quota = array();
+			foreach ($definition as $member) {
+				$key = $member[strlen($member) - 1];
+				if ($key == 'S' || $key == 'C') {
+					$key = $key == 'C' ? 'count' : 'size';
+				}
+				$quota[$key] = substr($member, 0, -1);
+			}
+			return $quota;
+    	}
+    	
+    	return $this->_quota;
+    }
+    
+    /**
+     * @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating maildirsize"
+     */
+    protected function _calculateMaildirsize() {
+    	$timestamps = array();
+    	$messages = 0;
+    	$total_size = 0;
+
+		if (is_array($this->_quota)) {
+			$quota = $this->_quota;
+		} else {
+			try {
+				$quota = $this->getQuota(true);
+			} catch (Zend_Mail_Storage_Exception $e) {
+				throw new Zend_Mail_Storage_Exception('no quota defintion found');
+			}
+		}
+    	
+    	$folders = new RecursiveIteratorIterator($this->getFolders(), RecursiveIteratorIterator::SELF_FIRST);
+		foreach ($folders as $folder) {
+			$subdir = $folder->getGlobalName();
+			if ($subdir == 'INBOX') {
+				$subdir = '';
+			} else {
+				$subdir = '.' . $subdir;
+			}
+			if ($subdir == 'Trash') {
+				continue;
+			}
+			
+			foreach (array('cur', 'new') as $subsubdir) {
+				$dirname = $this->_rootdir . $subdir . DIRECTORY_SEPARATOR . $subsubdir . DIRECTORY_SEPARATOR;
+				if (!file_exists($dirname)) {
+					continue;
+				}
+				// NOTE: we are using mtime instead of "the latest timestamp". The latest would be atime
+				// and as we are accessing the directory it would make the whole calculation useless.	
+				$timestamps[$dirname] = filemtime($dirname);
+
+				$dh = opendir($dirname);
+				// NOTE: Should have been checked in constructor. Not throwing an exception here, quotas will 
+				// therefore not be fully enforeced, but next request will fail anyway, if problem persists.
+				if (!$dh) {
+					continue;
+				}
+				
+								
+				while (($entry = readdir()) !== false) {
+					if ($entry[0] == '.' || !is_file($dirname . $entry)) {
+    	            	continue;
+        	    	}
+        	    	
+        	    	if (strpos($entry, ',S=')) {
+        	    		strtok($entry, '=');
+        	    		$filesize = strtok(':');
+        	    		if (is_numeric($filesize)) {
+        	    			$total_size += $filesize;
+        	    			++$messages;
+        	    			continue;
+        	    		}
+        	    	}
+        	    	$size = filesize($dirname . $entry);
+        	    	if ($size === false) {
+        	    		// ignore, as we assume file got removed
+        	    		continue;
+        	    	}
+        	    	$total_size += $size;
+        	    	++$messages;
+				}
+			}
+		}
+		
+		$tmp = $this->_createTmpFile();
+		$fh = $tmp['handle'];
+		$definition = array();
+		foreach ($quota as $type => $value) {
+			if ($type == 'size' || $type == 'count') {
+				$type = $type == 'count' ? 'C' : 'S';
+			}
+			$definition[] = $value . $type;
+		}
+		$definition = implode(',', $definition);
+		fputs($fh, "$definition\n");
+		fputs($fh, "$total_size $messages\n");
+		fclose($fh);
+		rename($tmp['filename'], $this->_rootdir . 'maildirsize');
+		foreach ($timestamps as $dir => $timestamp) {
+			if ($timestamp < filemtime($dir)) {
+				unlink($this->_rootdir . 'maildirsize');
+				break;
+			}
+		}
+		
+		return array('size' => $total_size, 'count' => $messages, 'quota' => $quota);
+    }
+    
+    /**
+     * @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating the quota for a Maildir++"
+     */
+    protected function _calculateQuota($forceRecalc = false) {
+    	$fh = null;
+		$total_size = 0;
+		$messages   = 0;
+		$maildirsize = '';
+    	if (!$forceRecalc && file_exists($this->_rootdir . 'maildirsize') && filesize($this->_rootdir . 'maildirsize') < 5120) {
+    		$fh = fopen($this->_rootdir . 'maildirsize', 'r');
+    	}
+		if ($fh) {
+			$maildirsize = fread($fh, 5120);
+			if (strlen($maildirsize) >= 5120) {
+				fclose($fh);
+				$fh = null;
+				$maildirsize = '';
+			}
+		}
+    	
+    	if (!$fh) {
+    		$result = $this->_calculateMaildirsize();
+    		$total_size = $result['size'];
+    		$messages   = $result['count'];
+    		$quota      = $result['quota'];
+    	} else {
+    		$maildirsize = explode("\n", $maildirsize);
+			if (is_array($this->_quota)) {
+				$quota = $this->_quota;
+			} else {
+				$definition = explode(',', $maildirsize[0]);
+				$quota = array();
+				foreach ($definition as $member) {
+					$key = $member[strlen($member) - 1];
+					if ($key == 'S' || $key == 'C') {
+						$key = $key == 'C' ? 'count' : 'size';
+					}
+					$quota[$key] = substr($member, 0, -1);
+				}
+			}
+			unset($maildirsize[0]);
+			foreach ($maildirsize as $line) {
+				list($size, $count) = explode(' ', trim($line));
+				$total_size += $size;
+				$messages   += $count;
+			}
+    	}
+    	
+    	$over_quota = false;
+    	$over_quota = $over_quota || (isset($quota['size'])  && $total_size > $quota['size']); 
+    	$over_quota = $over_quota || (isset($quota['count']) && $messages   > $quota['count']);
+    	// NOTE: $maildirsize equals false if it wasn't set (AKA we recalculated) or it's only
+    	// one line, because $maildirsize[0] gets unsetted.
+    	// Also we're using local time to calculate the 15 minute offset. Touching a file just for known the
+    	// local time of the file storage isn't worth the hassle.
+    	if ($over_quota && ($maildirsize || filemtime($this->_rootdir . 'maildirsize') > time() - 900)) {
+    		$result = $this->_calculateMaildirsize();
+    		$total_size = $result['size'];
+    		$messages   = $result['count'];
+    		$quota      = $result['quota'];
+			$over_quota = false;
+			$over_quota = $over_quota || (isset($quota['size'])  && $total_size > $quota['size']); 
+			$over_quota = $over_quota || (isset($quota['count']) && $messages   > $quota['count']);
+    	}
+    	
+    	if ($fh) {
+    		// TODO is there a safe way to keep the handle open for writing?
+    		fclose($fh);
+    	}
+    	
+    	return array('size' => $total_size, 'count' => $messages, 'quota' => $quota, 'over_quota' => $over_quota);
+    }
+    
+    protected function _addQuotaEntry($size, $count = 1) {
+    	if (!file_exists($this->_rootdir . 'maildirsize')) {
+    		// TODO: should get file handler from _calculateQuota
+    	}
+    	$size = (int)$size;
+    	$count = (int)$count;
+    	file_put_contents($this->_rootdir . 'maildirsize', "$size $count\n", FILE_APPEND);
+    }
+    
+    /**
+     * check if storage is currently over quota
+     *
+     * @param bool $detailedResponse return known data of quota and current size and message count @see _calculateQuota()
+     * @return bool|array over quota state or detailed response
+     */
+    public function checkQuota($detailedResponse = false, $forceRecalc = false) {
+    	$result = $this->_calculateQuota($forceRecalc);
+    	return $detailedResponse ? $result : $result['over_quota'];
+    }
+}
Index: libs/Zend/Mail/Storage/Abstract.php
===================================================================
--- libs/Zend/Mail/Storage/Abstract.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Abstract.php	(wersja 0)
@@ -0,0 +1,366 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Abstract.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+abstract class Zend_Mail_Storage_Abstract implements Countable, ArrayAccess, SeekableIterator
+{
+    /**
+     * class capabilities with default values
+     * @var array
+     */
+    protected $_has = array('uniqueid'  => true,
+                            'delete'    => false,
+                            'create'    => false,
+                            'top'       => false,
+                            'fetchPart' => true,
+                            'flags'     => false);
+
+    /**
+     * current iteration position
+     * @var int
+     */
+    protected $_iterationPos = 0;
+
+    /**
+     * maximum iteration position (= message count)
+     * @var null|int
+     */
+    protected $_iterationMax = null;
+
+    /**
+     * used message class, change it in an extened class to extend the returned message class
+     * @var string
+     */
+    protected $_messageClass = 'Zend_Mail_Message';
+
+    /**
+     * Getter for has-properties. The standard has properties
+     * are: hasFolder, hasUniqueid, hasDelete, hasCreate, hasTop
+     *
+     * The valid values for the has-properties are:
+     *   - true if a feature is supported
+     *   - false if a feature is not supported
+     *   - null is it's not yet known or it can't be know if a feature is supported
+     *
+     * @param  string $var  property name
+     * @return bool         supported or not
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function __get($var)
+    {
+        if (strpos($var, 'has') === 0) {
+            $var = strtolower(substr($var, 3));
+            return isset($this->_has[$var]) ? $this->_has[$var] : null;
+        }
+        
+        /**
+         * @see Zend_Mail_Storage_Exception
+         */
+        require_once 'Zend/Mail/Storage/Exception.php';
+        throw new Zend_Mail_Storage_Exception($var . ' not found');
+    }
+
+
+    /**
+     * Get a full list of features supported by the specific mail lib and the server
+     *
+     * @return array list of features as array(featurename => true|false[|null])
+     */
+    public function getCapabilities()
+    {
+        return $this->_has;
+    }
+
+
+    /**
+     * Count messages messages in current box/folder
+     *
+     * @return int number of messages
+     * @throws Zend_Mail_Storage_Exception
+     */
+    abstract public function countMessages();
+
+
+    /**
+     * Get a list of messages with number and size
+     *
+     * @param  int $id  number of message
+     * @return int|array size of given message of list with all messages as array(num => size)
+     */
+    abstract public function getSize($id = 0);
+
+
+    /**
+     * Get a message with headers and body
+     *
+     * @param  $id int number of message
+     * @return Zend_Mail_Message
+     */
+    abstract public function getMessage($id);
+
+
+    /**
+     * Get raw header of message or part
+     *
+     * @param  int               $id       number of message
+     * @param  null|array|string $part     path to part or null for messsage header
+     * @param  int               $topLines include this many lines with header (after an empty line)
+     * @return string raw header
+     */
+    abstract public function getRawHeader($id, $part = null, $topLines = 0);
+
+    /**
+     * Get raw content of message or part
+     *
+     * @param  int               $id   number of message
+     * @param  null|array|string $part path to part or null for messsage content
+     * @return string raw content
+     */
+    abstract public function getRawContent($id, $part = null);
+
+    /**
+     * Create instance with parameters
+     *
+     * @param  array $params mail reader specific parameters
+     * @throws Zend_Mail_Storage_Exception
+     */
+    abstract public function __construct($params);
+
+
+    /**
+     * Destructor calls close() and therefore closes the resource.
+     */
+    public function __destruct()
+    {
+        $this->close();
+    }
+
+
+    /**
+     * Close resource for mail lib. If you need to control, when the resource
+     * is closed. Otherwise the destructor would call this.
+     *
+     * @return null
+     */
+    abstract public function close();
+
+
+    /**
+     * Keep the resource alive.
+     *
+     * @return null
+     */
+    abstract public function noop();
+
+    /**
+     * delete a message from current box/folder
+     *
+     * @return null
+     */
+    abstract public function removeMessage($id);
+
+    /**
+     * get unique id for one or all messages
+     *
+     * if storage does not support unique ids it's the same as the message number
+     *
+     * @param int|null $id message number
+     * @return array|string message number for given message or all messages as array
+     * @throws Zend_Mail_Storage_Exception
+     */
+    abstract public function getUniqueId($id = null);
+
+    /**
+     * get a message number from a unique id
+     *
+     * I.e. if you have a webmailer that supports deleting messages you should use unique ids
+     * as parameter and use this method to translate it to message number right before calling removeMessage()
+     *
+     * @param string $id unique id
+     * @return int message number
+     * @throws Zend_Mail_Storage_Exception
+     */
+    abstract public function getNumberByUniqueId($id);
+
+    // interface implementations follows
+
+    /**
+     * Countable::count()
+     *
+     * @return   int
+     */
+     public function count()
+     {
+        return $this->countMessages();
+     }
+
+
+     /**
+      * ArrayAccess::offsetExists()
+      *
+      * @param    int     $id
+      * @return   boolean
+      */
+     public function offsetExists($id)
+     {
+        try {
+            if ($this->getMessage($id)) {
+                return true;
+            }
+        } catch(Zend_Mail_Storage_Exception $e) {}
+
+        return false;
+     }
+
+
+     /**
+      * ArrayAccess::offsetGet()
+      *
+      * @param    int $id
+      * @return   Zend_Mail_Message message object
+      */
+     public function offsetGet($id)
+     {
+        return $this->getMessage($id);
+     }
+
+
+     /**
+      * ArrayAccess::offsetSet()
+      *
+      * @param    id     $id
+      * @param    mixed  $value
+      * @throws   Zend_Mail_Storage_Exception
+      * @return   void
+      */
+     public function offsetSet($id, $value)
+     {
+        /**
+         * @see Zend_Mail_Storage_Exception
+         */
+        require_once 'Zend/Mail/Storage/Exception.php';
+        throw new Zend_Mail_Storage_Exception('cannot write mail messages via array access');
+     }
+
+
+     /**
+      * ArrayAccess::offsetUnset()
+      *
+      * @param    int   $id
+      * @return   boolean success
+      */
+     public function offsetUnset($id)
+     {
+        return $this->removeMessage($id);
+     }
+
+
+     /**
+      * Iterator::rewind()
+      *
+      * Rewind always gets the new count from the storage. Thus if you use
+      * the interfaces and your scripts take long you should use reset()
+      * from time to time.
+      *
+      * @return   void
+      */
+     public function rewind()
+     {
+        $this->_iterationMax = $this->countMessages();
+        $this->_iterationPos = 1;
+     }
+
+
+     /**
+      * Iterator::current()
+      *
+      * @return   Zend_Mail_Message current message
+      */
+     public function current()
+     {
+        return $this->getMessage($this->_iterationPos);
+     }
+
+
+     /**
+      * Iterator::key()
+      *
+      * @return   int id of current position
+      */
+     public function key()
+     {
+        return $this->_iterationPos;
+     }
+
+
+     /**
+      * Iterator::next()
+      *
+      * @return   void
+      */
+     public function next()
+     {
+        ++$this->_iterationPos;
+     }
+
+
+     /**
+      * Iterator::valid()
+      *
+      * @return   boolean
+      */
+     public function valid()
+     {
+        if ($this->_iterationMax === null) {
+          $this->_iterationMax = $this->countMessages();
+        }
+        return $this->_iterationPos && $this->_iterationPos <= $this->_iterationMax;
+     }
+
+
+     /**
+      * SeekableIterator::seek()
+      *
+      * @param  int $pos
+      * @return void
+      * @throws OutOfBoundsException
+      */
+     public function seek($pos)
+     {
+        if ($this->_iterationMax === null) {
+          $this->_iterationMax = $this->countMessages();
+        }
+
+        if ($pos > $this->_iterationMax) {
+            throw new OutOfBoundsException('this position does not exist');
+        }
+        $this->_iterationPos = $pos;
+     }
+
+}
Index: libs/Zend/Mail/Storage/Mbox.php
===================================================================
--- libs/Zend/Mail/Storage/Mbox.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Mbox.php	(wersja 0)
@@ -0,0 +1,434 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Mbox.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Loader
+ * May be used in constructor, but commented out for now
+ */
+// require_once 'Zend/Loader.php';
+
+/**
+ * @see Zend_Mail_Storage_Abstract
+ */
+require_once 'Zend/Mail/Storage/Abstract.php';
+
+/**
+ * @see Zend_Mail_Message
+ */
+require_once 'Zend/Mail/Message.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
+{
+    /**
+     * file handle to mbox file
+     * @var null|resource
+     */
+    protected $_fh;
+
+    /**
+     * filename of mbox file for __wakeup
+     * @var string
+     */
+    protected $_filename;
+
+    /**
+     * modification date of mbox file for __wakeup
+     * @var int
+     */
+    protected $_filemtime;
+
+    /**
+     * start and end position of messages as array('start' => start, 'seperator' => headersep, 'end' => end)
+     * @var array
+     */
+    protected $_positions;
+
+
+    /**
+     * Count messages all messages in current box
+     *
+     * @return int number of messages
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function countMessages()
+    {
+        return count($this->_positions);
+    }
+
+
+    /**
+     * Get a list of messages with number and size
+     *
+     * @param  int|null $id  number of message or null for all messages
+     * @return int|array size of given message of list with all messages as array(num => size)
+     */
+    public function getSize($id = 0)
+    {
+        if ($id) {
+            $pos = $this->_positions[$id - 1];
+            return $pos['end'] - $pos['start'];
+        }
+
+        $result = array();
+        foreach ($this->_positions as $num => $pos) {
+            $result[$num + 1] = $pos['end'] - $pos['start'];
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * Get positions for mail message or throw exeption if id is invalid
+     *
+     * @param int $id number of message
+     * @return array positions as in _positions
+     * @throws Zend_Mail_Storage_Exception
+     */
+    protected function _getPos($id)
+    {
+        if (!isset($this->_positions[$id - 1])) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('id does not exist');
+        }
+
+        return $this->_positions[$id - 1];
+    }
+
+
+    /**
+     * Fetch a message
+     *
+     * @param  int $id number of message
+     * @return Zend_Mail_Message
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getMessage($id)
+    {
+        $bodyLines = 0; // TODO: need a way to change that
+
+        $message = $this->getRawHeader($id);
+        // file pointer is after headers now
+        if ($bodyLines) {
+            $message .= "\n";
+            while ($bodyLines-- && ftell($this->_fh) < $this->_positions[$id - 1]['end']) {
+                $message .= fgets($this->_fh);
+            }
+        }
+
+        return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $message));
+    }
+
+    /*
+     * Get raw header of message or part
+     *
+     * @param  int               $id       number of message
+     * @param  null|array|string $part     path to part or null for messsage header
+     * @param  int               $topLines include this many lines with header (after an empty line)
+     * @return string raw header
+     * @throws Zend_Mail_Protocol_Exception
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getRawHeader($id, $part = null, $topLines = 0)
+    {
+        if ($part !== null) {
+            // TODO: implement
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('not implemented');
+        }
+        $messagePos = $this->_getPos($id);
+        // TODO: toplines
+        return stream_get_contents($this->_fh, $messagePos['separator'] - $messagePos['start'], $messagePos['start']);
+    }
+
+    /*
+     * Get raw content of message or part
+     *
+     * @param  int               $id   number of message
+     * @param  null|array|string $part path to part or null for messsage content
+     * @return string raw content
+     * @throws Zend_Mail_Protocol_Exception
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getRawContent($id, $part = null)
+    {
+        if ($part !== null) {
+            // TODO: implement
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('not implemented');
+        }
+        $messagePos = $this->_getPos($id);
+        return stream_get_contents($this->_fh, $messagePos['end'] - $messagePos['separator'], $messagePos['separator']);
+    }
+
+    /**
+     * Create instance with parameters
+     * Supported parameters are:
+     *   - filename filename of mbox file
+     *
+     * @param  $params array mail reader specific parameters
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function __construct($params)
+    {
+        if (is_array($params)) {
+            $params = (object)$params;
+        }
+    
+        if (!isset($params->filename) /* || Zend_Loader::isReadable($params['filename']) */) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('no valid filename given in params');
+        }
+
+        $this->_openMboxFile($params->filename);
+        $this->_has['top']      = true;
+        $this->_has['uniqueid'] = false;
+    }
+
+    /**
+     * check if given file is a mbox file
+     *
+     * if $file is a resource its file pointer is moved after the first line
+     *
+     * @param  resource|string $file stream resource of name of file
+     * @param  bool $fileIsString file is string or resource
+     * @return bool file is mbox file
+     */
+    protected function _isMboxFile($file, $fileIsString = true)
+    {
+        if ($fileIsString) {
+            $file = @fopen($file, 'r');
+            if (!$file) {
+                return false;
+            }
+        } else {
+            fseek($file, 0);
+        }
+
+        $result = false;
+
+        $line = fgets($file);
+        if (strpos($line, 'From ') === 0) {
+            $result = true;
+        }
+
+        if ($fileIsString) {
+            @fclose($file);
+        }
+
+        return $result;
+    }
+
+    /**
+     * open given file as current mbox file
+     *
+     * @param  string $filename filename of mbox file
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    protected function _openMboxFile($filename)
+    {
+        if ($this->_fh) {
+            $this->close();
+        }
+
+        $this->_fh = @fopen($filename, 'r');
+        if (!$this->_fh) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot open mbox file');
+        }
+        $this->_filename = $filename;
+        $this->_filemtime = filemtime($this->_filename);
+
+        if (!$this->_isMboxFile($this->_fh, false)) {
+            @fclose($this->_fh);
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('file is not a valid mbox format');
+        }
+
+        $messagePos = array('start' => ftell($this->_fh), 'separator' => 0, 'end' => 0);
+        while (($line = fgets($this->_fh)) !== false) {
+            if (strpos($line, 'From ') === 0) {
+                $messagePos['end'] = ftell($this->_fh) - strlen($line) - 2; // + newline
+                if (!$messagePos['separator']) {
+                    $messagePos['separator'] = $messagePos['end'];
+                }
+                $this->_positions[] = $messagePos;
+                $messagePos = array('start' => ftell($this->_fh), 'separator' => 0, 'end' => 0);
+            }
+            if (!$messagePos['separator'] && !trim($line)) {
+                $messagePos['separator'] = ftell($this->_fh);
+            }
+        }
+
+        $messagePos['end'] = ftell($this->_fh);
+        if (!$messagePos['separator']) {
+            $messagePos['separator'] = $messagePos['end'];
+        }
+        $this->_positions[] = $messagePos;
+    }
+
+    /**
+     * Close resource for mail lib. If you need to control, when the resource
+     * is closed. Otherwise the destructor would call this.
+     *
+     * @return void
+     */
+    public function close()
+    {
+        @fclose($this->_fh);
+        $this->_positions = array();
+    }
+
+
+    /**
+     * Waste some CPU cycles doing nothing.
+     *
+     * @return void
+     */
+    public function noop()
+    {
+        return true;
+    }
+
+
+    /**
+     * stub for not supported message deletion
+     *
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function removeMessage($id)
+    {
+        /**
+         * @see Zend_Mail_Storage_Exception
+         */
+        require_once 'Zend/Mail/Storage/Exception.php';
+        throw new Zend_Mail_Storage_Exception('mbox is read-only');
+    }
+
+    /**
+     * get unique id for one or all messages
+     *
+     * Mbox does not support unique ids (yet) - it's always the same as the message number.
+     * That shouldn't be a problem, because we can't change mbox files. Therefor the message
+     * number is save enough.
+     *
+     * @param int|null $id message number
+     * @return array|string message number for given message or all messages as array
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getUniqueId($id = null)
+    {
+        if ($id) {
+            // check if id exists
+            $this->_getPos($id);
+            return $id;
+        }
+
+        $range = range(1, $this->countMessages());
+        return array_combine($range, $range);
+    }
+
+    /**
+     * get a message number from a unique id
+     *
+     * I.e. if you have a webmailer that supports deleting messages you should use unique ids
+     * as parameter and use this method to translate it to message number right before calling removeMessage()
+     *
+     * @param string $id unique id
+     * @return int message number
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getNumberByUniqueId($id)
+    {
+        // check if id exists
+        $this->_getPos($id);
+        return $id;
+    }
+
+    /**
+     * magic method for serialize()
+     *
+     * with this method you can cache the mbox class
+     *
+     * @return array name of variables
+     */
+    public function __sleep()
+    {
+        return array('_filename', '_positions', '_filemtime');
+    }
+
+    /**
+     * magic method for unserialize()
+     *
+     * with this method you can cache the mbox class
+     * for cache validation the mtime of the mbox file is used
+     *
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function __wakeup()
+    {
+        if ($this->_filemtime != @filemtime($this->_filename)) {
+            $this->close();
+            $this->_openMboxFile($this->_filename);
+        } else {
+            $this->_fh = @fopen($this->_filename, 'r');
+            if (!$this->_fh) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception('cannot open mbox file');
+            }
+        }
+    }
+
+}
Index: libs/Zend/Mail/Storage/Folder/Interface.php
===================================================================
--- libs/Zend/Mail/Storage/Folder/Interface.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Folder/Interface.php	(wersja 0)
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Interface.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_Mail_Storage_Folder_Interface
+{
+    /**
+     * get root folder or given folder
+     *
+     * @param string $rootFolder get folder structure for given folder, else root
+     * @return Zend_Mail_Storage_Folder root or wanted folder
+     */
+    public function getFolders($rootFolder = null);
+
+    /**
+     * select given folder
+     *
+     * folder must be selectable!
+     *
+     * @param Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function selectFolder($globalName);
+
+
+    /**
+     * get Zend_Mail_Storage_Folder instance for current folder
+     *
+     * @return Zend_Mail_Storage_Folder instance of current folder
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getCurrentFolder();
+}
Index: libs/Zend/Mail/Storage/Folder/Maildir.php
===================================================================
--- libs/Zend/Mail/Storage/Folder/Maildir.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Folder/Maildir.php	(wersja 0)
@@ -0,0 +1,265 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Maildir.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Storage_Folder
+ */
+require_once 'Zend/Mail/Storage/Folder.php';
+
+/**
+ * @see Zend_Mail_Storage_Folder_Interface
+ */
+require_once 'Zend/Mail/Storage/Folder/Interface.php';
+
+/**
+ * @see Zend_Mail_Storage_Maildir
+ */
+require_once 'Zend/Mail/Storage/Maildir.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir implements Zend_Mail_Storage_Folder_Interface
+{
+    /**
+     * Zend_Mail_Storage_Folder root folder for folder structure
+     * @var Zend_Mail_Storage_Folder
+     */
+    protected $_rootFolder;
+
+    /**
+     * rootdir of folder structure
+     * @var string
+     */
+    protected $_rootdir;
+
+    /**
+     * name of current folder
+     * @var string
+     */
+    protected $_currentFolder;
+
+    /**
+     * delim char for subfolders
+     * @var string
+     */
+    protected $_delim;
+
+    /**
+     * Create instance with parameters
+     * Supported parameters are:
+     *   - dirname rootdir of maildir structure
+     *   - delim   delim char for folder structur, default is '.'
+     *   - folder intial selected folder, default is 'INBOX'
+     *
+     * @param  $params array mail reader specific parameters
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function __construct($params)
+    {
+        if (is_array($params)) {
+            $params = (object)$params;
+        }
+
+        if (!isset($params->dirname) || !is_dir($params->dirname)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('no valid dirname given in params');
+        }
+
+        $this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
+
+        $this->_delim = isset($params->delim) ? $params->delim : '.';
+
+        $this->_buildFolderTree();
+        $this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX');
+        $this->_has['top'] = true;
+        $this->_has['flags'] = true;
+    }
+
+    /**
+     * find all subfolders and mbox files for folder structure
+     *
+     * Result is save in Zend_Mail_Storage_Folder instances with the root in $this->_rootFolder.
+     * $parentFolder and $parentGlobalName are only used internally for recursion.
+     *
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    protected function _buildFolderTree()
+    {
+        $this->_rootFolder = new Zend_Mail_Storage_Folder('/', '/', false);
+        $this->_rootFolder->INBOX = new Zend_Mail_Storage_Folder('INBOX', 'INBOX', true);
+
+        $dh = @opendir($this->_rootdir);
+        if (!$dh) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception("can't read folders in maildir");
+        }
+        $dirs = array();
+        while (($entry = readdir($dh)) !== false) {
+            // maildir++ defines folders must start with .
+            if ($entry[0] != '.' || $entry == '.' || $entry == '..') {
+                continue;
+            }
+            if ($this->_isMaildir($this->_rootdir . $entry)) {
+                $dirs[] = $entry;
+            }
+        }
+        closedir($dh);
+
+        sort($dirs);
+        $stack = array(null);
+        $folderStack = array(null);
+        $parentFolder = $this->_rootFolder;
+        $parent = '.';
+
+        foreach ($dirs as $dir) {
+            do {
+                if (strpos($dir, $parent) === 0) {
+                    $local = substr($dir, strlen($parent));
+                    if (strpos($local, $this->_delim) !== false) {
+                        /**
+                         * @see Zend_Mail_Storage_Exception
+                         */
+                        require_once 'Zend/Mail/Storage/Exception.php';
+                        throw new Zend_Mail_Storage_Exception('error while reading maildir');
+                    }
+                    array_push($stack, $parent);
+                    $parent = $dir . $this->_delim;
+                    $folder = new Zend_Mail_Storage_Folder($local, substr($dir, 1), true);
+                    $parentFolder->$local = $folder;
+                    array_push($folderStack, $parentFolder);
+                    $parentFolder = $folder;
+                    break;
+                } else if ($stack) {
+                    $parent = array_pop($stack);
+                    $parentFolder = array_pop($folderStack);
+                }
+            } while ($stack);
+            if (!$stack) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception('error while reading maildir');
+            }
+        }
+    }
+
+    /**
+     * get root folder or given folder
+     *
+     * @param string $rootFolder get folder structure for given folder, else root
+     * @return Zend_Mail_Storage_Folder root or wanted folder
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getFolders($rootFolder = null)
+    {
+        if (!$rootFolder || $rootFolder == 'INBOX') {
+            return $this->_rootFolder;
+        }
+
+        // rootdir is same as INBOX in maildir
+        if (strpos($rootFolder, 'INBOX' . $this->_delim) === 0) {
+            $rootFolder = substr($rootFolder, 6);
+        }
+        $currentFolder = $this->_rootFolder;
+        $subname = trim($rootFolder, $this->_delim);
+        while ($currentFolder) {
+            @list($entry, $subname) = @explode($this->_delim, $subname, 2);
+            $currentFolder = $currentFolder->$entry;
+            if (!$subname) {
+                break;
+            }
+        }
+
+        if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->_delim)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception("folder $rootFolder not found");
+        }
+        return $currentFolder;
+    }
+
+    /**
+     * select given folder
+     *
+     * folder must be selectable!
+     *
+     * @param Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function selectFolder($globalName)
+    {
+        $this->_currentFolder = (string)$globalName;
+
+        // getting folder from folder tree for validation
+        $folder = $this->getFolders($this->_currentFolder);
+
+        try {
+            $this->_openMaildir($this->_rootdir . '.' . $folder->getGlobalName());
+        } catch(Zend_Mail_Storage_Exception $e) {
+            // check what went wrong
+            if (!$folder->isSelectable()) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable");
+            }
+            // seems like file has vanished; rebuilding folder tree - but it's still an exception
+            $this->_buildFolderTree($this->_rootdir);
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('seems like the maildir has vanished, I\'ve rebuild the ' .
+                                                         'folder tree, search for an other folder and try again');
+        }
+    }
+
+    /**
+     * get Zend_Mail_Storage_Folder instance for current folder
+     *
+     * @return Zend_Mail_Storage_Folder instance of current folder
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getCurrentFolder()
+    {
+        return $this->_currentFolder;
+    }
+}
Index: libs/Zend/Mail/Storage/Folder/Mbox.php
===================================================================
--- libs/Zend/Mail/Storage/Folder/Mbox.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Folder/Mbox.php	(wersja 0)
@@ -0,0 +1,264 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Mbox.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Storage_Folder
+ */
+require_once 'Zend/Mail/Storage/Folder.php';
+
+/**
+ * @see Zend_Mail_Storage_Folder_Interface
+ */
+require_once 'Zend/Mail/Storage/Folder/Interface.php';
+
+/**
+ * @see Zend_Mail_Storage_Mbox
+ */
+require_once 'Zend/Mail/Storage/Mbox.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Zend_Mail_Storage_Folder_Interface
+{
+    /**
+     * Zend_Mail_Storage_Folder root folder for folder structure
+     * @var Zend_Mail_Storage_Folder
+     */
+    protected $_rootFolder;
+
+    /**
+     * rootdir of folder structure
+     * @var string
+     */
+    protected $_rootdir;
+
+    /**
+     * name of current folder
+     * @var string
+     */
+    protected $_currentFolder;
+
+    /**
+     * Create instance with parameters
+     *
+     * Disallowed parameters are:
+     *   - filename use Zend_Mail_Storage_Mbox for a single file
+     * Supported parameters are:
+     *   - dirname rootdir of mbox structure
+     *   - folder intial selected folder, default is 'INBOX'
+     *
+     * @param  $params array mail reader specific parameters
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function __construct($params)
+    {
+        if (is_array($params)) {
+            $params = (object)$params;
+        }
+
+        if (isset($params->filename)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('use Zend_Mail_Storage_Mbox for a single file');
+        }
+
+        if (!isset($params->dirname) || !is_dir($params->dirname)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('no valid dirname given in params');
+        }
+
+        $this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
+
+        $this->_buildFolderTree($this->_rootdir);
+        $this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX');
+        $this->_has['top']      = true;
+        $this->_has['uniqueid'] = false;
+    }
+
+    /**
+     * find all subfolders and mbox files for folder structure
+     *
+     * Result is save in Zend_Mail_Storage_Folder instances with the root in $this->_rootFolder.
+     * $parentFolder and $parentGlobalName are only used internally for recursion.
+     *
+     * @param string $currentDir call with root dir, also used for recursion.
+     * @param Zend_Mail_Storage_Folder|null $parentFolder used for recursion
+     * @param string $parentGlobalName used for rescursion
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    protected function _buildFolderTree($currentDir, $parentFolder = null, $parentGlobalName = '')
+    {
+        if (!$parentFolder) {
+            $this->_rootFolder = new Zend_Mail_Storage_Folder('/', '/', false);
+            $parentFolder = $this->_rootFolder;
+        }
+
+        $dh = @opendir($currentDir);
+        if (!$dh) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception("can't read dir $currentDir");
+        }
+        while (($entry = readdir($dh)) !== false) {
+            // ignore hidden files for mbox
+            if ($entry[0] == '.') {
+                continue;
+            }
+            $absoluteEntry = $currentDir . $entry;
+            $globalName = $parentGlobalName . DIRECTORY_SEPARATOR . $entry;
+            if (is_file($absoluteEntry) && $this->_isMboxFile($absoluteEntry)) {
+                $parentFolder->$entry = new Zend_Mail_Storage_Folder($entry, $globalName);
+                continue;
+            }
+            if (!is_dir($absoluteEntry) /* || $entry == '.' || $entry == '..' */) {
+                continue;
+            }
+            $folder = new Zend_Mail_Storage_Folder($entry, $globalName, false);
+            $parentFolder->$entry = $folder;
+            $this->_buildFolderTree($absoluteEntry . DIRECTORY_SEPARATOR, $folder, $globalName);
+        }
+
+        closedir($dh);
+    }
+
+    /**
+     * get root folder or given folder
+     *
+     * @param string $rootFolder get folder structure for given folder, else root
+     * @return Zend_Mail_Storage_Folder root or wanted folder
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getFolders($rootFolder = null)
+    {
+        if (!$rootFolder) {
+            return $this->_rootFolder;
+        }
+
+        $currentFolder = $this->_rootFolder;
+        $subname = trim($rootFolder, DIRECTORY_SEPARATOR);
+        while ($currentFolder) {
+            @list($entry, $subname) = @explode(DIRECTORY_SEPARATOR, $subname, 2);
+            $currentFolder = $currentFolder->$entry;
+            if (!$subname) {
+                break;
+            }
+        }
+
+        if ($currentFolder->getGlobalName() != DIRECTORY_SEPARATOR . trim($rootFolder, DIRECTORY_SEPARATOR)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception("folder $rootFolder not found");
+        }
+        return $currentFolder;
+    }
+
+    /**
+     * select given folder
+     *
+     * folder must be selectable!
+     *
+     * @param Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function selectFolder($globalName)
+    {
+        $this->_currentFolder = (string)$globalName;
+
+        // getting folder from folder tree for validation
+        $folder = $this->getFolders($this->_currentFolder);
+
+        try {
+            $this->_openMboxFile($this->_rootdir . $folder->getGlobalName());
+        } catch(Zend_Mail_Storage_Exception $e) {
+            // check what went wrong
+            if (!$folder->isSelectable()) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable");
+            }
+            // seems like file has vanished; rebuilding folder tree - but it's still an exception
+            $this->_buildFolderTree($this->_rootdir);
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('seems like the mbox file has vanished, I\'ve rebuild the ' .
+                                                         'folder tree, search for an other folder and try again');
+        }
+    }
+
+    /**
+     * get Zend_Mail_Storage_Folder instance for current folder
+     *
+     * @return Zend_Mail_Storage_Folder instance of current folder
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getCurrentFolder()
+    {
+        return $this->_currentFolder;
+    }
+
+    /**
+     * magic method for serialize()
+     *
+     * with this method you can cache the mbox class
+     *
+     * @return array name of variables
+     */
+    public function __sleep()
+    {
+        return array_merge(parent::__sleep(), array('_currentFolder', '_rootFolder', '_rootdir'));
+    }
+
+    /**
+     * magic method for unserialize()
+     *
+     * with this method you can cache the mbox class
+     *
+     * @return null
+     */
+    public function __wakeup()
+    {
+        // if cache is stall selectFolder() rebuilds the tree on error
+        parent::__wakeup();
+    }
+}
Index: libs/Zend/Mail/Storage/Imap.php
===================================================================
--- libs/Zend/Mail/Storage/Imap.php	(wersja 0)
+++ libs/Zend/Mail/Storage/Imap.php	(wersja 0)
@@ -0,0 +1,608 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Imap.php 8928 2008-03-20 19:41:41Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Storage_Abstract
+ */
+require_once 'Zend/Mail/Storage/Abstract.php';
+
+/**
+ * @see Zend_Mail_Protocol_Imap
+ */
+require_once 'Zend/Mail/Protocol/Imap.php';
+
+/**
+ * @see Zend_Mail_Storage_Writable_Interface
+ */
+require_once 'Zend/Mail/Storage/Writable/Interface.php';
+
+/**
+ * @see Zend_Mail_Storage_Folder_Interface
+ */
+require_once 'Zend/Mail/Storage/Folder/Interface.php';
+
+/**
+ * @see Zend_Mail_Storage_Folder
+ */
+require_once 'Zend/Mail/Storage/Folder.php';
+
+/**
+ * @see Zend_Mail_Message
+ */
+require_once 'Zend/Mail/Message.php';
+
+/**
+ * @see Zend_Mail_Storage
+ */
+require_once 'Zend/Mail/Storage.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
+                             implements Zend_Mail_Storage_Folder_Interface, Zend_Mail_Storage_Writable_Interface
+{
+    // TODO: with an internal cache we could optimize this class, or create an extra class with
+    // such optimizations. Especially the various fetch calls could be combined to one cache call
+
+    /**
+     * protocol handler
+     * @var null|Zend_Mail_Protocol_Imap
+     */
+    protected $_protocol;
+
+    /**
+     * name of current folder
+     * @var string
+     */
+    protected $_currentFolder = '';
+
+    /**
+     * imap flags to constants translation
+     * @var array
+     */
+    protected static $_knownFlags = array('\Passed'   => Zend_Mail_Storage::FLAG_PASSED,
+                                          '\Answered' => Zend_Mail_Storage::FLAG_ANSWERED,
+                                          '\Seen'     => Zend_Mail_Storage::FLAG_SEEN,
+                                          '\Deleted'  => Zend_Mail_Storage::FLAG_DELETED,
+                                          '\Draft'    => Zend_Mail_Storage::FLAG_DRAFT,
+                                          '\Flagged'  => Zend_Mail_Storage::FLAG_FLAGGED);
+
+    /**
+     * Count messages all messages in current box
+     *
+     * @return int number of messages
+     * @throws Zend_Mail_Storage_Exception
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function countMessages()
+    {
+        if (!$this->_currentFolder) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('No selected folder to count');
+        }
+
+        // we're reselecting the current mailbox, because STATUS is slow and shouldn't be used on the current mailbox
+        $result = $this->_protocol->select($this->_currentFolder);
+        return $result['exists'];
+    }
+
+    /**
+     * get a list of messages with number and size
+     *
+     * @param int $id number of message
+     * @return int|array size of given message of list with all messages as array(num => size)
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function getSize($id = 0)
+    {
+        if ($id) {
+            return $this->_protocol->fetch('RFC822.SIZE', $id);
+        }
+        return $this->_protocol->fetch('RFC822.SIZE', 1, INF);
+    }
+
+    /**
+     * Fetch a message
+     *
+     * @param int $id number of message
+     * @return Zend_Mail_Message
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function getMessage($id)
+    {
+        $data = $this->_protocol->fetch(array('FLAGS', 'RFC822.HEADER'), $id);
+        $header = $data['RFC822.HEADER'];
+
+        $flags = array();
+        foreach ($data['FLAGS'] as $flag) {
+            $flags[] = isset(self::$_knownFlags[$flag]) ? self::$_knownFlags[$flag] : $flag;
+        }
+
+        return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $header, 'flags' => $flags));
+    }
+
+    /*
+     * Get raw header of message or part
+     *
+     * @param  int               $id       number of message
+     * @param  null|array|string $part     path to part or null for messsage header
+     * @param  int               $topLines include this many lines with header (after an empty line)
+     * @param  int $topLines include this many lines with header (after an empty line)
+     * @return string raw header
+     * @throws Zend_Mail_Protocol_Exception
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getRawHeader($id, $part = null, $topLines = 0)
+    {
+        if ($part !== null) {
+            // TODO: implement
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('not implemented');
+        }
+
+        // TODO: toplines
+        return $this->_protocol->fetch('RFC822.HEADER', $id);
+    }
+
+    /*
+     * Get raw content of message or part
+     *
+     * @param  int               $id   number of message
+     * @param  null|array|string $part path to part or null for messsage content
+     * @return string raw content
+     * @throws Zend_Mail_Protocol_Exception
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getRawContent($id, $part = null)
+    {
+        if ($part !== null) {
+            // TODO: implement
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('not implemented');
+        }
+
+        return $this->_protocol->fetch('RFC822.TEXT', $id);
+    }
+
+    /**
+     * create instance with parameters
+     * Supported paramters are
+     *   - user username
+     *   - host hostname or ip address of IMAP server [optional, default = 'localhost']
+     *   - password password for user 'username' [optional, default = '']
+     *   - port port for IMAP server [optional, default = 110]
+     *   - ssl 'SSL' or 'TLS' for secure sockets
+     *   - folder select this folder [optional, default = 'INBOX']
+     *
+     * @param  array $params mail reader specific parameters
+     * @throws Zend_Mail_Storage_Exception
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function __construct($params)
+    {
+        if (is_array($params)) {
+            $params = (object)$params;
+        }
+
+        $this->_has['flags'] = true;
+
+        if ($params instanceof Zend_Mail_Protocol_Imap) {
+            $this->_protocol = $params;
+            try {
+                $this->selectFolder('INBOX');
+            } catch(Zend_Mail_Storage_Exception $e) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception('cannot select INBOX, is this a valid transport?');
+            }
+            return;
+        }
+
+        if (!isset($params->user)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('need at least user in params');
+        }
+
+        $host     = isset($params->host)     ? $params->host     : 'localhost';
+        $password = isset($params->password) ? $params->password : '';
+        $port     = isset($params->port)     ? $params->port     : null;
+        $ssl      = isset($params->ssl)      ? $params->ssl      : false;
+
+        $this->_protocol = new Zend_Mail_Protocol_Imap();
+        $this->_protocol->connect($host, $port, $ssl);
+        if (!$this->_protocol->login($params->user, $password)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot login, user or password wrong');
+        }
+        $this->selectFolder(isset($params->folder) ? $params->folder : 'INBOX');
+    }
+
+    /**
+     * Close resource for mail lib. If you need to control, when the resource
+     * is closed. Otherwise the destructor would call this.
+     *
+     * @return null
+     */
+    public function close()
+    {
+        $this->_currentFolder = '';
+        $this->_protocol->logout();
+    }
+
+    /**
+     * Keep the server busy.
+     *
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function noop()
+    {
+        if (!$this->_protocol->noop()) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('could not do nothing');
+        }
+    }
+
+    /**
+     * Remove a message from server. If you're doing that from a web enviroment
+     * you should be careful and use a uniqueid as parameter if possible to
+     * identify the message.
+     *
+     * @param   int $id number of message
+     * @return  null
+     * @throws  Zend_Mail_Storage_Exception
+     */
+    public function removeMessage($id)
+    {
+        if (!$this->_protocol->store(array(Zend_Mail_Storage::FLAG_DELETED), $id, null, '+')) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot set deleted flag');
+        }
+        // TODO: expunge here or at close? we can handle an error here better and are more fail safe
+        if (!$this->_protocol->expunge()) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('message marked as deleted, but could not expunge');
+        }
+    }
+
+    /**
+     * get unique id for one or all messages
+     *
+     * if storage does not support unique ids it's the same as the message number
+     *
+     * @param int|null $id message number
+     * @return array|string message number for given message or all messages as array
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getUniqueId($id = null)
+    {
+        if ($id) {
+            return $this->_protocol->fetch('UID', $id);
+        }
+
+        return $this->_protocol->fetch('UID', 1, INF);
+    }
+
+    /**
+     * get a message number from a unique id
+     *
+     * I.e. if you have a webmailer that supports deleting messages you should use unique ids
+     * as parameter and use this method to translate it to message number right before calling removeMessage()
+     *
+     * @param string $id unique id
+     * @return int message number
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getNumberByUniqueId($id)
+    {
+        // TODO: use search to find number directly
+        $ids = $this->getUniqueId();
+        foreach ($ids as $k => $v) {
+            if ($v == $id) {
+                return $k;
+            }
+        }
+
+        /**
+         * @see Zend_Mail_Storage_Exception
+         */
+        require_once 'Zend/Mail/Storage/Exception.php';
+        throw new Zend_Mail_Storage_Exception('unique id not found');
+    }
+
+
+    /**
+     * get root folder or given folder
+     *
+     * @param  string $rootFolder get folder structure for given folder, else root
+     * @return Zend_Mail_Storage_Folder root or wanted folder
+     * @throws Zend_Mail_Storage_Exception
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function getFolders($rootFolder = null)
+    {
+        $folders = $this->_protocol->listMailbox((string)$rootFolder);
+        if (!$folders) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('folder not found');
+        }
+
+        ksort($folders, SORT_STRING);
+        $root = new Zend_Mail_Storage_Folder('/', '/', false);
+        $stack = array(null);
+        $folderStack = array(null);
+        $parentFolder = $root;
+        $parent = '';
+
+        foreach ($folders as $globalName => $data) {
+            do {
+                if (!$parent || strpos($globalName, $parent) === 0) {
+                    $pos = strrpos($globalName, $data['delim']);
+                    if ($pos === false) {
+                        $localName = $globalName;
+                    } else {
+                        $localName = substr($globalName, $pos + 1);
+                    }
+                    $selectable = !$data['flags'] || !in_array('\\Noselect', $data['flags']);
+
+                    array_push($stack, $parent);
+                    $parent = $globalName . $data['delim'];
+                    $folder = new Zend_Mail_Storage_Folder($localName, $globalName, $selectable);
+                    $parentFolder->$localName = $folder;
+                    array_push($folderStack, $parentFolder);
+                    $parentFolder = $folder;
+                    break;
+                } else if ($stack) {
+                    $parent = array_pop($stack);
+                    $parentFolder = array_pop($folderStack);
+                }
+            } while ($stack);
+            if (!$stack) {
+                /**
+                 * @see Zend_Mail_Storage_Exception
+                 */
+                require_once 'Zend/Mail/Storage/Exception.php';
+                throw new Zend_Mail_Storage_Exception('error while constructing folder tree');
+            }
+        }
+
+        return $root;
+    }
+
+    /**
+     * select given folder
+     *
+     * folder must be selectable!
+     *
+     * @param  Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     * @throws Zend_Mail_Protocol_Exception
+     */
+    public function selectFolder($globalName)
+    {
+        $this->_currentFolder = $globalName;
+        if (!$this->_protocol->select($this->_currentFolder)) {
+            $this->_currentFolder = '';
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot change folder, maybe it does not exist');
+        }
+    }
+
+
+    /**
+     * get Zend_Mail_Storage_Folder instance for current folder
+     *
+     * @return Zend_Mail_Storage_Folder instance of current folder
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function getCurrentFolder()
+    {
+        return $this->_currentFolder;
+    }
+
+    /**
+     * create a new folder
+     *
+     * This method also creates parent folders if necessary. Some mail storages may restrict, which folder
+     * may be used as parent or which chars may be used in the folder name
+     *
+     * @param  string                          $name         global name of folder, local name if $parentFolder is set
+     * @param  string|Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function createFolder($name, $parentFolder = null)
+    {
+        // TODO: we assume / as the hierarchy delim - need to get that from the folder class!
+        if ($parentFolder instanceof Zend_Mail_Storage_Folder) {
+            $folder = $parentFolder->getGlobalName() . '/' . $name;
+        } else if ($parentFolder != null) {
+            $folder = $parentFolder . '/' . $name;
+        } else {
+            $folder = $name;
+        }
+
+        if (!$this->_protocol->create($folder)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot create folder');
+        }
+    }
+
+    /**
+     * remove a folder
+     *
+     * @param  string|Zend_Mail_Storage_Folder $name      name or instance of folder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function removeFolder($name)
+    {
+        if ($name instanceof Zend_Mail_Storage_Folder) {
+            $name = $name->getGlobalName();
+        }
+
+        if (!$this->_protocol->delete($name)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot delete folder');
+        }
+    }
+
+    /**
+     * rename and/or move folder
+     *
+     * The new name has the same restrictions as in createFolder()
+     *
+     * @param  string|Zend_Mail_Storage_Folder $oldName name or instance of folder
+     * @param  string                          $newName new global name of folder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function renameFolder($oldName, $newName)
+    {
+        if ($oldName instanceof Zend_Mail_Storage_Folder) {
+            $oldName = $oldName->getGlobalName();
+        }
+
+        if (!$this->_protocol->rename($oldName, $newName)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot rename folder');
+        }
+    }
+
+    /**
+     * append a new message to mail storage
+     *
+     * @param  string                                     $message message as string or instance of message class
+     * @param  null|string|Zend_Mail_Storage_Folder       $folder  folder for new message, else current folder is taken
+     * @param  null|array                                 $flags   set flags for new message, else a default set is used
+     * @throws Zend_Mail_Storage_Exception
+     */
+     // not yet * @param string|Zend_Mail_Message|Zend_Mime_Message $message message as string or instance of message class
+    public function appendMessage($message, $folder = null, $flags = null)
+    {
+        if ($folder === null) {
+            $folder = $this->_currentFolder;
+        }
+
+        if ($flags === null) {
+            $flags = array(Zend_Mail_Storage::FLAG_SEEN);
+        }
+
+        // TODO: handle class instances for $message
+        if (!$this->_protocol->append($folder, $message, $flags)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot create message, please check if the folder exists and your flags');
+        }
+    }
+
+    /**
+     * copy an existing message
+     *
+     * @param  int                             $id     number of message
+     * @param  string|Zend_Mail_Storage_Folder $folder name or instance of targer folder
+     * @return null
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function copyMessage($id, $folder)
+    {
+        if (!$this->_protocol->copy($folder, $id)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot copy message, does the folder exist?');
+        }
+    }
+
+
+    /**
+     * set flags for message
+     *
+     * NOTE: this method can't set the recent flag.
+     *
+     * @param  int   $id    number of message
+     * @param  array $flags new flags for message
+     * @throws Zend_Mail_Storage_Exception
+     */
+    public function setFlags($id, $flags)
+    {
+        if (!$this->_protocol->store($flags, $id)) {
+            /**
+             * @see Zend_Mail_Storage_Exception
+             */
+            require_once 'Zend/Mail/Storage/Exception.php';
+            throw new Zend_Mail_Storage_Exception('cannot set flags, have you tried to set the recent flag or special chars?');
+        }
+    }
+}
+
Index: libs/Zend/Mail/Exception.php
===================================================================
--- libs/Zend/Mail/Exception.php	(wersja 0)
+++ libs/Zend/Mail/Exception.php	(wersja 0)
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Exception
+ */
+require_once 'Zend/Exception.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Exception extends Zend_Exception
+{}
+
Index: libs/Zend/Mail/Storage.php
===================================================================
--- libs/Zend/Mail/Storage.php	(wersja 0)
+++ libs/Zend/Mail/Storage.php	(wersja 0)
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Storage.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Storage
+{
+    // maildir and IMAP flags, using IMAP names, where possible to be able to distinguish between IMAP
+    // system flags and other flags
+    const FLAG_PASSED   = 'Passed';
+    const FLAG_SEEN     = '\Seen';
+    const FLAG_ANSWERED = '\Answered';
+    const FLAG_FLAGGED  = '\Flagged';
+    const FLAG_DELETED  = '\Deleted';
+    const FLAG_DRAFT    = '\Draft';
+    const FLAG_RECENT   = '\Recent';
+}
Index: libs/Zend/Mail/Message.php
===================================================================
--- libs/Zend/Mail/Message.php	(wersja 0)
+++ libs/Zend/Mail/Message.php	(wersja 0)
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Message.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * Zend_Mail_Part
+ */
+require_once 'Zend/Mail/Part.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Message extends Zend_Mail_Part
+{
+    /**
+     * flags for this message
+     * @var array
+     */
+    protected $_flags = array();
+
+    /**
+     * Public constructor
+     *
+     * In addition to the parameters of Zend_Mail_Part::__construct() this constructor supports:
+     * - file  filename or file handle of a file with raw message content
+     * - flags array with flags for message, keys are ignored, use constants defined in Zend_Mail_Storage
+     *
+     * @param  string $rawMessage  full message with or without headers
+     * @throws Zend_Mail_Exception
+     */
+    public function __construct(array $params)
+    {
+        if (isset($params['file'])) {
+            if (!is_resource($params['file'])) {
+                $params['raw'] = @file_get_contents($params['file']);
+                if ($params['raw'] === false) {
+                    /**
+                     * @see Zend_Mail_Exception
+                     */
+                    require_once 'Zend/Mail/Exception.php';
+                    throw new Zend_Mail_Exception('could not open file');
+                }
+            } else {
+                $params['raw'] = stream_get_contents($params['file']);
+            }
+        }
+
+        if (!empty($params['flags'])) {
+            // set key and value to the same value for easy lookup
+            $this->_flags = array_combine($params['flags'], $params['flags']);
+        }
+
+        parent::__construct($params);
+    }
+
+    /**
+     * return toplines as found after headers
+     *
+     * @return string toplines
+     */
+    public function getTopLines()
+    {
+        return $this->_topLines;
+    }
+
+    /**
+     * check if flag is set
+     *
+     * @param mixed $flag a flag name, use constants defined in Zend_Mail_Storage
+     * @return bool true if set, otherwise false
+     */
+    public function hasFlag($flag)
+    {
+        return isset($this->_flags[$flag]);
+    }
+
+    /**
+     * get all set flags
+     *
+     * @return array array with flags, key and value are the same for easy lookup
+     */
+    public function getFlags()
+    {
+        return $this->_flags;
+    }
+}
Index: libs/Zend/Mail/Transport/Sendmail.php
===================================================================
--- libs/Zend/Mail/Transport/Sendmail.php	(wersja 0)
+++ libs/Zend/Mail/Transport/Sendmail.php	(wersja 0)
@@ -0,0 +1,170 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Transport
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Sendmail.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Transport_Abstract
+ */
+require_once 'Zend/Mail/Transport/Abstract.php';
+
+
+/**
+ * Class for sending eMails via the PHP internal mail() function
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Transport
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
+{
+    /**
+     * Subject
+     * @var string
+     * @access public
+     */
+    public $subject = null;
+
+
+    /**
+     * Config options for sendmail parameters
+     *
+     * @var string
+     */
+    public $parameters;
+
+
+    /**
+     * EOL character string
+     * @var string
+     * @access public
+     */
+    public $EOL = PHP_EOL;
+
+
+    /**
+     * Constructor.
+     *
+     * @param  string $parameters OPTIONAL (Default: null)
+     * @return void
+     */
+    public function __construct($parameters = null)
+    {
+        $this->parameters = $parameters;
+    }
+
+
+    /**
+     * Send mail using PHP native mail()
+     *
+     * @access public
+     * @return void
+     * @throws Zend_Mail_Transport_Exception on mail() failure
+     */
+    public function _sendMail()
+    {
+        if ($this->parameters === null) {
+            $result = mail(
+                $this->recipients,
+                $this->_mail->getSubject(),
+                $this->body,
+                $this->header);
+        } else {
+            $result = mail(
+                $this->recipients,
+                $this->_mail->getSubject(),
+                $this->body,
+                $this->header,
+                $this->parameters);
+        }
+        if (!$result) {
+            /**
+             * @see Zend_Mail_Transport_Exception
+             */
+            require_once 'Zend/Mail/Transport/Exception.php';
+            throw new Zend_Mail_Transport_Exception('Unable to send mail');
+        }
+    }
+
+
+    /**
+     * Format and fix headers
+     *
+     * mail() uses its $to and $subject arguments to set the To: and Subject:
+     * headers, respectively. This method strips those out as a sanity check to
+     * prevent duplicate header entries.
+     *
+     * @access  protected
+     * @param   array $headers
+     * @return  void
+     * @throws  Zend_Mail_Transport_Exception
+     */
+    protected function _prepareHeaders($headers)
+    {
+        if (!$this->_mail) {
+            /**
+             * @see Zend_Mail_Transport_Exception
+             */
+            require_once 'Zend/Mail/Transport/Exception.php';
+            throw new Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Zend_Mail object');
+        }
+
+        // mail() uses its $to parameter to set the To: header, and the $subject
+        // parameter to set the Subject: header. We need to strip them out.
+        if (0 === strpos(PHP_OS, 'WIN')) {
+            // If the current recipients list is empty, throw an error
+            if (empty($this->recipients)) {
+                /**
+                 * @see Zend_Mail_Transport_Exception
+                 */
+                require_once 'Zend/Mail/Transport/Exception.php';
+                throw new Zend_Mail_Transport_Exception('Missing To addresses');
+            }
+        } else {
+            // All others, simply grab the recipients and unset the To: header
+            if (!isset($headers['To'])) {
+                /**
+                 * @see Zend_Mail_Transport_Exception
+                 */
+                require_once 'Zend/Mail/Transport/Exception.php';
+                throw new Zend_Mail_Transport_Exception('Missing To header');
+            }
+
+            unset($headers['To']['append']);
+            $this->recipients = implode(',', $headers['To']);
+        }
+
+        // Remove recipient header
+        unset($headers['To']);
+
+        // Remove subject header, if present
+        if (isset($headers['Subject'])) {
+            unset($headers['Subject']);
+        }
+
+        // Prepare headers
+        parent::_prepareHeaders($headers);
+    }
+
+}
+
Index: libs/Zend/Mail/Transport/Exception.php
===================================================================
--- libs/Zend/Mail/Transport/Exception.php	(wersja 0)
+++ libs/Zend/Mail/Transport/Exception.php	(wersja 0)
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Transport
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Exception
+ */
+require_once 'Zend/Mail/Exception.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Transport
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Transport_Exception extends Zend_Mail_Exception
+{}
+
Index: libs/Zend/Mail/Transport/Abstract.php
===================================================================
--- libs/Zend/Mail/Transport/Abstract.php	(wersja 0)
+++ libs/Zend/Mail/Transport/Abstract.php	(wersja 0)
@@ -0,0 +1,350 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Transport
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Abstract.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mime
+ */
+require_once 'Zend/Mime.php';
+
+
+/**
+ * Abstract for sending eMails through different
+ * ways of transport
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Transport
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+abstract class Zend_Mail_Transport_Abstract 
+{
+    /**
+     * Mail body
+     * @var string
+     * @access public
+     */
+    public $body = '';
+
+    /**
+     * MIME boundary
+     * @var string
+     * @access public
+     */
+    public $boundary = '';
+
+    /**
+     * Mail header string
+     * @var string
+     * @access public
+     */
+    public $header = '';
+
+    /**
+     * Array of message headers
+     * @var array
+     * @access protected
+     */
+    protected $_headers = array();
+
+    /**
+     * Message is a multipart message
+     * @var boolean
+     * @access protected
+     */
+    protected $_isMultipart = false;
+
+    /**
+     * Zend_Mail object
+     * @var false|Zend_Mail
+     * @access protected
+     */
+    protected $_mail = false;
+
+    /**
+     * Array of message parts
+     * @var array
+     * @access protected
+     */
+    protected $_parts = array();
+
+    /**
+     * Recipients string
+     * @var string
+     * @access public
+     */
+    public $recipients = '';
+
+    /**
+     * EOL character string used by transport
+     * @var string
+     * @access public
+     */
+    public $EOL = "\r\n";
+
+    /**
+     * Send an email independent from the used transport
+     *
+     * The requisite information for the email will be found in the following
+     * properties:
+     *
+     * - {@link $recipients} - list of recipients (string)
+     * - {@link $header} - message header
+     * - {@link $body} - message body
+     */
+    abstract protected function _sendMail();
+
+    /**
+     * Return all mail headers as an array
+     *
+     * If a boundary is given, a multipart header is generated with a
+     * Content-Type of either multipart/alternative or multipart/mixed depending
+     * on the mail parts present in the {@link $_mail Zend_Mail object} present.
+     *
+     * @param string $boundary
+     * @return array
+     */
+    protected function _getHeaders($boundary)
+    {
+        if (null !== $boundary) {
+            // Build multipart mail
+            $type = $this->_mail->getType();
+            if (!$type) {
+                if ($this->_mail->hasAttachments) {
+                    $type = Zend_Mime::MULTIPART_MIXED;
+                } elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml()) {
+                    $type = Zend_Mime::MULTIPART_ALTERNATIVE;
+                } else {
+                    $type = Zend_Mime::MULTIPART_MIXED;
+                }
+            }
+
+            $this->_headers['Content-Type'] = array(
+                $type . '; charset="' . $this->_mail->getCharset() . '";'
+                . $this->EOL
+                . " " . 'boundary="' . $boundary . '"'
+            );
+            $this->_headers['MIME-Version'] = array('1.0');
+
+            $this->boundary = $boundary;
+        }
+
+        return $this->_headers;
+    }
+
+    /**
+     * Prepend header name to header value
+     *
+     * @param string $item
+     * @param string $key
+     * @param string $prefix
+     * @static
+     * @access protected
+     * @return void
+     */
+    protected static function _formatHeader(&$item, $key, $prefix)
+    {
+        $item = $prefix . ': ' . $item;
+    }
+
+    /**
+     * Prepare header string for use in transport
+     *
+     * Prepares and generates {@link $header} based on the headers provided.
+     *
+     * @param mixed $headers
+     * @access protected
+     * @return void
+     * @throws Zend_Mail_Transport_Exception if any header lines exceed 998
+     * characters
+     */
+    protected function _prepareHeaders($headers)
+    {
+        if (!$this->_mail) {
+            /**
+             * @see Zend_Mail_Transport_Exception
+             */
+            require_once 'Zend/Mail/Transport/Exception.php';
+            throw new Zend_Mail_Transport_Exception('Missing Zend_Mail object in _mail property');
+        }
+
+        $this->header = '';
+
+        foreach ($headers as $header => $content) {
+            if (isset($content['append'])) {
+                unset($content['append']);
+                $value = implode(',' . $this->EOL . ' ', $content);
+                $this->header .= $header . ': ' . $value . $this->EOL;
+            } else {
+                array_walk($content, array(get_class($this), '_formatHeader'), $header);
+                $this->header .= implode($this->EOL, $content) . $this->EOL;
+            }
+        }
+
+        // Sanity check on headers -- should not be > 998 characters
+        $sane = true;
+        foreach (explode($this->EOL, $this->header) as $line) {
+            if (strlen(trim($line)) > 998) {
+                $sane = false;
+                break;
+            }
+        }
+        if (!$sane) {
+            /**
+             * @see Zend_Mail_Transport_Exception
+             */
+            require_once 'Zend/Mail/Transport/Exception.php';
+            throw new Zend_Mail_Exception('At least one mail header line is too long');
+        }
+    }
+
+    /**
+     * Generate MIME compliant message from the current configuration
+     *
+     * If both a text and HTML body are present, generates a
+     * multipart/alternative Zend_Mime_Part containing the headers and contents
+     * of each. Otherwise, uses whichever of the text or HTML parts present.
+     *
+     * The content part is then prepended to the list of Zend_Mime_Parts for
+     * this message.
+     *
+     * @return void
+     */
+    protected function _buildBody()
+    {
+        if (($text = $this->_mail->getBodyText())
+            && ($html = $this->_mail->getBodyHtml()))
+        {
+            // Generate unique boundary for multipart/alternative
+            $mime = new Zend_Mime(null);
+            $boundaryLine = $mime->boundaryLine($this->EOL);
+            $boundaryEnd  = $mime->mimeEnd($this->EOL);
+
+            $text->disposition = false;
+            $html->disposition = false;
+
+            $body = $boundaryLine
+                  . $text->getHeaders($this->EOL)
+                  . $this->EOL
+                  . $text->getContent($this->EOL)
+                  . $this->EOL
+                  . $boundaryLine
+                  . $html->getHeaders($this->EOL)
+                  . $this->EOL
+                  . $html->getContent($this->EOL)
+                  . $this->EOL
+                  . $boundaryEnd;
+
+            $mp           = new Zend_Mime_Part($body);
+            $mp->type     = Zend_Mime::MULTIPART_ALTERNATIVE;
+            $mp->boundary = $mime->boundary();
+
+            $this->_isMultipart = true;
+
+            // Ensure first part contains text alternatives
+            array_unshift($this->_parts, $mp);
+
+            // Get headers
+            $this->_headers = $this->_mail->getHeaders();
+            return;
+        }
+
+        // If not multipart, then get the body
+        if (false !== ($body = $this->_mail->getBodyHtml())) {
+            array_unshift($this->_parts, $body);
+        } elseif (false !== ($body = $this->_mail->getBodyText())) {
+            array_unshift($this->_parts, $body);
+        }
+
+        if (!$body) {
+            /**
+             * @see Zend_Mail_Transport_Exception
+             */
+            require_once 'Zend/Mail/Transport/Exception.php';
+            throw new Zend_Mail_Transport_Exception('No body specified');
+        }
+
+        // Get headers
+        $this->_headers = $this->_mail->getHeaders();
+        $headers = $body->getHeadersArray($this->EOL);
+        foreach ($headers as $header) {
+            // Headers in Zend_Mime_Part are kept as arrays with two elements, a
+            // key and a value
+            $this->_headers[$header[0]] = array($header[1]);
+        }
+    }
+
+    /**
+     * Send a mail using this transport
+     *
+     * @param  Zend_Mail $mail
+     * @access public
+     * @return void
+     * @throws Zend_Mail_Transport_Exception if mail is empty
+     */
+    public function send(Zend_Mail $mail)
+    {
+        $this->_isMultipart = false;
+        $this->_mail        = $mail;
+        $this->_parts       = $mail->getParts();
+        $mime               = $mail->getMime();
+
+        // Build body content
+        $this->_buildBody();
+
+        // Determine number of parts and boundary
+        $count    = count($this->_parts);
+        $boundary = null;
+        if ($count < 1) {
+            /**
+             * @see Zend_Mail_Transport_Exception
+             */
+            require_once 'Zend/Mail/Transport/Exception.php';
+            throw new Zend_Mail_Transport_Exception('Empty mail cannot be sent');
+        }
+
+        if ($count > 1) {
+            // Multipart message; create new MIME object and boundary
+            $mime     = new Zend_Mime($this->_mail->getMimeBoundary());
+            $boundary = $mime->boundary();
+        } elseif ($this->_isMultipart) {
+            // multipart/alternative -- grab boundary
+            $boundary = $this->_parts[0]->boundary;
+        }
+
+        // Determine recipients, and prepare headers
+        $this->recipients = implode(',', $mail->getRecipients());
+        $this->_prepareHeaders($this->_getHeaders($boundary));
+
+        // Create message body
+        // This is done so that the same Zend_Mail object can be used in
+        // multiple transports
+        $message = new Zend_Mime_Message();
+        $message->setParts($this->_parts);
+        $message->setMime($mime);
+        $this->body = $message->generateMessage($this->EOL);
+
+        // Send to transport!
+        $this->_sendMail();
+    }
+}
Index: libs/Zend/Mail/Transport/Smtp.php
===================================================================
--- libs/Zend/Mail/Transport/Smtp.php	(wersja 0)
+++ libs/Zend/Mail/Transport/Smtp.php	(wersja 0)
@@ -0,0 +1,241 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ * 
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Transport
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Smtp.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Loader
+ */
+require_once 'Zend/Loader.php';
+
+/**
+ * @see Zend_Mime
+ */
+require_once 'Zend/Mime.php';
+
+/**
+ * @see Zend_Mail_Protocol_Smtp
+ */
+require_once 'Zend/Mail/Protocol/Smtp.php';
+
+/**
+ * @see Zend_Mail_Transport_Abstract
+ */
+require_once 'Zend/Mail/Transport/Abstract.php';
+
+
+/**
+ * SMTP connection object
+ *
+ * Loads an instance of Zend_Mail_Protocol_Smtp and forwards smtp transactions
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @subpackage Transport
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Transport_Smtp extends Zend_Mail_Transport_Abstract
+{
+    /**
+     * EOL character string used by transport
+     * @var string
+     * @access public
+     */
+    public $EOL = "\n";
+
+    /**
+     * Remote smtp hostname or i.p.
+     *
+     * @var string
+     */
+    protected $_host;
+
+
+    /**
+     * Port number
+     *
+     * @var integer|null
+     */
+    protected $_port;
+
+
+    /**
+     * Local client hostname or i.p.
+     *
+     * @var string
+     */
+    protected $_name = 'localhost';
+
+
+    /**
+     * Authentication type OPTIONAL
+     *
+     * @var string
+     */
+    protected $_auth;
+
+
+    /**
+     * Config options for authentication
+     *
+     * @var array
+     */
+    protected $_config;
+
+
+    /**
+     * Instance of Zend_Mail_Protocol_Smtp
+     *
+     * @var Zend_Mail_Protocol_Smtp
+     */
+    protected $_connection;
+
+
+    /**
+     * Constructor.
+     *
+     * @param  string $host OPTIONAL (Default: 127.0.0.1)
+     * @param  array|null $config OPTIONAL (Default: null)
+     * @return void
+     */
+    public function __construct($host = '127.0.0.1', Array $config = array())
+    {
+        if (isset($config['name'])) {
+            $this->_name = $config['name'];
+        }
+        if (isset($config['port'])) {
+            $this->_port = $config['port'];
+        }
+        if (isset($config['auth'])) {
+            $this->_auth = $config['auth'];
+        }
+
+        $this->_host = $host;
+        $this->_config = $config;
+    }
+
+
+    /**
+     * Class destructor to ensure all open connections are closed
+     *
+     * @return void
+     */
+    public function __destruct()
+    {
+        if ($this->_connection instanceof Zend_Mail_Protocol_Smtp) {
+            try {
+                $this->_connection->quit();
+            } catch (Zend_Mail_Protocol_Exception $e) {
+            	// ignore
+            }
+            $this->_connection->disconnect();
+        }
+    }
+
+
+    /**
+     * Sets the connection protocol instance
+     *
+     * @param Zend_Mail_Protocol_Abstract $client
+     *
+     * @return void
+     */
+    public function setConnection(Zend_Mail_Protocol_Abstract $connection)
+    {
+        $this->_connection = $connection;
+    }
+
+
+    /**
+     * Gets the connection protocol instance
+     *
+     * @return Zend_Mail_Protocol|null
+     */
+    public function getConnection()
+    {
+        return $this->_connection;
+    }
+
+    /**
+     * Send an email via the SMTP connection protocol
+     *
+     * The connection via the protocol adapter is made just-in-time to allow a
+     * developer to add a custom adapter if required before mail is sent.
+     *
+     * @return void
+     */
+    public function _sendMail()
+    {
+        // If sending multiple messages per session use existing adapter
+        if (!($this->_connection instanceof Zend_Mail_Protocol_Smtp)) {
+            // Check if authentication is required and determine required class
+            $connectionClass = 'Zend_Mail_Protocol_Smtp';
+            if ($this->_auth) {
+                $connectionClass .= '_Auth_' . ucwords($this->_auth);
+            }
+            Zend_Loader::loadClass($connectionClass);
+            $this->setConnection(new $connectionClass($this->_host, $this->_port, $this->_config));
+            $this->_connection->connect();
+            $this->_connection->helo($this->_name);
+        } else {
+            // Reset connection to ensure reliable transaction
+            $this->_connection->rset();
+        }
+
+        // Set mail return path from sender email address
+        $this->_connection->mail($this->_mail->getReturnPath());
+
+        // Set recipient forward paths
+        foreach ($this->_mail->getRecipients() as $recipient) {
+            $this->_connection->rcpt($recipient);
+        }
+
+        // Issue DATA command to client
+        $this->_connection->data($this->header . Zend_Mime::LINEEND . $this->body);
+    }
+
+    /**
+     * Format and fix headers
+     *
+     * Some SMTP servers do not strip BCC headers. Most clients do it themselves as do we.
+     *
+     * @access  protected
+     * @param   array $headers
+     * @return  void
+     * @throws  Zend_Transport_Exception
+     */
+    protected function _prepareHeaders($headers)
+    {
+        if (!$this->_mail) {
+            /**
+             * @see Zend_Mail_Transport_Exception
+             */
+            require_once 'Zend/Mail/Transport/Exception.php';
+            throw new Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Zend_Mail object');
+        }
+
+        unset($headers['Bcc']);
+
+        // Prepare headers
+        parent::_prepareHeaders($headers);
+    }
+}
Index: libs/Zend/Mail/Part.php
===================================================================
--- libs/Zend/Mail/Part.php	(wersja 0)
+++ libs/Zend/Mail/Part.php	(wersja 0)
@@ -0,0 +1,469 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to version 1.0 of the Zend Framework
+ * license, that is bundled with this package in the file LICENSE.txt, and
+ * is available through the world-wide-web at the following URL:
+ * http://framework.zend.com/license/new-bsd. If you did not receive
+ * a copy of the Zend Framework license and are unable to obtain it
+ * through the world-wide-web, please send a note to license@zend.com
+ * so we can mail you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Part.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mime_Decode
+ */
+require_once 'Zend/Mime/Decode.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail_Part implements RecursiveIterator
+{
+    /**
+     * headers of part as array
+     * @var null|array
+     */
+    protected $_headers;
+
+    /**
+     * raw part body
+     * @var null|string
+     */
+    protected $_content;
+
+    /**
+     * toplines as fetched with headers
+     * @var string
+     */
+    protected $_topLines = '';
+
+    /**
+     * parts of multipart message
+     * @var array
+     */
+    protected $_parts = array();
+
+    /**
+     * count of parts of a multipart message
+     * @var null|int
+     */
+    protected $_countParts;
+
+    /**
+     * current position of iterator
+     * @var int
+     */
+    protected $_iterationPos = 1;
+
+    /**
+     * mail handler, if late fetch is active
+     * @var null|Zend_Mail_Storage_Abstract
+     */
+    protected $_mail;
+
+    /**
+     * message number for mail handler
+     * @var int
+     */
+    protected $_messageNum = 0;
+
+    /**
+     * Public constructor
+     *
+     * Zend_Mail_Part supports different sources for content. The possible params are:
+     * - handler    a instance of Zend_Mail_Storage_Abstract for late fetch
+     * - id         number of message for handler
+     * - raw        raw content with header and body as string
+     * - headers    headers as array (name => value) or string, if a content part is found it's used as toplines
+     * - noToplines ignore content found after headers in param 'headers'
+     * - content    content as string
+     *
+     * @param   array $params  full message with or without headers
+     * @throws  Zend_Mail_Exception
+     */
+    public function __construct(array $params)
+    {
+        if (isset($params['handler'])) {
+            if (!$params['handler'] instanceof Zend_Mail_Storage_Abstract) {
+                /**
+                 * @see Zend_Mail_Exception
+                 */
+                require_once 'Zend/Mail/Exception.php';
+                throw new Zend_Mail_Exception('handler is not a valid mail handler');
+            }
+            if (!isset($params['id'])) {
+                /**
+                 * @see Zend_Mail_Exception
+                 */
+                require_once 'Zend/Mail/Exception.php';
+                throw new Zend_Mail_Exception('need a message id with a handler');
+            }
+
+            $this->_mail       = $params['handler'];
+            $this->_messageNum = $params['id'];
+        }
+
+        if (isset($params['raw'])) {
+            Zend_Mime_Decode::splitMessage($params['raw'], $this->_headers, $this->_content);
+        } else if (isset($params['headers'])) {
+            if (is_array($params['headers'])) {
+                $this->_headers = $params['headers'];
+            } else {
+                if (!empty($params['noToplines'])) {
+                    Zend_Mime_Decode::splitMessage($params['headers'], $this->_headers, $null);
+                } else {
+                    Zend_Mime_Decode::splitMessage($params['headers'], $this->_headers, $this->_topLines);
+                }
+            }
+            if (isset($params['content'])) {
+                $this->_content = $params['content'];
+            }
+        }
+    }
+
+    /**
+     * Check if part is a multipart message
+     *
+     * @return bool if part is multipart
+     */
+    public function isMultipart()
+    {
+        try {
+            return stripos($this->contentType, 'multipart/') === 0;
+        } catch(Zend_Mail_Exception $e) {
+            return false;
+        }
+    }
+
+
+    /**
+     * Body of part
+     *
+     * If part is multipart the raw content of this part with all sub parts is returned
+     *
+     * @return string body
+     * @throws Zend_Mail_Exception
+     */
+    public function getContent()
+    {
+        if ($this->_content !== null) {
+            return $this->_content;
+        }
+
+        if ($this->_mail) {
+            return $this->_mail->getRawContent($this->_messageNum);
+        } else {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('no content');
+        }
+    }
+
+    /**
+     * Cache content and split in parts if multipart
+     *
+     * @return null
+     * @throws Zend_Mail_Exception
+     */
+    protected function _cacheContent()
+    {
+        // caching content if we can't fetch parts
+        if ($this->_content === null && $this->_mail) {
+            $this->_content = $this->_mail->getRawContent($this->_messageNum);
+        }
+
+        if (!$this->isMultipart()) {
+            return;
+        }
+
+        // split content in parts
+        $boundary = $this->getHeaderField('content-type', 'boundary');
+        if (!$boundary) {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('no boundary found in content type to split message');
+        }
+        $parts = Zend_Mime_Decode::splitMessageStruct($this->_content, $boundary);
+        $counter = 1;
+        foreach ($parts as $part) {
+            $this->_parts[$counter++] = new self(array('headers' => $part['header'], 'content' => $part['body']));
+        }
+    }
+
+    /**
+     * Get part of multipart message
+     *
+     * @param  int $num number of part starting with 1 for first part
+     * @return Zend_Mail_Part wanted part
+     * @throws Zend_Mail_Exception
+     */
+    public function getPart($num)
+    {
+        if (isset($this->_parts[$num])) {
+            return $this->_parts[$num];
+        }
+
+        if (!$this->_mail && $this->_content === null) {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('part not found');
+        }
+
+        if ($this->_mail && $this->_mail->hasFetchPart) {
+            // TODO: fetch part
+            // return
+        }
+
+        $this->_cacheContent();
+
+        if (!isset($this->_parts[$num])) {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('part not found');
+        }
+
+        return $this->_parts[$num];
+    }
+
+    /**
+     * Count parts of a multipart part
+     *
+     * @return int number of sub-parts
+     */
+    public function countParts()
+    {
+        if ($this->_countParts) {
+            return $this->_countParts;
+        }
+
+        $this->_countParts = count($this->_parts);
+        if ($this->_countParts) {
+            return $this->_countParts;
+        }
+
+        if ($this->_mail && $this->_mail->hasFetchPart) {
+            // TODO: fetch part
+            // return
+        }
+
+        $this->_cacheContent();
+
+        $this->_countParts = count($this->_parts);
+        return $this->_countParts;
+    }
+
+
+    /**
+     * Get all headers
+     *
+     * The returned headers are as saved internally. All names are lowercased. The value is a string or an array
+     * if a header with the same name occurs more than once.
+     *
+     * @return array headers as array(name => value)
+     */
+    public function getHeaders()
+    {
+        if ($this->_headers === null) {
+            if (!$this->_mail) {
+                $this->_headers = array();
+            } else {
+                $part = $this->_mail->getRawHeader($this->_messageNum);
+                Zend_Mime_Decode::splitMessage($part, $this->_headers, $null);
+            }
+        }
+
+        return $this->_headers;
+    }
+
+    /**
+     * Get a header in specificed format
+     *
+     * Internally headers that occur more than once are saved as array, all other as string. If $format
+     * is set to string implode is used to concat the values (with Zend_Mime::LINEEND as delim).
+     *
+     * @param  string $name   name of header, matches case-insensitive, but camel-case is replaced with dashes
+     * @param  string $format change type of return value to 'string' or 'array'
+     * @return string|array value of header in wanted or internal format
+     * @throws Zend_Mail_Exception
+     */
+    public function getHeader($name, $format = null)
+    {
+        if ($this->_headers === null) {
+            $this->getHeaders();
+        }
+
+        $lowerName = strtolower($name);
+
+        if (!isset($this->_headers[$lowerName])) {
+            $lowerName = strtolower(preg_replace('%([a-z])([A-Z])%', '\1-\2', $name));
+            if (!isset($this->_headers[$lowerName])) {
+                /**
+                 * @see Zend_Mail_Exception
+                 */
+                require_once 'Zend/Mail/Exception.php';
+                throw new Zend_Mail_Exception("no Header with Name $name found");
+            }
+        }
+        $name = $lowerName;
+
+        $header = $this->_headers[$name];
+
+        switch ($format) {
+            case 'string':
+                if (is_array($header)) {
+                    $header = implode(Zend_Mime::LINEEND, $header);
+                }
+                break;
+            case 'array':
+                $header = (array)$header;
+            default:
+                // do nothing
+        }
+
+        return $header;
+    }
+    
+    /**
+     * Get a specific field from a header like content type or all fields as array
+     *
+     * If the header occurs more than once, only the value from the first header
+     * is returned.
+     *
+     * Throws a Zend_Mail_Exception if the requested header does not exist. If
+     * the specific header field does not exist, returns null.
+     *
+     * @param  string $name       name of header, like in getHeader()
+     * @param  string $wantedPart the wanted part, default is first, if null an array with all parts is returned
+     * @param  string $firstName  key name for the first part
+     * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
+     * @throws Zend_Exception, Zend_Mail_Exception
+     */
+    public function getHeaderField($name, $wantedPart = 0, $firstName = 0) {
+    	return Zend_Mime_Decode::splitHeaderField(current($this->getHeader($name, 'array')), $wantedPart, $firstName);
+    }
+
+
+    /**
+     * Getter for mail headers - name is matched in lowercase
+     *
+     * This getter is short for Zend_Mail_Part::getHeader($name, 'string')
+     *
+     * @see Zend_Mail_Part::getHeader()
+     *
+     * @param  string $name header name
+     * @return string value of header
+     * @throws Zend_Mail_Exception
+     */
+    public function __get($name)
+    {
+        return $this->getHeader($name, 'string');
+    }
+
+    /**
+     * magic method to get content of part
+     *
+     * @return string content
+     */
+    public function __toString()
+    {
+        return $this->getContent();
+    }
+
+    /**
+     * implements RecursiveIterator::hasChildren()
+     *
+     * @return bool current element has children/is multipart
+     */
+    public function hasChildren()
+    {
+        $current = $this->current();
+        return $current && $current instanceof Zend_Mail_Part && $current->isMultipart();
+    }
+
+    /**
+     * implements RecursiveIterator::getChildren()
+     *
+     * @return Zend_Mail_Part same as self::current()
+     */
+    public function getChildren()
+    {
+        return $this->current();
+    }
+
+    /**
+     * implements Iterator::valid()
+     *
+     * @return bool check if there's a current element
+     */
+    public function valid()
+    {
+        if ($this->_countParts === null) {
+            $this->countParts();
+        }
+        return $this->_iterationPos && $this->_iterationPos <= $this->_countParts;
+    }
+
+    /**
+     * implements Iterator::next()
+     *
+     * @return null
+     */
+    public function next()
+    {
+        ++$this->_iterationPos;
+    }
+
+    /**
+     * implements Iterator::key()
+     *
+     * @return string key/number of current part
+     */
+    public function key()
+    {
+        return $this->_iterationPos;
+    }
+
+    /**
+     * implements Iterator::current()
+     *
+     * @return Zend_Mail_Part current part
+     */
+    public function current()
+    {
+        return $this->getPart($this->_iterationPos);
+    }
+
+    /**
+     * implements Iterator::rewind()
+     *
+     * @return null
+     */
+    public function rewind()
+    {
+        $this->countParts();
+        $this->_iterationPos = 1;
+    }
+}
Index: libs/Zend/Mime/Exception.php
===================================================================
--- libs/Zend/Mime/Exception.php	(wersja 0)
+++ libs/Zend/Mime/Exception.php	(wersja 0)
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * Zend_Exception
+ */
+require_once 'Zend/Exception.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mime_Exception extends Zend_Exception
+{}
+
Index: libs/Zend/Mime/Decode.php
===================================================================
--- libs/Zend/Mime/Decode.php	(wersja 0)
+++ libs/Zend/Mime/Decode.php	(wersja 0)
@@ -0,0 +1,238 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Zend_Mime
+ */
+require_once 'Zend/Mime.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mime_Decode
+{
+    /**
+     * Explode MIME multipart string into seperate parts
+     *
+     * Parts consist of the header and the body of each MIME part.
+     *
+     * @param  string $body     raw body of message
+     * @param  string $boundary boundary as found in content-type
+     * @return array parts with content of each part, empty if no parts found
+     * @throws Zend_Exception
+     */
+    public static function splitMime($body, $boundary)
+    {
+        // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r?
+        $body = str_replace("\r", '', $body);
+
+        $start = 0;
+        $res = array();
+        // find every mime part limiter and cut out the
+        // string before it.
+        // the part before the first boundary string is discarded:
+        $p = strpos($body, '--' . $boundary . "\n", $start);
+        if ($p === false) {
+            // no parts found!
+            return array();
+        }
+
+        // position after first boundary line
+        $start = $p + 3 + strlen($boundary);
+
+        while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) {
+            $res[] = substr($body, $start, $p-$start);
+            $start = $p + 3 + strlen($boundary);
+        }
+
+        // no more parts, find end boundary
+        $p = strpos($body, '--' . $boundary . '--', $start);
+        if ($p===false) {
+            throw new Zend_Exception('Not a valid Mime Message: End Missing');
+        }
+
+        // the remaining part also needs to be parsed:
+        $res[] = substr($body, $start, $p-$start);
+        return $res;
+    }
+
+    /**
+     * decodes a mime encoded String and returns a
+     * struct of parts with header and body
+     *
+     * @param  string $message  raw message content
+     * @param  string $boundary boundary as found in content-type
+     * @param  string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}
+     * @return array|null parts as array('header' => array(name => value), 'body' => content), null if no parts found
+     * @throws Zend_Exception
+     */
+    public static function splitMessageStruct($message, $boundary, $EOL = Zend_Mime::LINEEND)
+    {
+        $parts = self::splitMime($message, $boundary);
+        if (count($parts) <= 0) {
+            return null;
+        }
+        $result = array();
+        foreach ($parts as $part) {
+            self::splitMessage($part, $headers, $body, $EOL);
+            $result[] = array('header' => $headers,
+                              'body'   => $body    );
+        }
+        return $result;
+    }
+
+    /**
+     * split a message in header and body part, if no header or an
+     * invalid header is found $headers is empty
+     *
+     * The charset of the returned headers depend on your iconv settings.
+     *
+     * @param  string $message raw message with header and optional content
+     * @param  array  $headers output param, array with headers as array(name => value)
+     * @param  string $body    output param, content of message
+     * @param  string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}
+     * @return null
+     */
+    public static function splitMessage($message, &$headers, &$body, $EOL = Zend_Mime::LINEEND)
+    {
+        // check for valid header at first line
+        $firstline = strtok($message, "\n");
+        if (!preg_match('%^[^\s]+[^:]*:%', $firstline)) {
+            $headers = array();
+            // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r?
+            $body = str_replace(array("\r", "\n"), array('', $EOL), $message);
+            return;
+        }
+
+        // find an empty line between headers and body
+        // default is set new line
+        if (strpos($message, $EOL . $EOL)) {
+            list($headers, $body) = explode($EOL . $EOL, $message, 2);
+        // next is the standard new line
+        } else if ($EOL != "\r\n" && strpos($message, "\r\n\r\n")) {
+            list($headers, $body) = explode("\r\n\r\n", $message, 2);
+        // next is the other "standard" new line
+        } else if ($EOL != "\n" && strpos($message, "\n\n")) {
+            list($headers, $body) = explode("\n\n", $message, 2);
+        // at last resort find anything that looks like a new line
+        } else {
+            @list($headers, $body) = @preg_split("%([\r\n]+)\\1%U", $message, 2);
+        }
+
+        $headers = iconv_mime_decode_headers($headers, ICONV_MIME_DECODE_CONTINUE_ON_ERROR);
+
+        // normalize header names
+        foreach ($headers as $name => $header) {
+            $lower = strtolower($name);
+            if ($lower == $name) {
+                continue;
+            }
+            unset($headers[$name]);
+            if (!isset($headers[$lower])) {
+                $headers[$lower] = $header;
+                continue;
+            }
+            if (is_array($headers[$lower])) {
+                $headers[$lower][] = $header;
+                continue;
+            }
+            $headers[$lower] = array($headers[$lower], $header);
+        }
+    }
+
+    /**
+     * split a content type in its different parts
+     *
+     * @param  string $type       content-type
+     * @param  string $wantedPart the wanted part, else an array with all parts is returned
+     * @return string|array wanted part or all parts as array('type' => content-type, partname => value)
+     */
+    public static function splitContentType($type, $wantedPart = null)
+    {
+        return self::splitHeaderField($type, $wantedPart, 'type');
+    }
+
+    /**
+     * split a header field like content type in its different parts
+     *
+     * @param  string $type       header field
+     * @param  string $wantedPart the wanted part, else an array with all parts is returned
+     * @param  string $firstName  key name for the first part
+     * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
+     * @throws Zend_Exception
+     */
+    public static function splitHeaderField($field, $wantedPart = null, $firstName = 0)
+    {
+    	$wantedPart = strtolower($wantedPart);
+    	$firstName = strtolower($firstName);
+
+        // special case - a bit optimized
+        if ($firstName === $wantedPart) {
+            $field = strtok($field, ';');
+            return $field[0] == '"' ? substr($field, 1, -1) : $field;
+        }
+        
+        $field = $firstName . '=' . $field;
+        if (!preg_match_all('%([^=]+)=("[^"]+"|[^;]+)(;\s*|$)%', $field, $matches)) {
+            throw new Zend_Exception('not a valid header field');
+        }
+
+        if ($wantedPart) {
+            foreach ($matches[1] as $key => $name) {
+                if (strcasecmp($name, $wantedPart)) {
+                    continue;
+                }
+                if ($matches[2][$key][0] != '"') {
+                    return $matches[2][$key];
+                }
+                return substr($matches[2][$key], 1, -1);
+            }
+            return null;
+        }
+
+        $split = array();
+        foreach ($matches[1] as $key => $name) {
+        	$name = strtolower($name);
+            if ($matches[2][$key][0] == '"') {
+                $split[$name] = substr($matches[2][$key], 1, -1);
+            } else {
+                $split[$name] = $matches[2][$key];
+            }
+        }
+
+        return $split;
+    }
+
+    /**
+     * decode a quoted printable encoded string
+     *
+     * The charset of the returned string depends on your iconv settings.
+     *
+     * @param  string encoded string
+     * @return string decoded string
+     */
+    public static function decodeQuotedPrintable($string)
+    {
+        return iconv_mime_decode($string, ICONV_MIME_DECODE_CONTINUE_ON_ERROR);
+    }
+}
Index: libs/Zend/Mime/Message.php
===================================================================
--- libs/Zend/Mime/Message.php	(wersja 0)
+++ libs/Zend/Mime/Message.php	(wersja 0)
@@ -0,0 +1,280 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * Zend_Mime
+ */
+require_once 'Zend/Mime.php';
+
+/**
+ * Zend_Mime_Part
+ */
+require_once 'Zend/Mime/Part.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mime_Message
+{
+
+    protected $_parts = array();
+    protected $_mime = null;
+
+    /**
+     * Returns the list of all Zend_Mime_Parts in the message
+     *
+     * @return array of Zend_Mime_Part
+     */
+    public function getParts()
+    {
+        return $this->_parts;
+    }
+
+    /**
+     * Sets the given array of Zend_Mime_Parts as the array for the message
+     *
+     * @param array $parts
+     */
+    public function setParts($parts)
+    {
+        $this->_parts = $parts;
+    }
+
+    /**
+     * Append a new Zend_Mime_Part to the current message
+     *
+     * @param Zend_Mime_Part $part
+     */
+    public function addPart(Zend_Mime_Part $part)
+    {
+        /**
+         * @todo check for duplicate object handle
+         */
+        $this->_parts[] = $part;
+    }
+
+    /**
+     * Check if message needs to be sent as multipart
+     * MIME message or if it has only one part.
+     *
+     * @return boolean
+     */
+    public function isMultiPart()
+    {
+        return (count($this->_parts) > 1);
+    }
+
+    /**
+     * Set Zend_Mime object for the message
+     *
+     * This can be used to set the boundary specifically or to use a subclass of
+     * Zend_Mime for generating the boundary.
+     *
+     * @param Zend_Mime $mime
+     */
+    public function setMime(Zend_Mime $mime)
+    {
+        $this->_mime = $mime;
+    }
+
+    /**
+     * Returns the Zend_Mime object in use by the message
+     *
+     * If the object was not present, it is created and returned. Can be used to
+     * determine the boundary used in this message.
+     *
+     * @return Zend_Mime
+     */
+    public function getMime()
+    {
+        if ($this->_mime === null) {
+            $this->_mime = new Zend_Mime();
+        }
+
+        return $this->_mime;
+    }
+
+    /**
+     * Generate MIME-compliant message from the current configuration
+     *
+     * This can be a multipart message if more than one MIME part was added. If
+     * only one part is present, the content of this part is returned. If no
+     * part had been added, an empty string is returned.
+     *
+     * Parts are seperated by the mime boundary as defined in Zend_Mime. If
+     * {@link setMime()} has been called before this method, the Zend_Mime
+     * object set by this call will be used. Otherwise, a new Zend_Mime object
+     * is generated and used.
+     *
+     * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}
+     * @return string
+     */
+    public function generateMessage($EOL = Zend_Mime::LINEEND)
+    {
+        if (! $this->isMultiPart()) {
+            $body = array_shift($this->_parts);
+            $body = $body->getContent($EOL);
+        } else {
+            $mime = $this->getMime();
+
+            $boundaryLine = $mime->boundaryLine($EOL);
+            $body = 'This is a message in Mime Format.  If you see this, '
+                  . "your mail reader does not support this format." . $EOL;
+
+            foreach (array_keys($this->_parts) as $p) {
+                $body .= $boundaryLine
+                       . $this->getPartHeaders($p, $EOL)
+                       . $EOL
+                       . $this->getPartContent($p, $EOL);
+            }
+
+            $body .= $mime->mimeEnd($EOL);
+        }
+
+        return trim($body);
+    }
+
+    /**
+     * Get the headers of a given part as an array
+     *
+     * @param int $partnum
+     * @return array
+     */
+    public function getPartHeadersArray($partnum)
+    {
+        return $this->_parts[$partnum]->getHeadersArray();
+    }
+
+    /**
+     * Get the headers of a given part as a string
+     *
+     * @param int $partnum
+     * @return string
+     */
+    public function getPartHeaders($partnum, $EOL = Zend_Mime::LINEEND)
+    {
+        return $this->_parts[$partnum]->getHeaders($EOL);
+    }
+
+    /**
+     * Get the (encoded) content of a given part as a string
+     *
+     * @param int $partnum
+     * @return string
+     */
+    public function getPartContent($partnum, $EOL = Zend_Mime::LINEEND)
+    {
+        return $this->_parts[$partnum]->getContent($EOL);
+    }
+
+    /**
+     * Explode MIME multipart string into seperate parts
+     *
+     * Parts consist of the header and the body of each MIME part.
+     *
+     * @param string $body
+     * @param string $boundary
+     * @return array
+     */
+    protected static function _disassembleMime($body, $boundary)
+    {
+        $start = 0;
+        $res = array();
+        // find every mime part limiter and cut out the
+        // string before it.
+        // the part before the first boundary string is discarded:
+        $p = strpos($body, '--'.$boundary."\n", $start);
+        if ($p === false) {
+            // no parts found!
+            return array();
+        }
+
+        // position after first boundary line
+        $start = $p + 3 + strlen($boundary);
+
+        while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) {
+            $res[] = substr($body, $start, $p-$start);
+            $start = $p + 3 + strlen($boundary);
+        }
+
+        // no more parts, find end boundary
+        $p = strpos($body, '--' . $boundary . '--', $start);
+        if ($p===false) {
+            throw new Zend_Exception('Not a valid Mime Message: End Missing');
+        }
+
+        // the remaining part also needs to be parsed:
+        $res[] = substr($body, $start, $p-$start);
+        return $res;
+    }
+
+    /**
+     * Decodes a MIME encoded string and returns a Zend_Mime_Message object with
+     * all the MIME parts set according to the given string
+     *
+     * @param string $message
+     * @param string $boundary
+     * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}
+     * @return Zend_Mime_Message
+     */
+    public static function createFromMessage($message, $boundary, $EOL = Zend_Mime::LINEEND)
+    {
+        require_once 'Zend/Mime/Decode.php';
+        $parts = Zend_Mime_Decode::splitMessageStruct($message, $boundary, $EOL);
+
+        $res = new self();
+        foreach ($parts as $part) {
+            // now we build a new MimePart for the current Message Part:
+            $newPart = new Zend_Mime_Part($part);
+            foreach ($part['header'] as $key => $value) {
+                /**
+                 * @todo check for characterset and filename
+                 */
+                // list($key, $value) = $header;
+                switch($key) {
+                    case 'content-type':
+                        $newPart->type = $value;
+                        break;
+                    case 'content-transfer-encoding':
+                        $newPart->encoding = $value;
+                        break;
+                    case 'content-id':
+                        $newPart->id = trim($value,'<>');
+                        break;
+                    case 'Content-Disposition':
+                        $newPart->disposition = $value;
+                        break;
+                    case 'content-description':
+                        $newPart->description = $value;
+                        break;
+                    default:
+                        throw new Zend_Exception('Unknown header ignored for MimePart:' . $key);
+                }
+            }
+            $res->addPart($newPart);
+        }
+        return $res;
+    }
+}
Index: libs/Zend/Mime/Part.php
===================================================================
--- libs/Zend/Mime/Part.php	(wersja 0)
+++ libs/Zend/Mime/Part.php	(wersja 0)
@@ -0,0 +1,208 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Zend_Mime
+ */
+require_once 'Zend/Mime.php';
+
+/**
+ * Zend_Mime_Exception
+ */
+require_once 'Zend/Mime/Exception.php';
+
+/**
+ * Class representing a MIME part.
+ *
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mime_Part {
+
+    public $type = Zend_Mime::TYPE_OCTETSTREAM;
+    public $encoding = Zend_Mime::ENCODING_8BIT;
+    public $id;
+    public $disposition;
+    public $filename;
+    public $description;
+    public $charset;
+    public $boundary;
+    protected $_content;
+    protected $_isStream = false;
+
+
+    /**
+     * create a new Mime Part.
+     * The (unencoded) content of the Part as passed
+     * as a string or stream
+     *
+     * @param mixed $content  String or Stream containing the content
+     */
+    public function __construct($content)
+    {
+        $this->_content = $content;
+        if (is_resource($content)) {
+            $this->_isStream = true;
+        }
+    }
+
+    /**
+     * @todo setters/getters
+     * @todo error checking for setting $type
+     * @todo error checking for setting $encoding
+     */
+
+    /**
+     * check if this part can be read as a stream.
+     * if true, getEncodedStream can be called, otherwise
+     * only getContent can be used to fetch the encoded
+     * content of the part
+     *
+     * @return bool
+     */
+    public function isStream()
+    {
+      return $this->_isStream;
+    }
+
+    /**
+     * if this was created with a stream, return a filtered stream for
+     * reading the content. very useful for large file attachments.
+     *
+     * @return stream
+     * @throws Zend_Mime_Exception if not a stream or unable to append filter
+     */
+    public function getEncodedStream()
+    {
+        if (!$this->_isStream) {
+            throw new Zend_Mime_Exception('Attempt to get a stream from a string part');
+        }
+
+        //stream_filter_remove(); // ??? is that right?
+        switch ($this->encoding) {
+            case Zend_Mime::ENCODING_QUOTEDPRINTABLE:
+                $filter = stream_filter_append(
+                    $this->_content,
+                    'convert.quoted-printable-encode',
+                    STREAM_FILTER_READ,
+                    array(
+                        'line-length'      => 76,
+                        'line-break-chars' => Zend_Mime::LINEEND
+                    )
+                );
+                if (!is_resource($filter)) {
+                    throw new Zend_Mime_Exception('Failed to append quoted-printable filter');
+                }
+                break;
+            case Zend_Mime::ENCODING_BASE64:
+                $filter = stream_filter_append(
+                    $this->_content,
+                    'convert.base64-encode',
+                    STREAM_FILTER_READ,
+                    array(
+                        'line-length'      => 76,
+                        'line-break-chars' => Zend_Mime::LINEEND
+                    )
+                );
+                if (!is_resource($filter)) {
+                    throw new Zend_Mime_Exception('Failed to append base64 filter');
+                }
+                break;
+            default:
+        }
+        return $this->_content;
+    }
+
+    /**
+     * Get the Content of the current Mime Part in the given encoding.
+     *
+     * @return String
+     */
+    public function getContent($EOL = Zend_Mime::LINEEND)
+    {
+        if ($this->_isStream) {
+            return stream_get_contents($this->getEncodedStream());
+        } else {
+            return Zend_Mime::encode($this->_content, $this->encoding, $EOL);
+        }
+    }
+
+    /**
+     * Create and return the array of headers for this MIME part
+     *
+     * @access public
+     * @return array
+     */
+    public function getHeadersArray($EOL = Zend_Mime::LINEEND)
+    {
+        $headers = array();
+
+        $contentType = $this->type;
+        if ($this->charset) {
+            $contentType .= '; charset="' . $this->charset . '"';
+        }
+
+        if ($this->boundary) {
+            $contentType .= ';' . $EOL
+                          . " boundary=\"" . $this->boundary . '"';
+        }
+
+        $headers[] = array('Content-Type', $contentType);
+
+        if ($this->encoding) {
+            $headers[] = array('Content-Transfer-Encoding', $this->encoding);
+        }
+
+        if ($this->id) {
+            $headers[]  = array('Content-ID', '<' . $this->id . '>');
+        }
+
+        if ($this->disposition) {
+            $disposition = $this->disposition;
+            if ($this->filename) {
+                $disposition .= '; filename="' . $this->filename . '"';
+            }
+            $headers[] = array('Content-Disposition', $disposition);
+        }
+
+        if ($this->description) {
+            $headers[] = array('Content-Description', $this->description);
+        }
+
+        return $headers;
+    }
+
+    /**
+     * Return the headers for this part as a string
+     *
+     * @return String
+     */
+    public function getHeaders($EOL = Zend_Mime::LINEEND)
+    {
+        $res = '';
+        foreach ($this->getHeadersArray($EOL) as $header) {
+            $res .= $header[0] . ': ' . $header[1] . $EOL;
+        }
+
+        return $res;
+    }
+}
Index: libs/Zend/Mail.php
===================================================================
--- libs/Zend/Mail.php	(wersja 0)
+++ libs/Zend/Mail.php	(wersja 0)
@@ -0,0 +1,725 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Mail.php 8064 2008-02-16 10:58:39Z thomas $
+ */
+
+
+/**
+ * @see Zend_Mail_Transport_Abstract
+ */
+require_once 'Zend/Mail/Transport/Abstract.php';
+
+/**
+ * @see Zend_Mime
+ */
+require_once 'Zend/Mime.php';
+
+/**
+ * @see Zend_Mail_Transport_Abstract
+ */
+require_once 'Zend/Mail/Transport/Abstract.php';
+
+/**
+ * @see Zend_Mime_Message
+ */
+require_once 'Zend/Mime/Message.php';
+
+/**
+ * @see Zend_Mime_Part
+ */
+require_once 'Zend/Mime/Part.php';
+
+
+/**
+ * Class for sending an email.
+ *
+ * @category   Zend
+ * @package    Zend_Mail
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mail extends Zend_Mime_Message
+{
+    /**#@+
+     * @access protected
+     */
+
+    /**
+     * @var Zend_Mail_Transport_Abstract
+     * @static
+     */
+    protected static $_defaultTransport = null;
+
+    /**
+     * Mail character set
+     * @var string
+     */
+    protected $_charset = null;
+
+    /**
+     * Mail headers
+     * @var array
+     */
+    protected $_headers = array();
+
+    /**
+     * From: address
+     * @var string
+     */
+    protected $_from = null;
+
+    /**
+     * To: addresses
+     * @var array
+     */
+    protected $_to = array();
+
+    /**
+     * Array of all recipients
+     * @var array
+     */
+    protected $_recipients = array();
+
+    /**
+     * Return-Path header
+     * @var string
+     */
+    protected $_returnPath = null;
+
+    /**
+     * Subject: header
+     * @var string
+     */
+    protected $_subject = null;
+
+    /**
+     * Date: header
+     * @var string
+     */
+    protected $_date = null;
+
+    /**
+     * text/plain MIME part
+     * @var false|Zend_Mime_Part
+     */
+    protected $_bodyText = false;
+
+    /**
+     * text/html MIME part
+     * @var false|Zend_Mime_Part
+     */
+    protected $_bodyHtml = false;
+
+    /**
+     * MIME boundary string
+     * @var string
+     */
+    protected $_mimeBoundary = null;
+
+    /**
+     * Content type of the message
+     * @var string
+     */
+    protected $_type = null;
+
+    /**#@-*/
+
+    /**
+     * Flag: whether or not email has attachments
+     * @var boolean
+     */
+    public $hasAttachments = false;
+
+
+    /**
+     * Sets the default mail transport for all following uses of
+     * Zend_Mail::send();
+     *
+     * @todo Allow passing a string to indicate the transport to load
+     * @todo Allow passing in optional options for the transport to load
+     * @param  Zend_Mail_Transport_Abstract $transport
+     */
+    public static function setDefaultTransport(Zend_Mail_Transport_Abstract $transport)
+    {
+        self::$_defaultTransport = $transport;
+    }
+
+    /**
+     * Public constructor
+     *
+     * @param string $charset
+     */
+    public function __construct($charset='iso-8859-1')
+    {
+        $this->_charset = $charset;
+    }
+
+    /**
+     * Return charset string
+     *
+     * @return string
+     */
+    public function getCharset()
+    {
+        return $this->_charset;
+    }
+
+    /**
+     * Set content type
+     *
+     * Should only be used for manually setting multipart content types.
+     *
+     * @param  string $type Content type
+     * @return Zend_Mail Implements fluent interface
+     * @throws Zend_Mail_Exception for types not supported by Zend_Mime
+     */
+    public function setType($type)
+    {
+        $allowed = array(
+            Zend_Mime::MULTIPART_ALTERNATIVE,
+            Zend_Mime::MULTIPART_MIXED,
+            Zend_Mime::MULTIPART_RELATED,
+        );
+        if (!in_array($type, $allowed)) {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('Invalid content type "' . $type . '"');
+        }
+
+        $this->_type = $type;
+        return $this;
+    }
+
+    /**
+     * Get content type of the message
+     *
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->_type;
+    }
+
+    /**
+     * Set an arbitrary mime boundary for the message
+     *
+     * If not set, Zend_Mime will generate one.
+     *
+     * @param  string    $boundary
+     * @return Zend_Mail Provides fluent interface
+     */
+    public function setMimeBoundary($boundary)
+    {
+        $this->_mimeBoundary = $boundary;
+
+        return $this;
+    }
+
+    /**
+     * Return the boundary string used for the message
+     *
+     * @return string
+     */
+    public function getMimeBoundary()
+    {
+        return $this->_mimeBoundary;
+    }
+
+    /**
+     * Sets the text body for the message.
+     *
+     * @param  string $txt
+     * @param  string $charset
+     * @param  string $encoding
+     * @return Zend_Mail Provides fluent interface
+    */
+    public function setBodyText($txt, $charset = null, $encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE)
+    {
+        if ($charset === null) {
+            $charset = $this->_charset;
+        }
+
+        $mp = new Zend_Mime_Part($txt);
+        $mp->encoding = $encoding;
+        $mp->type = Zend_Mime::TYPE_TEXT;
+        $mp->disposition = Zend_Mime::DISPOSITION_INLINE;
+        $mp->charset = $charset;
+
+        $this->_bodyText = $mp;
+
+        return $this;
+    }
+
+    /**
+     * Return text body Zend_Mime_Part or string
+     *
+     * @param  bool textOnly Whether to return just the body text content or the MIME part; defaults to false, the MIME part
+     * @return false|Zend_Mime_Part|string
+     */
+    public function getBodyText($textOnly = false)
+    {
+        if ($textOnly && $this->_bodyText) {
+            $body = $this->_bodyText;
+            return $body->getContent();
+        }
+
+        return $this->_bodyText;
+    }
+
+    /**
+     * Sets the HTML body for the message
+     *
+     * @param  string    $html
+     * @param  string    $charset
+     * @param  string    $encoding
+     * @return Zend_Mail Provides fluent interface
+     */
+    public function setBodyHtml($html, $charset = null, $encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE)
+    {
+        if ($charset === null) {
+            $charset = $this->_charset;
+        }
+
+        $mp = new Zend_Mime_Part($html);
+        $mp->encoding = $encoding;
+        $mp->type = Zend_Mime::TYPE_HTML;
+        $mp->disposition = Zend_Mime::DISPOSITION_INLINE;
+        $mp->charset = $charset;
+
+        $this->_bodyHtml = $mp;
+
+        return $this;
+    }
+
+    /**
+     * Return Zend_Mime_Part representing body HTML
+     *
+     * @param  bool $htmlOnly Whether to return the body HTML only, or the MIME part; defaults to false, the MIME part
+     * @return false|Zend_Mime_Part|string
+     */
+    public function getBodyHtml($htmlOnly = false)
+    {
+        if ($htmlOnly && $this->_bodyHtml) {
+            $body = $this->_bodyHtml;
+            return $body->getContent();
+        }
+
+        return $this->_bodyHtml;
+    }
+
+    /**
+     * Adds an existing attachment to the mail message
+     *
+     * @param  Zend_Mime_Part $attachment
+     * @return Zend_Mail Provides fluent interface
+     */
+    public function addAttachment(Zend_Mime_Part $attachment)
+    {
+        $this->addPart($attachment);
+        $this->hasAttachments = true;
+
+        return $this;
+    }
+
+    /**
+     * Creates a Zend_Mime_Part attachment
+     *
+     * Attachment is automatically added to the mail object after creation. The
+     * attachment object is returned to allow for further manipulation.
+     *
+     * @param  string         $body
+     * @param  string         $mimeType
+     * @param  string         $disposition
+     * @param  string         $encoding
+     * @param  string         $filename OPTIONAL A filename for the attachment
+     * @return Zend_Mime_Part Newly created Zend_Mime_Part object (to allow
+     * advanced settings)
+     */
+    public function createAttachment($body,
+                                     $mimeType    = Zend_Mime::TYPE_OCTETSTREAM,
+                                     $disposition = Zend_Mime::DISPOSITION_ATTACHMENT,
+                                     $encoding    = Zend_Mime::ENCODING_BASE64,
+                                     $filename    = null)
+    {
+
+        $mp = new Zend_Mime_Part($body);
+        $mp->encoding = $encoding;
+        $mp->type = $mimeType;
+        $mp->disposition = $disposition;
+        $mp->filename = $filename;
+
+        $this->addAttachment($mp);
+
+        return $mp;
+    }
+
+    /**
+     * Return a count of message parts
+     *
+     * @return integer
+     */
+    public function getPartCount()
+    {
+        return count($this->_parts);
+    }
+
+    /**
+     * Encode header fields
+     *
+     * Encodes header content according to RFC1522 if it contains non-printable
+     * characters.
+     *
+     * @param  string $value
+     * @return string
+     */
+    protected function _encodeHeader($value)
+    {
+      if (Zend_Mime::isPrintable($value)) {
+          return $value;
+      } else {
+          $quotedValue = Zend_Mime::encodeQuotedPrintable($value);
+          $quotedValue = str_replace(array('?', ' '), array('=3F', '=20'), $quotedValue);
+          return '=?' . $this->_charset . '?Q?' . $quotedValue . '?=';
+      }
+    }
+
+    /**
+     * Add a header to the message
+     *
+     * Adds a header to this message. If append is true and the header already
+     * exists, raises a flag indicating that the header should be appended.
+     *
+     * @param string  $headerName
+     * @param string  $value
+     * @param boolean $append
+     */
+    protected function _storeHeader($headerName, $value, $append=false)
+    {
+// ??        $value = strtr($value,"\r\n\t",'???');
+        if (isset($this->_headers[$headerName])) {
+            $this->_headers[$headerName][] = $value;
+        } else {
+            $this->_headers[$headerName] = array($value);
+        }
+
+        if ($append) {
+            $this->_headers[$headerName]['append'] = true;
+        }
+
+    }
+
+    /**
+     * Add a recipient
+     *
+     * @param string $email
+     */
+    protected function _addRecipient($email, $to = false)
+    {
+        // prevent duplicates
+        $this->_recipients[$email] = 1;
+
+        if ($to) {
+            $this->_to[] = $email;
+        }
+    }
+
+    /**
+     * Helper function for adding a recipient and the corresponding header
+     *
+     * @param string $headerName
+     * @param string $name
+     * @param string $email
+     */
+    protected function _addRecipientAndHeader($headerName, $name, $email)
+    {
+        $email = strtr($email,"\r\n\t",'???');
+        $this->_addRecipient($email, ('To' == $headerName) ? true : false);
+        if ($name != '') {
+            $name = '"' . $this->_encodeHeader($name) . '" ';
+        }
+
+        $this->_storeHeader($headerName, $name .'<'. $email . '>', true);
+    }
+
+    /**
+     * Adds To-header and recipient
+     *
+     * @param  string $name
+     * @param  string $email
+     * @return Zend_Mail Provides fluent interface
+     */
+    public function addTo($email, $name='')
+    {
+        $this->_addRecipientAndHeader('To', $name, $email);
+        return $this;
+    }
+
+    /**
+     * Adds Cc-header and recipient
+     *
+     * @param  string    $name
+     * @param  string    $email
+     * @return Zend_Mail Provides fluent interface
+     */
+    public function addCc($email, $name='')
+    {
+        $this->_addRecipientAndHeader('Cc', $name, $email);
+        return $this;
+    }
+
+    /**
+     * Adds Bcc recipient
+     *
+     * @param  string    $email
+     * @return Zend_Mail Provides fluent interface
+     */
+    public function addBcc($email)
+    {
+        $this->_addRecipientAndHeader('Bcc', '', $email);
+        return $this;
+    }
+
+    /**
+     * Return list of recipient email addresses
+     *
+     * @return array (of strings)
+     */
+    public function getRecipients()
+    {
+        return array_keys($this->_recipients);
+    }
+
+    /**
+     * Sets From-header and sender of the message
+     *
+     * @param  string    $email
+     * @param  string    $name
+     * @return Zend_Mail Provides fluent interface
+     * @throws Zend_Mail_Exception if called subsequent times
+     */
+    public function setFrom($email, $name = '')
+    {
+        if ($this->_from === null) {
+            $email = strtr($email,"\r\n\t",'???');
+            $this->_from = $email;
+            $this->_storeHeader('From', $this->_encodeHeader('"'.$name.'"').' <'.$email.'>', true);
+        } else {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('From Header set twice');
+        }
+        return $this;
+    }
+
+    /**
+     * Returns the sender of the mail
+     *
+     * @return string
+     */
+    public function getFrom()
+    {
+        return $this->_from;
+    }
+
+    /**
+     * Sets the Return-Path header for an email
+     *
+     * @param  string    $email
+     * @return Zend_Mail Provides fluent interface
+     * @throws Zend_Mail_Exception if set multiple times
+     */
+    public function setReturnPath($email)
+    {
+        if ($this->_returnPath === null) {
+            $email = strtr($email,"\r\n\t",'???');
+            $this->_returnPath = $email;
+            $this->_storeHeader('Return-Path', $email, false);
+        } else {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('Return-Path Header set twice');
+        }
+        return $this;
+    }
+
+    /**
+     * Returns the current Return-Path address for the email
+     *
+     * If no Return-Path header is set, returns the value of {@link $_from}.
+     *
+     * @return string
+     */
+    public function getReturnPath()
+    {
+        if (null !== $this->_returnPath) {
+            return $this->_returnPath;
+        }
+
+        return $this->_from;
+    }
+
+    /**
+     * Sets the subject of the message
+     *
+     * @param   string    $subject
+     * @return  Zend_Mail Provides fluent interface
+     * @throws  Zend_Mail_Exception
+     */
+    public function setSubject($subject)
+    {
+        if ($this->_subject === null) {
+            $subject = strtr($subject,"\r\n\t",'???');
+            $this->_subject = $this->_encodeHeader($subject);
+            $this->_storeHeader('Subject', $this->_subject);
+        } else {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('Subject set twice');
+        }
+        return $this;
+    }
+
+    /**
+     * Returns the encoded subject of the message
+     *
+     * @return string
+     */
+    public function getSubject()
+    {
+        return $this->_subject;
+    }
+    
+    /**
+     * Sets Date-header
+     *
+     * @param  string    $date
+     * @return Zend_Mail Provides fluent interface
+     * @throws Zend_Mail_Exception if called subsequent times
+     */
+    public function setDate($date = null)
+    {
+        if ($this->_date === null) {
+            if ($date === null) {
+                $date = date('r');
+            } else if (is_int($date)) {
+                $date = date('r', $date);
+            } else if (is_string($date)) {
+            	$date = strtotime($date);
+                if ($date === false || $date < 0) {
+                    throw new Zend_Mail_Exception('String representations of Date Header must be ' .
+                                                  'strtotime()-compatible');
+                }
+                $date = date('r', $date);
+            } else if ($date instanceof Zend_Date) {
+                $date = $date->get(Zend_Date::RFC_2822);
+            } else {
+                throw new Zend_Mail_Exception(__METHOD__ . ' only accepts UNIX timestamps, Zend_Date objects, ' .
+                                              ' and strtotime()-compatible strings');
+            }
+            $this->_date = $date;
+            $this->_storeHeader('Date', $date);
+        } else {
+            throw new Zend_Mail_Exception('Date Header set twice');
+        }
+        return $this;
+    }
+
+    /**
+     * Returns the formatted date of the message
+     *
+     * @return string
+     */
+    public function getDate()
+    {
+        return $this->_date;
+    }
+
+    /**
+     * Add a custom header to the message
+     *
+     * @param  string              $name
+     * @param  string              $value
+     * @param  boolean             $append
+     * @return Zend_Mail           Provides fluent interface
+     * @throws Zend_Mail_Exception on attempts to create standard headers
+     */
+    public function addHeader($name, $value, $append = false)
+    {
+        if (in_array(strtolower($name), array('to', 'cc', 'bcc', 'from', 'subject', 'return-path', 'date'))) {
+            /**
+             * @see Zend_Mail_Exception
+             */
+            require_once 'Zend/Mail/Exception.php';
+            throw new Zend_Mail_Exception('Cannot set standard header from addHeader()');
+        }
+
+        $value = strtr($value,"\r\n\t",'???');
+        $value = $this->_encodeHeader($value);
+        $this->_storeHeader($name, $value, $append);
+
+        return $this;
+    }
+
+    /**
+     * Return mail headers
+     *
+     * @return void
+     */
+    public function getHeaders()
+    {
+        return $this->_headers;
+    }
+
+    /**
+     * Sends this email using the given transport or a previously
+     * set DefaultTransport or the internal mail function if no
+     * default transport had been set.
+     *
+     * @param  Zend_Mail_Transport_Abstract $transport
+     * @return Zend_Mail                    Provides fluent interface
+     */
+    public function send($transport = null)
+    {
+        if ($transport === null) {
+            if (! self::$_defaultTransport instanceof Zend_Mail_Transport_Abstract) {
+                require_once 'Zend/Mail/Transport/Sendmail.php';
+                $transport = new Zend_Mail_Transport_Sendmail();
+            } else {
+                $transport = self::$_defaultTransport;
+            }
+        }
+
+        if (is_null($this->_date)) {
+            $this->setDate();
+        }
+
+        $transport->send($this);
+
+        return $this;
+    }
+
+}
Index: libs/Zend/Mime.php
===================================================================
--- libs/Zend/Mime.php	(wersja 0)
+++ libs/Zend/Mime.php	(wersja 0)
@@ -0,0 +1,252 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * Support class for MultiPart Mime Messages
+ *
+ * @category   Zend
+ * @package    Zend_Mime
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mime
+{
+    const TYPE_OCTETSTREAM = 'application/octet-stream';
+    const TYPE_TEXT = 'text/plain';
+    const TYPE_HTML = 'text/html';
+    const ENCODING_7BIT = '7bit';
+    const ENCODING_8BIT = '8bit';
+    const ENCODING_QUOTEDPRINTABLE = 'quoted-printable';
+    const ENCODING_BASE64 = 'base64';
+    const DISPOSITION_ATTACHMENT = 'attachment';
+    const DISPOSITION_INLINE = 'inline';
+    const LINELENGTH = 74;
+    const LINEEND = "\n";
+    const MULTIPART_ALTERNATIVE = 'multipart/alternative';
+    const MULTIPART_MIXED = 'multipart/mixed';
+    const MULTIPART_RELATED = 'multipart/related';
+
+    protected $_boundary;
+    protected static $makeUnique = 0;
+
+    // lookup-Tables for QuotedPrintable
+    public static $qpKeys = array(
+        "\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07",
+        "\x08","\x09","\x0A","\x0B","\x0C","\x0D","\x0E","\x0F",
+        "\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17",
+        "\x18","\x19","\x1A","\x1B","\x1C","\x1D","\x1E","\x1F",
+        "\x7F","\x80","\x81","\x82","\x83","\x84","\x85","\x86",
+        "\x87","\x88","\x89","\x8A","\x8B","\x8C","\x8D","\x8E",
+        "\x8F","\x90","\x91","\x92","\x93","\x94","\x95","\x96",
+        "\x97","\x98","\x99","\x9A","\x9B","\x9C","\x9D","\x9E",
+        "\x9F","\xA0","\xA1","\xA2","\xA3","\xA4","\xA5","\xA6",
+        "\xA7","\xA8","\xA9","\xAA","\xAB","\xAC","\xAD","\xAE",
+        "\xAF","\xB0","\xB1","\xB2","\xB3","\xB4","\xB5","\xB6",
+        "\xB7","\xB8","\xB9","\xBA","\xBB","\xBC","\xBD","\xBE",
+        "\xBF","\xC0","\xC1","\xC2","\xC3","\xC4","\xC5","\xC6",
+        "\xC7","\xC8","\xC9","\xCA","\xCB","\xCC","\xCD","\xCE",
+        "\xCF","\xD0","\xD1","\xD2","\xD3","\xD4","\xD5","\xD6",
+        "\xD7","\xD8","\xD9","\xDA","\xDB","\xDC","\xDD","\xDE",
+        "\xDF","\xE0","\xE1","\xE2","\xE3","\xE4","\xE5","\xE6",
+        "\xE7","\xE8","\xE9","\xEA","\xEB","\xEC","\xED","\xEE",
+        "\xEF","\xF0","\xF1","\xF2","\xF3","\xF4","\xF5","\xF6",
+        "\xF7","\xF8","\xF9","\xFA","\xFB","\xFC","\xFD","\xFE",
+        "\xFF"
+        );
+
+    public static $qpReplaceValues = array(
+        "=00","=01","=02","=03","=04","=05","=06","=07",
+        "=08","=09","=0A","=0B","=0C","=0D","=0E","=0F",
+        "=10","=11","=12","=13","=14","=15","=16","=17",
+        "=18","=19","=1A","=1B","=1C","=1D","=1E","=1F",
+        "=7F","=80","=81","=82","=83","=84","=85","=86",
+        "=87","=88","=89","=8A","=8B","=8C","=8D","=8E",
+        "=8F","=90","=91","=92","=93","=94","=95","=96",
+        "=97","=98","=99","=9A","=9B","=9C","=9D","=9E",
+        "=9F","=A0","=A1","=A2","=A3","=A4","=A5","=A6",
+        "=A7","=A8","=A9","=AA","=AB","=AC","=AD","=AE",
+        "=AF","=B0","=B1","=B2","=B3","=B4","=B5","=B6",
+        "=B7","=B8","=B9","=BA","=BB","=BC","=BD","=BE",
+        "=BF","=C0","=C1","=C2","=C3","=C4","=C5","=C6",
+        "=C7","=C8","=C9","=CA","=CB","=CC","=CD","=CE",
+        "=CF","=D0","=D1","=D2","=D3","=D4","=D5","=D6",
+        "=D7","=D8","=D9","=DA","=DB","=DC","=DD","=DE",
+        "=DF","=E0","=E1","=E2","=E3","=E4","=E5","=E6",
+        "=E7","=E8","=E9","=EA","=EB","=EC","=ED","=EE",
+        "=EF","=F0","=F1","=F2","=F3","=F4","=F5","=F6",
+        "=F7","=F8","=F9","=FA","=FB","=FC","=FD","=FE",
+        "=FF"
+        );
+
+    public static $qpKeysString =
+         "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF";
+
+    /**
+     * Check if the given string is "printable"
+     *
+     * Checks that a string contains no unprintable characters. If this returns
+     * false, encode the string for secure delivery.
+     *
+     * @param string $str
+     * @return boolean
+     */
+    public static function isPrintable($str)
+    {
+        return (strcspn($str, self::$qpKeysString) == strlen($str));
+    }
+
+    /**
+     * Encode a given string with the QUOTED_PRINTABLE mechanism
+     *
+     * @param string $str
+     * @param int $lineLength Defaults to {@link LINELENGTH}
+     * @param int $lineEnd Defaults to {@link LINEEND}
+     * @return string
+     */
+    public static function encodeQuotedPrintable($str,
+        $lineLength = self::LINELENGTH,
+        $lineEnd = self::LINEEND)
+    {
+        $out = '';
+        $str = str_replace('=', '=3D', $str);
+        $str = str_replace(self::$qpKeys, self::$qpReplaceValues, $str);
+        $str = rtrim($str);
+
+        // Split encoded text into separate lines
+        while ($str) {
+            $ptr = strlen($str);
+            if ($ptr > $lineLength) {
+                $ptr = $lineLength;
+            }
+
+            // Ensure we are not splitting across an encoded character
+            $pos = strrpos(substr($str, 0, $ptr), '=');
+            if ($pos !== false && $pos >= $ptr - 2) {
+                $ptr = $pos;
+            }
+
+            // Check if there is a space at the end of the line and rewind
+            if ($ptr > 0 && $str[$ptr - 1] == ' ') {
+                --$ptr;
+            }
+
+            // Add string and continue
+            $out .= substr($str, 0, $ptr) . '=' . $lineEnd;
+            $str = substr($str, $ptr);
+        }
+
+        $out = rtrim($out, $lineEnd);
+        $out = rtrim($out, '=');
+        return $out;
+    }
+
+    /**
+     * Encode a given string in base64 encoding and break lines
+     * according to the maximum linelength.
+     *
+     * @param string $str
+     * @param int $lineLength Defaults to {@link LINELENGTH}
+     * @param int $lineEnd Defaults to {@link LINEEND}
+     * @return string
+     */
+    public static function encodeBase64($str,
+        $lineLength = self::LINELENGTH,
+        $lineEnd = self::LINEEND)
+    {
+        return rtrim(chunk_split(base64_encode($str), $lineLength, $lineEnd));
+    }
+
+    /**
+     * Constructor
+     *
+     * @param null|string $boundary
+     * @access public
+     * @return void
+     */
+    public function __construct($boundary = null)
+    {
+        // This string needs to be somewhat unique
+        if ($boundary === null) {
+            $this->_boundary = '=_' . md5(microtime(1) . self::$makeUnique++);
+        } else {
+            $this->_boundary = $boundary;
+        }
+    }
+
+    /**
+     * Encode the given string with the given encoding.
+     *
+     * @param string $str
+     * @param string $encoding
+     * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}
+     * @return string
+     */
+    public static function encode($str, $encoding, $EOL = self::LINEEND)
+    {
+        switch ($encoding) {
+            case self::ENCODING_BASE64:
+                return self::encodeBase64($str, self::LINELENGTH, $EOL);
+
+            case self::ENCODING_QUOTEDPRINTABLE:
+                return self::encodeQuotedPrintable($str, self::LINELENGTH, $EOL);
+
+            default:
+                /**
+                 * @todo 7Bit and 8Bit is currently handled the same way.
+                 */
+                return $str;
+        }
+    }
+
+    /**
+     * Return a MIME boundary
+     *
+     * @access public
+     * @return string
+     */
+    public function boundary()
+    {
+        return $this->_boundary;
+    }
+
+    /**
+     * Return a MIME boundary line
+     *
+     * @param mixed $EOL Defaults to {@link LINEEND}
+     * @access public
+     * @return string
+     */
+    public function boundaryLine($EOL = self::LINEEND)
+    {
+        return $EOL . '--' . $this->_boundary . $EOL;
+    }
+
+    /**
+     * Return MIME ending
+     *
+     * @access public
+     * @return string
+     */
+    public function mimeEnd($EOL = self::LINEEND)
+    {
+        return $EOL . '--' . $this->_boundary . '--' . $EOL;
+    }
+}
Index: libs/javascript/sprintf.js
===================================================================
--- libs/javascript/sprintf.js	(wersja 0)
+++ libs/javascript/sprintf.js	(wersja 0)
@@ -0,0 +1,55 @@
+/**
+ * sprintf() for JavaScript v.0.4
+ *
+ * Copyright (c) 2007 Alexandru Marasteanu <http://alexei.417.ro/>
+ * Thanks to David Baird (unit test and patch).
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+function str_repeat(i, m) { for (var o = []; m > 0; o[--m] = i); return(o.join('')); }
+
+function sprintf () {
+  var i = 0, a, f = arguments[i++], o = [], m, p, c, x;
+  while (f) {
+    if (m = /^[^\x25]+/.exec(f)) o.push(m[0]);
+    else if (m = /^\x25{2}/.exec(f)) o.push('%');
+    else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {
+      if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) throw("Too few arguments.");
+      if (/[^s]/.test(m[7]) && (typeof(a) != 'number'))
+        throw("Expecting number but found " + typeof(a));
+      switch (m[7]) {
+        case 'b': a = a.toString(2); break;
+        case 'c': a = String.fromCharCode(a); break;
+        case 'd': a = parseInt(a); break;
+        case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
+        case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
+        case 'o': a = a.toString(8); break;
+        case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
+        case 'u': a = Math.abs(a); break;
+        case 'x': a = a.toString(16); break;
+        case 'X': a = a.toString(16).toUpperCase(); break;
+      }
+      a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a);
+      c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
+      x = m[5] - String(a).length;
+      p = m[5] ? str_repeat(c, x) : '';
+      o.push(m[4] ? a + p : p + a);
+    }
+    else throw ("Huh ?!");
+    f = f.substring(m[0].length);
+  }
+  return o.join('');
+}
Index: modules/SmartyPlugins/modifier.translate.php
===================================================================
--- modules/SmartyPlugins/modifier.translate.php	(wersja 441)
+++ modules/SmartyPlugins/modifier.translate.php	(kopia robocza)
@@ -18,15 +18,16 @@
  * 
  * @return string The translated string
  */
-function smarty_modifier_translate($string, $aValues = null)
+function smarty_modifier_translate($string)
 {
-	if(is_null($aValues))
+	if(func_num_args() <= 1)
 	{
 		$aValues = array();
 	}
-	if(!is_array($aValues))
+	else
 	{
-		$aValues = array( $aValues);
+		$aValues = func_get_args();
+		array_shift($aValues);
 	}
 	return vsprintf(Piwik_Translate($string), $aValues);
-}
\ brakuje znaku końca linii na końcu pliku 
+}
Index: modules/SmartyPlugins/function.loadJavascriptTranslations.php
===================================================================
--- modules/SmartyPlugins/function.loadJavascriptTranslations.php	(wersja 0)
+++ modules/SmartyPlugins/function.loadJavascriptTranslations.php	(wersja 0)
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ *	inserts javascript translation array into the template from given modules
+ *  must be called with 'modules' argument which consists of space-separated module names (i.e. plugins)
+ *
+ *
+ *  Example (use in template):
+ *
+ *  {loadJavascriptTranslations modules='SitesManager Home General'}
+ *
+ *  loads javascript array translations from main translation file ('General')
+ *  and both 'Home' and 'SitesManager' plugins translations
+ * 
+ *  only translations with '_fs' suffix will be loaded
+ *
+ *  in order to use translation in your javascript use _pk_translate function
+ *  (it is always loaded with translations):
+ *
+ *  <script type="text/javascript">
+ *     alert(_pk_translate('MY_TRANSLATION_STRING','Default string in English'))
+ *  </script>
+ *
+ *  Note: Use translation string from your translation file WITHOUT '_js' suffix.
+ * 
+ * _pk_translate function supports printf() arguments, so you can call:
+ *
+ *   _pk_translate('_NB_OF_EGGS','There is %s eggs on the table','ten')
+ */
+
+function smarty_function_loadJavascriptTranslations($params, &$smarty) 
+{
+	if(!isset($params['modules']))
+	{
+		throw new Exception("The smarty function loadJavascriptTranslations needs a 'modules' parameter.");
+	}
+	$translate = Piwik_Translate::getInstance();
+	
+	return $translate->getJavascriptTranslations(explode(' ',$params['modules']));
+}
Index: modules/TranslateException.php
===================================================================
--- modules/TranslateException.php	(wersja 0)
+++ modules/TranslateException.php	(wersja 0)
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ * 
+ * @package Piwik_Helper
+ */
+
+require_once "Translate.php";
+
+/**
+ * Returns translated string or given message if translation is not found.
+ * This function does not throw any exception. Use it to translate exceptions.
+ *
+ * @return string
+ */
+function Piwik_TranslateException($message)
+{
+	$s = null;
+	
+	try 
+	{
+		$s = Piwik_Translate($message);
+	}
+	catch(Exception $e)
+	{
+		$s = null;
+	}
+	
+	if( $s == null )
+	{
+		$s = $message;
+	}
+	
+	return $s;		
+}
Index: modules/FrontController.php
===================================================================
--- modules/FrontController.php	(wersja 441)
+++ modules/FrontController.php	(kopia robocza)
@@ -29,6 +29,8 @@
 require_once "API/Proxy.php";
 require_once "Site.php";
 require_once "Translate.php";
+require_once "TranslateException.php";
+require_once "Mail.php";
 require_once "Url.php";
 require_once "Controller.php";
 
Index: modules/Translate.php
===================================================================
--- modules/Translate.php	(wersja 441)
+++ modules/Translate.php	(kopia robocza)
@@ -69,6 +69,54 @@
 			throw new Exception("The language selected ('$language') is not a valid language file ");
 		}
 	}
+	
+	/**
+	 * Generate javascript translations array
+	 * 
+	 * @return string containing javascript code with translations array (including <script> tag)
+	 *
+	 */
+	public function getJavascriptTranslations($moduleList)
+	{
+		if( !$moduleList )
+		{
+			return '';
+		}
+		// TODO: add {$PiwikUrl} to the following js include:
+		$js = '<script type="text/javascript" src="libs/javascript/sprintf.js" /></script>';
+		
+		$js .= '<script type="text/javascript">var translations = {';
+					
+		$moduleRegex = '#^(';
+		foreach($moduleList as $module)
+		{
+			$moduleRegex .= $module.'|'; 
+		}
+		$moduleRegex = substr($moduleRegex, 0, -1);
+		$moduleRegex .= ')_([^_]+)_js$#i';
+		
+		foreach($GLOBALS['Piwik_translations'] as $key => $value)
+		{
+			$matches = array();
+			
+			if( preg_match($moduleRegex,$key,$matches) ) {
+				$varName = $matches[1].'_'.$matches[2];
+				$varValue = $value;
+				
+				$js .= $varName. ": '".str_replace("'","\\'",$varValue)."',";
+			}
+			
+			$matches = null;
+		}
+		
+		$js .= '};';
+		$js .= 'function _pk_translate(tvar, str) { '.
+			'var s = translations[tvar] ? translations[tvar] : str;'.
+			'return sprintf(s, Array.prototype.slice.call(arguments).slice(2)); }';
+		$js .= '</script>';
+		
+		return $js;
+	}
 }
 
 function Piwik_Translate($index)
Index: modules/Mail.php
===================================================================
--- modules/Mail.php	(wersja 0)
+++ modules/Mail.php	(wersja 0)
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ * 
+ * @package Piwik
+ */
+
+require_once "Zend/Mail.php";
+
+/**
+ * Class for sending mails, for more information see: 
+ * http://framework.zend.com/manual/en/zend.mail.html 
+ *
+ * @package Piwik
+ */
+class Piwik_Mail extends Zend_Mail
+{
+	/**
+	 * Public constructor, default charset utf-8
+	 *
+	 * @param string $charset
+	 */
+	public function __construct($charset = 'utf-8')
+	{
+		parent::__construct($charset);
+	}
+}
Index: modules/Common.php
===================================================================
--- modules/Common.php	(wersja 441)
+++ modules/Common.php	(kopia robocza)
@@ -611,7 +611,32 @@
 		// at this point we really can't guess the country
 		return 'xx';
 	}
+	
+	
+	/**
+	 * Generate random string 
+	 *
+	 * @param string $length string length
+	 * @param string $alphabet characters allowed in random string
+	 *
+	 * @return string random string with given length
+	 */	
+	public static function getRandomString($length = 16, $alphabet = "abcdefghijklmnoprstuvwxyz0123456789")
+	{
+		$chars = $alphabet;
+		$str = '';
 
+		list($usec, $sec) = explode(" ", microtime());
+		$seed = ((float)$sec+(float)$usec)*100000;
+		mt_srand($seed);
+		
+		for($i = 0; $i < $length; $i++)
+		{
+			$rand_key = mt_rand(0, strlen($chars)-1);
+			$str  .= substr($chars, $rand_key, 1);
+		}
+		return str_shuffle($str);
+	}
 }
 
 

